@sema-agent/core 7.55.0 → 7.56.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 (418) hide show
  1. package/CHANGELOG.md +513 -0
  2. package/dist/agents/cascade.js +1 -1
  3. package/dist/agents/cc-peer-directory.js +1 -0
  4. package/dist/agents/child-model-seat.d.ts +0 -11
  5. package/dist/agents/child-model-seat.js +0 -3
  6. package/dist/agents/list-agents-tool.d.ts +3 -1
  7. package/dist/agents/list-agents-tool.js +7 -7
  8. package/dist/agents/peer-directory.d.ts +22 -4
  9. package/dist/agents/peer-directory.js +24 -2
  10. package/dist/agents/peer-session-drain.js +2 -2
  11. package/dist/agents/repair-loop.js +2 -2
  12. package/dist/agents/send-message-tool.js +4 -4
  13. package/dist/agents/subagent.d.ts +6 -4
  14. package/dist/agents/subagent.js +64 -60
  15. package/dist/agents/tool-filter.d.ts +7 -5
  16. package/dist/agents/tool-filter.js +12 -9
  17. package/dist/agents/verify.d.ts +3 -2
  18. package/dist/agents/verify.js +3 -3
  19. package/dist/brain/anthropic.js +30 -73
  20. package/dist/brain/media-degrade.d.ts +18 -7
  21. package/dist/brain/media-degrade.js +13 -2
  22. package/dist/brain/model-capability.d.ts +37 -0
  23. package/dist/brain/model-capability.js +34 -0
  24. package/dist/brain/model-presets.d.ts +2 -8
  25. package/dist/brain/model-presets.js +1 -6
  26. package/dist/brain/open-responses.js +13 -26
  27. package/dist/brain/openai.js +14 -87
  28. package/dist/brain/reasoning-request.d.ts +96 -0
  29. package/dist/brain/reasoning-request.js +174 -0
  30. package/dist/brain/reasoning.d.ts +11 -11
  31. package/dist/brain/reasoning.js +4 -3
  32. package/dist/brain/request-params.d.ts +7 -4
  33. package/dist/brain/request-params.js +7 -4
  34. package/dist/brain/status-sink.d.ts +20 -0
  35. package/dist/brain/status-sink.js +7 -0
  36. package/dist/core/a2a.d.ts +2 -1
  37. package/dist/core/a2a.js +19 -13
  38. package/dist/core/agent-definition.d.ts +10 -0
  39. package/dist/core/allow-entry.d.ts +20 -13
  40. package/dist/core/allow-entry.js +26 -22
  41. package/dist/core/allow-rule-shadow.d.ts +3 -3
  42. package/dist/core/ask-origin.d.ts +64 -18
  43. package/dist/core/ask-origin.js +63 -23
  44. package/dist/core/ask-question.d.ts +51 -8
  45. package/dist/core/ask-question.js +3 -4
  46. package/dist/core/ask-unresolvable-notice.d.ts +8 -3
  47. package/dist/core/ask-unresolvable-notice.js +16 -2
  48. package/dist/core/checkpoint-generation.d.ts +53 -0
  49. package/dist/core/checkpoint-generation.js +35 -0
  50. package/dist/core/checkpoint-queries.d.ts +180 -0
  51. package/dist/core/checkpoint-queries.js +272 -0
  52. package/dist/core/checkpoint-requirements.d.ts +13 -1
  53. package/dist/core/checkpoint-requirements.js +4 -0
  54. package/dist/core/checkpoint-store.d.ts +88 -24
  55. package/dist/core/checkpoint-store.js +24 -9
  56. package/dist/core/cross-boundary-taint.d.ts +6 -5
  57. package/dist/core/cross-boundary-taint.js +1 -3
  58. package/dist/core/decision-receipt.d.ts +37 -3
  59. package/dist/core/decision-receipt.js +17 -17
  60. package/dist/core/delegation-not-started.d.ts +6 -0
  61. package/dist/core/delegation-not-started.js +17 -0
  62. package/dist/core/engine-attestation.d.ts +93 -0
  63. package/dist/core/engine-attestation.js +70 -0
  64. package/dist/core/engine-capabilities.d.ts +4 -1
  65. package/dist/core/engine-capabilities.js +1 -1
  66. package/dist/core/engine-notice.d.ts +30 -11
  67. package/dist/core/file-history-store.d.ts +90 -14
  68. package/dist/core/file-history-store.js +23 -15
  69. package/dist/core/gate-fold.d.ts +1 -1
  70. package/dist/core/gate-fold.js +22 -10
  71. package/dist/core/gate-lanes.js +73 -64
  72. package/dist/core/gate-outcome.d.ts +26 -5
  73. package/dist/core/gate-outcome.js +26 -0
  74. package/dist/core/governance-codes.d.ts +5 -1
  75. package/dist/core/governance-codes.js +6 -0
  76. package/dist/core/hooks.d.ts +17 -16
  77. package/dist/core/hooks.js +3 -1
  78. package/dist/core/host-floor.d.ts +128 -0
  79. package/dist/core/host-floor.js +206 -0
  80. package/dist/core/host-target.d.ts +38 -3
  81. package/dist/core/host-target.js +38 -5
  82. package/dist/core/mcp.d.ts +5 -1
  83. package/dist/core/mcp.js +67 -41
  84. package/dist/core/memory-engine/delegation-settlement.js +15 -24
  85. package/dist/core/memory-engine/engine.js +4 -4
  86. package/dist/core/memory-engine/layout.d.ts +60 -8
  87. package/dist/core/memory-engine/layout.js +65 -6
  88. package/dist/core/model-seat.d.ts +10 -3
  89. package/dist/core/mods/classic-events.d.ts +67 -0
  90. package/dist/core/mods/classic-events.js +1 -0
  91. package/dist/core/mods/dollar.d.ts +13 -0
  92. package/dist/core/mods/extension-call.d.ts +31 -0
  93. package/dist/core/mods/extension-call.js +43 -0
  94. package/dist/core/mods/kernel/dispatch.d.ts +20 -3
  95. package/dist/core/mods/kernel/dispatch.js +140 -69
  96. package/dist/core/mods/kernel/events.d.ts +47 -11
  97. package/dist/core/mods/kernel/events.js +66 -42
  98. package/dist/core/mods/kernel/index.d.ts +4 -4
  99. package/dist/core/mods/kernel/index.js +2 -2
  100. package/dist/core/mods/kernel/receive.d.ts +39 -5
  101. package/dist/core/mods/kernel/receive.js +290 -17
  102. package/dist/core/mods/kernel/registration.d.ts +33 -2
  103. package/dist/core/mods/kernel/registration.js +6 -7
  104. package/dist/core/mods/kernel/site-rules.d.ts +44 -16
  105. package/dist/core/mods/kernel/site-rules.js +24 -42
  106. package/dist/core/mods/spec-seats.d.ts +69 -0
  107. package/dist/core/mods/spec-seats.js +114 -0
  108. package/dist/core/mods/stations.d.ts +28 -8
  109. package/dist/core/mods/stations.js +29 -13
  110. package/dist/core/mods/tool-call.d.ts +79 -0
  111. package/dist/core/mods/tool-call.js +152 -0
  112. package/dist/core/namespaced-rule-name.d.ts +32 -38
  113. package/dist/core/namespaced-rule-name.js +29 -36
  114. package/dist/core/parent-spec-seat.d.ts +6 -1
  115. package/dist/core/parent-spec-seat.js +2 -0
  116. package/dist/core/park-selfcheck.js +1 -0
  117. package/dist/core/permission-rule-consent.d.ts +19 -0
  118. package/dist/core/permission-rule-consent.js +116 -26
  119. package/dist/core/permission-rule-model.d.ts +14 -3
  120. package/dist/core/permission-rule-model.js +39 -24
  121. package/dist/core/permission-rule-org.d.ts +6 -2
  122. package/dist/core/permission-rule-org.js +7 -3
  123. package/dist/core/permission-rule-provider.d.ts +5 -2
  124. package/dist/core/permission-rule-provider.js +41 -11
  125. package/dist/core/permission-rule-store.d.ts +3 -2
  126. package/dist/core/permission-rule-store.js +11 -2
  127. package/dist/core/permission-rule-sync.js +3 -2
  128. package/dist/core/permission-rule-syntax.d.ts +5 -4
  129. package/dist/core/permission-rule-syntax.js +2 -2
  130. package/dist/core/permission-rules.d.ts +4 -4
  131. package/dist/core/permission-rules.js +11 -20
  132. package/dist/core/persisted-rule-arms.d.ts +2 -2
  133. package/dist/core/persisted-rule-arms.js +10 -12
  134. package/dist/core/principal-name.d.ts +20 -0
  135. package/dist/core/principal-name.js +22 -0
  136. package/dist/core/prompt-section-seat.js +4 -6
  137. package/dist/core/protocol-http-auth.d.ts +26 -5
  138. package/dist/core/protocol-http-auth.js +137 -4
  139. package/dist/core/retired-keys.d.ts +16 -0
  140. package/dist/core/retired-keys.js +16 -4
  141. package/dist/core/rewrite-rejudge.d.ts +60 -0
  142. package/dist/core/rewrite-rejudge.js +36 -0
  143. package/dist/core/roles.d.ts +28 -1
  144. package/dist/core/roles.js +31 -19
  145. package/dist/core/rule-lane-reads.d.ts +20 -15
  146. package/dist/core/rule-lane-reads.js +45 -17
  147. package/dist/core/rule-owner.d.ts +3 -3
  148. package/dist/core/rule-owner.js +3 -2
  149. package/dist/core/runner/announce-once-ledger.d.ts +14 -0
  150. package/dist/core/runner/announce-once-ledger.js +5 -0
  151. package/dist/core/runner/assemble-result.d.ts +1 -0
  152. package/dist/core/runner/assemble-result.js +1 -1
  153. package/dist/core/runner/call-hook-stations.d.ts +3 -2
  154. package/dist/core/runner/caller-roster.d.ts +16 -4
  155. package/dist/core/runner/caller-roster.js +33 -6
  156. package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
  157. package/dist/core/runner/capability-withheld-seat.js +24 -0
  158. package/dist/core/runner/classifier-ladder.d.ts +7 -9
  159. package/dist/core/runner/classifier-ladder.js +3 -3
  160. package/dist/core/runner/construction-doors.js +3 -0
  161. package/dist/core/runner/contracts.d.ts +28 -25
  162. package/dist/core/runner/cross-boundary-lane.d.ts +17 -13
  163. package/dist/core/runner/cross-boundary-lane.js +40 -27
  164. package/dist/core/runner/denial-limit-arms.d.ts +2 -2
  165. package/dist/core/runner/denial-limit-arms.js +1 -1
  166. package/dist/core/runner/file-history-request.d.ts +18 -0
  167. package/dist/core/runner/file-history-request.js +21 -13
  168. package/dist/core/runner/file-history-restore.d.ts +45 -0
  169. package/dist/core/runner/file-history-restore.js +46 -0
  170. package/dist/core/runner/gate-exit.d.ts +3 -3
  171. package/dist/core/runner/gate-exit.js +4 -3
  172. package/dist/core/runner/image.d.ts +7 -17
  173. package/dist/core/runner/image.js +9 -60
  174. package/dist/core/runner/permission-rule-lanes.d.ts +4 -4
  175. package/dist/core/runner/permission-rule-lanes.js +26 -10
  176. package/dist/core/runner/person-path-rows.d.ts +12 -9
  177. package/dist/core/runner/person-path-rows.js +18 -7
  178. package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
  179. package/dist/core/runner/prepare-ask-lane.js +5 -2
  180. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
  181. package/dist/core/runner/prepare-caps-and-workflow.js +4 -3
  182. package/dist/core/runner/prepare-config-doors.d.ts +29 -38
  183. package/dist/core/runner/prepare-config-doors.js +42 -25
  184. package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
  185. package/dist/core/runner/prepare-defer-classify.js +7 -8
  186. package/dist/core/runner/prepare-file-history.d.ts +48 -8
  187. package/dist/core/runner/prepare-file-history.js +7 -39
  188. package/dist/core/runner/prepare-gate-stations.d.ts +1 -1
  189. package/dist/core/runner/prepare-gate-stations.js +10 -1
  190. package/dist/core/runner/prepare-hands-readface.d.ts +2 -8
  191. package/dist/core/runner/prepare-hands-readface.js +15 -14
  192. package/dist/core/runner/prepare-inherited-gate.d.ts +6 -3
  193. package/dist/core/runner/prepare-inherited-gate.js +5 -3
  194. package/dist/core/runner/prepare-memory-engine-session.js +1 -1
  195. package/dist/core/runner/prepare-park-ask.js +5 -5
  196. package/dist/core/runner/prepare-policy-chain.d.ts +6 -3
  197. package/dist/core/runner/prepare-policy-chain.js +65 -72
  198. package/dist/core/runner/prepare-prompt-assembly.d.ts +5 -7
  199. package/dist/core/runner/prepare-prompt-assembly.js +10 -8
  200. package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
  201. package/dist/core/runner/prepare-prompt-inputs.js +3 -5
  202. package/dist/core/runner/prepare-protocol-tools.d.ts +2 -0
  203. package/dist/core/runner/prepare-protocol-tools.js +3 -3
  204. package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
  205. package/dist/core/runner/prepare-safety-scan.js +0 -17
  206. package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
  207. package/dist/core/runner/prepare-suspend-saga.js +5 -6
  208. package/dist/core/runner/prepare-task.d.ts +1 -1
  209. package/dist/core/runner/prepare-task.js +29 -20
  210. package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +7 -4
  211. package/dist/core/runner/prepare-tool-disclosure-mount.js +20 -16
  212. package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
  213. package/dist/core/runner/prepare-turn-wiring.js +2 -7
  214. package/dist/core/runner/prepare-wiring-manifest.d.ts +6 -2
  215. package/dist/core/runner/prepare-wiring-manifest.js +3 -3
  216. package/dist/core/runner/resume-admission.js +1 -1
  217. package/dist/core/runner/resume-apply.js +11 -12
  218. package/dist/core/runner/resume-checkpoint-screen.js +3 -0
  219. package/dist/core/runner/resume-claim.d.ts +4 -2
  220. package/dist/core/runner/resume-claim.js +15 -8
  221. package/dist/core/runner/retired-runner-deps.js +1 -0
  222. package/dist/core/runner/rewind-files.d.ts +15 -0
  223. package/dist/core/runner/rewind-files.js +132 -0
  224. package/dist/core/runner/run-attachment-seats.js +2 -1
  225. package/dist/core/runner/run-brain-sinks.d.ts +4 -1
  226. package/dist/core/runner/run-brain-sinks.js +4 -2
  227. package/dist/core/runner/run-harness-handlers.js +12 -4
  228. package/dist/core/runner/run-leg.d.ts +1 -1
  229. package/dist/core/runner/run-leg.js +30 -18
  230. package/dist/core/runner/run-settle-and-teardown.js +2 -1
  231. package/dist/core/runner/run-turn-boundary.js +1 -10
  232. package/dist/core/runner/runtask.d.ts +3 -0
  233. package/dist/core/runner/runtask.js +8 -9
  234. package/dist/core/runner/session-read-file-states.d.ts +15 -0
  235. package/dist/core/runner/session-read-file-states.js +28 -0
  236. package/dist/core/runner/session-rule-policy.js +4 -3
  237. package/dist/core/runner/shell-env-withheld.d.ts +33 -0
  238. package/dist/core/runner/shell-env-withheld.js +51 -0
  239. package/dist/core/runner/skills-seat.js +6 -2
  240. package/dist/core/runner/stream-settle-backstop.js +1 -1
  241. package/dist/core/runner/sub-agent-deny-lists.js +4 -7
  242. package/dist/core/runner/synthetic-tools.d.ts +6 -0
  243. package/dist/core/runner/synthetic-tools.js +4 -1
  244. package/dist/core/runner/tool-disclosure.d.ts +10 -12
  245. package/dist/core/runner/tool-disclosure.js +1 -3
  246. package/dist/core/runner/tool-end-body.d.ts +1 -1
  247. package/dist/core/runner/tool-end-body.js +10 -9
  248. package/dist/core/runner/tool-not-executed.d.ts +5 -0
  249. package/dist/core/runner/tool-not-executed.js +11 -0
  250. package/dist/core/runner/tool-occurrence.d.ts +8 -0
  251. package/dist/core/runner/tool-occurrence.js +7 -0
  252. package/dist/core/runner/turn-attachments.d.ts +33 -15
  253. package/dist/core/runner/turn-attachments.js +62 -37
  254. package/dist/core/runner-deps.d.ts +5 -5
  255. package/dist/core/safety-axis-vocab.d.ts +6 -4
  256. package/dist/core/safety-axis-vocab.js +6 -5
  257. package/dist/core/safety-merge-corpus.js +11 -3
  258. package/dist/core/secret-env.d.ts +26 -3
  259. package/dist/core/secret-env.js +44 -8
  260. package/dist/core/select-model.js +3 -3
  261. package/dist/core/session-policy-store.d.ts +27 -15
  262. package/dist/core/session-policy-store.js +156 -36
  263. package/dist/core/session-store.d.ts +29 -10
  264. package/dist/core/session-store.js +51 -19
  265. package/dist/core/session.d.ts +82 -16
  266. package/dist/core/session.js +53 -0
  267. package/dist/core/shell-read-silence.d.ts +11 -12
  268. package/dist/core/shell-read-silence.js +9 -5
  269. package/dist/core/shell-run-candidates.js +3 -1
  270. package/dist/core/shell-wrapper-projection.js +1 -1
  271. package/dist/core/shell-wrapper-table.d.ts +14 -7
  272. package/dist/core/shell-wrapper-table.js +5 -4
  273. package/dist/core/side-query.js +10 -1
  274. package/dist/core/skill-grant.d.ts +7 -2
  275. package/dist/core/skill-grant.js +5 -0
  276. package/dist/core/skills-directory.js +6 -2
  277. package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
  278. package/dist/core/store-contracts/checkpoint-store-contract.js +140 -2
  279. package/dist/core/store-contracts/file-history-store-contract.js +31 -1
  280. package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
  281. package/dist/core/store-contracts/peer-directory-contract.js +14 -2
  282. package/dist/core/store-contracts/session-repo-contract.js +51 -0
  283. package/dist/core/store-contracts/session-store-contract.d.ts +2 -1
  284. package/dist/core/store-contracts/session-store-contract.js +150 -14
  285. package/dist/core/stub-env.d.ts +2 -0
  286. package/dist/core/stub-env.js +1 -0
  287. package/dist/core/synthetic-read-verdict.js +3 -3
  288. package/dist/core/task-event.d.ts +32 -4
  289. package/dist/core/task-notification.d.ts +16 -12
  290. package/dist/core/task-registry.d.ts +9 -0
  291. package/dist/core/task-registry.js +11 -1
  292. package/dist/core/task-result.d.ts +18 -0
  293. package/dist/core/task-spec.d.ts +18 -13
  294. package/dist/core/tighten-task-spec.js +2 -1
  295. package/dist/core/tool-catalog-entries.d.ts +17 -0
  296. package/dist/core/tool-catalog-entries.js +13 -2
  297. package/dist/core/tool-check-reading.d.ts +11 -0
  298. package/dist/core/tool-check-reading.js +11 -6
  299. package/dist/core/tool-model-gate.d.ts +2 -2
  300. package/dist/core/tool-name-aliases.d.ts +16 -16
  301. package/dist/core/tool-name-aliases.js +13 -19
  302. package/dist/core/tool-name-readings.d.ts +5 -35
  303. package/dist/core/tool-name-readings.js +1 -9
  304. package/dist/core/tool-policy.d.ts +68 -198
  305. package/dist/core/tool-policy.js +149 -198
  306. package/dist/core/tool-result-store.js +3 -0
  307. package/dist/core/tool-roster.d.ts +14 -19
  308. package/dist/core/tool-roster.js +11 -44
  309. package/dist/core/tool-spec-members.js +7 -2
  310. package/dist/core/tool-spec.d.ts +19 -11
  311. package/dist/core/tools.js +49 -9
  312. package/dist/core/trace.d.ts +2 -2
  313. package/dist/core/types.d.ts +1 -1
  314. package/dist/core/user-attachment.d.ts +8 -1
  315. package/dist/core/user-attachment.js +64 -4
  316. package/dist/core/wiring-manifest.d.ts +9 -0
  317. package/dist/core/wiring-manifest.js +1 -0
  318. package/dist/core/workflow-journal-store.js +1 -1
  319. package/dist/engine/compaction/compaction.js +3 -2
  320. package/dist/engine/execution-env/node-execution-env.d.ts +7 -3
  321. package/dist/engine/execution-env/node-execution-env.js +11 -2
  322. package/dist/engine/harness/agent-harness.d.ts +25 -1
  323. package/dist/engine/harness/agent-harness.js +54 -7
  324. package/dist/engine/harness/types.d.ts +29 -2
  325. package/dist/engine/llm/types.d.ts +28 -11
  326. package/dist/engine/loop/agent-loop.d.ts +22 -0
  327. package/dist/engine/loop/agent-loop.js +16 -26
  328. package/dist/engine/loop/types.d.ts +16 -6
  329. package/dist/engine/session/memory-repo.d.ts +9 -2
  330. package/dist/engine/session/memory-repo.js +11 -1
  331. package/dist/engine/session/repo-utils.d.ts +6 -5
  332. package/dist/engine/session/repo-utils.js +14 -6
  333. package/dist/index.d.ts +22 -10
  334. package/dist/index.js +15 -7
  335. package/dist/internal/harness-types.d.ts +1 -1
  336. package/dist/internal/llm.d.ts +1 -1
  337. package/dist/orchestration/run-workflow-tool.d.ts +6 -4
  338. package/dist/orchestration/run-workflow-tool.js +5 -3
  339. package/dist/orchestration/workflow.d.ts +3 -0
  340. package/dist/orchestration/workflow.js +36 -18
  341. package/dist/prompt-assembly/artifact.d.ts +2 -2
  342. package/dist/prompt-assembly/artifact.js +5 -3
  343. package/dist/prompt-assembly/assemble.d.ts +3 -2
  344. package/dist/prompt-assembly/assemble.js +1 -1
  345. package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
  346. package/dist/prompt-assembly/catalog/schema.js +34 -2
  347. package/dist/prompt-assembly/catalog/sections.js +0 -1
  348. package/dist/prompt-assembly/composer.d.ts +3 -1
  349. package/dist/prompt-assembly/composer.js +1 -1
  350. package/dist/prompt-assembly/event-registry.js +1 -0
  351. package/dist/prompt-assembly/overlay.js +3 -3
  352. package/dist/prompt-assembly/renderers.d.ts +1 -1
  353. package/dist/prompt-assembly/renderers.js +0 -3
  354. package/dist/prompt-assembly/role-base.d.ts +15 -0
  355. package/dist/prompt-assembly/role-base.js +9 -0
  356. package/dist/prompt-assembly/select.d.ts +39 -14
  357. package/dist/prompt-assembly/select.js +47 -16
  358. package/dist/prompt-assembly/sugar.d.ts +17 -11
  359. package/dist/prompt-assembly/sugar.js +8 -3
  360. package/dist/prompt-assembly/tool-catalog.d.ts +37 -3
  361. package/dist/prompt-assembly/tool-catalog.js +114 -4
  362. package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
  363. package/dist/prompt-assembly/turn-snapshot.js +0 -3
  364. package/dist/prompt-assembly/types.d.ts +0 -7
  365. package/dist/scenarios/full-body.d.ts +11 -11
  366. package/dist/scenarios/full-body.js +4 -3
  367. package/dist/shell/lex.js +10 -1
  368. package/dist/stores/file/adoption/adopt.js +4 -3
  369. package/dist/stores/file/adoption/marker.js +3 -2
  370. package/dist/stores/file/checkpoint-store.d.ts +21 -0
  371. package/dist/stores/file/checkpoint-store.js +38 -6
  372. package/dist/stores/file/file-history-store.js +6 -7
  373. package/dist/stores/file/index.js +2 -1
  374. package/dist/stores/file/permission-rule-adopt.js +4 -3
  375. package/dist/stores/file/permission-rule-store.js +11 -5
  376. package/dist/stores/file/session-store.d.ts +29 -6
  377. package/dist/stores/file/session-store.js +42 -50
  378. package/dist/tools/artifact/artifact-tool.js +3 -2
  379. package/dist/tools/fs/bash-program-position.d.ts +19 -2
  380. package/dist/tools/fs/bash-program-position.js +56 -9
  381. package/dist/tools/fs/fs-bash.js +5 -5
  382. package/dist/tools/fs/fs-glob.d.ts +86 -0
  383. package/dist/tools/fs/fs-glob.js +226 -0
  384. package/dist/tools/fs/fs-read.js +14 -14
  385. package/dist/tools/fs/fs-search-tools.js +7 -7
  386. package/dist/tools/fs/pattern-kill-guard.d.ts +22 -0
  387. package/dist/tools/fs/pattern-kill-guard.js +397 -0
  388. package/dist/tools/fs/pdf.d.ts +9 -6
  389. package/dist/tools/fs/pdf.js +3 -3
  390. package/dist/tools/fs/program-read-model.d.ts +57 -7
  391. package/dist/tools/fs/program-read-model.js +11 -1
  392. package/dist/tools/fs/program-read-model.rows.js +78 -21
  393. package/dist/tools/fs/read-deny-home.js +3 -2
  394. package/dist/tools/fs/removal-targets.d.ts +17 -7
  395. package/dist/tools/fs/removal-targets.js +47 -20
  396. package/dist/tools/fs/search.d.ts +10 -0
  397. package/dist/tools/fs/search.js +20 -26
  398. package/dist/tools/fs/shell-read-argv.js +89 -12
  399. package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
  400. package/dist/tools/fs/shell-read-bindings.js +41 -0
  401. package/dist/tools/fs/shell-read-check.js +6 -19
  402. package/dist/tools/fs/shell-read-environment.d.ts +5 -1
  403. package/dist/tools/fs/shell-read-environment.js +3 -2
  404. package/dist/tools/fs/shell-read-establish.d.ts +15 -0
  405. package/dist/tools/fs/shell-read-establish.js +19 -20
  406. package/dist/tools/fs/shell-read-plan.js +24 -16
  407. package/dist/tools/fs/shell-read-start.d.ts +6 -1
  408. package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
  409. package/dist/tools/fs/shell-read-write-targets.js +2 -3
  410. package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
  411. package/dist/tools/fs/shell-reentry-text.js +40 -2
  412. package/dist/tools/todo.js +63 -63
  413. package/dist/tools/web.d.ts +19 -14
  414. package/dist/tools/web.js +38 -55
  415. package/package.json +1 -1
  416. package/test/export-surface.snapshot.json +143 -5
  417. package/wire-changes/core@7.56.0.json +3891 -0
  418. package/wire-changes/mods-kernel@7.56.0.json +303 -0
@@ -1,5 +1,4 @@
1
1
  import { snapshotActorAssertion } from "../../internal/llm.js";
2
- import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
3
2
  import { CheckpointError, remainingBudgetMicroUsd } from "../checkpoint-store.js";
4
3
  import { chainPolicyOnLeg, chainTopAnchors } from "./child-tree.js";
5
4
  import { mintHookInvocationIdentity } from "../hooks.js";
@@ -8,14 +7,15 @@ import { checkToolPolicyProjection, policyCannotAnswer, refuseOutOfContractDecis
8
7
  import { callFaceSeat, parkedCallFaceOf } from "../tool-roster.js";
9
8
  import { readCallTarget } from "../effective-path-target.js";
10
9
  import { inlineUntrusted } from "../untrusted-text.js";
11
- import { deepJsonEqual, describeSuppliedValue, mintDecideRecord } from "./decide-continuation.js";
10
+ import { describeSuppliedValue, mintDecideRecord } from "./decide-continuation.js";
11
+ import { editRewrittenSentence, readRejudge } from "../rewrite-rejudge.js";
12
12
  import { orgVerdictBeforeClaim } from "./permission-rule-lanes.js";
13
13
  import { chainCannotJudge } from "./call-hook-stations.js";
14
14
  import { thrownText } from "../thrown-value.js";
15
- import { wireOf } from "../tool-name-readings.js";
16
15
  import { judgeApprovalObject } from "../approval-object.js";
17
- import { SKILL_CONTENT_MAX_CHARS, SKILL_TOOL_NAME, normalizeSkills } from "./synthetic-tools.js";
18
- import { skillLoadReading } from "./skill-base-dir.js";
16
+ import { SKILL_TOOL_NAME, normalizeSkills, skillsThatLoad } from "./synthetic-tools.js";
17
+ import { readSkillsSeat } from "./skills-seat.js";
18
+ import { frozenSkillScopesOf } from "../mods/spec-seats.js";
19
19
  export async function resumeApply(input) {
20
20
  const { cp, config, internals, outcomeGate, wakeMessage, resumeSignal, recheckGovernanceWindow, plainReviewOutcome, plainParkOutcome, runner, effectiveDelegationFacts } = input;
21
21
  let plainPolicyOutcome = input.plainPolicyOutcome;
@@ -23,7 +23,7 @@ export async function resumeApply(input) {
23
23
  let legMods;
24
24
  if (outcomeGate === "wake" && wakeMessage !== undefined) {
25
25
  if (resumeSignal?.aborted !== true) {
26
- legMods = await admitLegMods({ spec: config, deps: runner.deps, sessionId: cp.sessionId });
26
+ legMods = await admitLegMods({ spec: config, deps: runner.deps, sessionId: cp.sessionId, skills: skillsThatLoad(readSkillsSeat(config.skills)), reopenedSkills: frozenSkillScopesOf(cp.state) });
27
27
  }
28
28
  if (legMods !== undefined && legMods.bus.hasHandlers("classic.UserPromptSubmit")) {
29
29
  const screenedMessage = wakeMessage;
@@ -75,7 +75,7 @@ export async function resumeApply(input) {
75
75
  });
76
76
  };
77
77
  if (plainPolicyOutcome?.decision === "allow" && cp.pendingAction.kind === "tool_approval") {
78
- const servedSkills = normalizeSkills(config.skills).filter((s) => skillLoadReading(s, SKILL_CONTENT_MAX_CHARS).loads);
78
+ const servedSkills = skillsThatLoad(normalizeSkills(config.skills));
79
79
  const claimed = judgeApprovalObject(cp.pendingAction, { args: plainPolicyOutcome.updatedInput ?? cp.pendingAction.args, skills: servedSkills, skillToolName: SKILL_TOOL_NAME }, "claim");
80
80
  if (claimed !== "match")
81
81
  throw new CheckpointError("checkpoint.invalid_outcome", claimed.message, { field: "boundGrantDigest" });
@@ -83,8 +83,7 @@ export async function resumeApply(input) {
83
83
  if (plainPolicyOutcome !== undefined &&
84
84
  plainPolicyOutcome.decision === "allow" &&
85
85
  plainPolicyOutcome.updatedInput !== undefined &&
86
- cp.pendingAction.kind === "tool_approval" &&
87
- wireOf("resume.editRecheckQuestionSkip", cp.pendingAction) !== ASK_USER_QUESTION_TOOL_NAME) {
86
+ cp.pendingAction.kind === "tool_approval") {
88
87
  const editedArgs = plainPolicyOutcome.updatedInput;
89
88
  const editBudget = {
90
89
  resourceRemainingMicroUsd: remainingBudgetMicroUsd(cp.resourceLedger),
@@ -148,9 +147,9 @@ export async function resumeApply(input) {
148
147
  }
149
148
  if (policyCannotAnswer(rechecked, plainPolicyOutcome.hostDecision.decidedBy))
150
149
  throw new CheckpointError("checkpoint.invalid_outcome", `the approver EDITED this call's input, the edited args raise a question that requires real approval, and the decision is the deployment's policy — a policy's answer is not a person's (decide the edit as "person", or approve the shown input); refusing pre-CAS, the checkpoint stays pending`, { field: "hostDecision" });
151
- if (rechecked.updatedInput !== undefined && !deepJsonEqual(rechecked.updatedInput, editedArgs)) {
152
- throw new CheckpointError("resume.constraint_rejected", `the deployment's resume-edit policy REWROTE the approver's edited args to a different value than was approved — the durable resume cannot execute either the un-adjudicated edit or an unapproved rewrite; ` +
153
- `refused pre-CAS (the checkpoint stays pending); re-submit the edited action so the rewrite is adjudicated and approved synchronously`);
150
+ const reread = readRejudge(editedReq, editedArgs, rechecked);
151
+ if (reread.kind === "rewritten") {
152
+ throw new CheckpointError("resume.constraint_rejected", `${editRewrittenSentence(cp.pendingAction.toolName)} (detail.editRewritten) — refused pre-CAS, the checkpoint stays pending and decidable`, { editRewritten: { acceptableForm: reread.form } });
154
153
  }
155
154
  }
156
155
  }
@@ -5,6 +5,7 @@ import { CHECKPOINT_FEATURES, CheckpointError, checkpointVersionOf, MAX_SUPPORTE
5
5
  import { judgeCheckpointRequirements } from "../checkpoint-requirements.js";
6
6
  import { constraintChainDigest, constraintChainEntryOfSuppliedLayer } from "../tool-policy.js";
7
7
  import { readFrozenSkillGrants } from "../skill-grant.js";
8
+ import { readFrozenSkillScopes } from "../mods/spec-seats.js";
8
9
  import { chainInstallationGaps, chainInstallationRefusal } from "./child-tree.js";
9
10
  import { screeningInstallationsOf, unraisableGuardsOf } from "../mods/stations.js";
10
11
  import { refusePersistedToolNames, refuseRenamedDelegationMounts } from "./sub-agent-deny-lists.js";
@@ -61,6 +62,8 @@ export function resumeCheckpointScreen(input) {
61
62
  }
62
63
  if (readFrozenSkillGrants(cp.state.skillGrants) === undefined)
63
64
  throw new CheckpointError("checkpoint.invalid_outcome", "this checkpoint carries a skill-grant section (state.skillGrants) that does not read as grant rows under this engine — a damaged section, or a row an earlier release wrote whose entry this release reads as nothing (an entry with a surrounding space, say) — refusing to resume without the grant rows and refusals it carries; the checkpoint stays pending: finish it on a worker of the release that parked it, or expire it", { reason: "skill_grants_damaged" });
65
+ if (readFrozenSkillScopes(cp.state.skillScopes) === undefined)
66
+ throw new CheckpointError("checkpoint.invalid_outcome", "this checkpoint carries a skill-scope section (state.skillScopes) that does not read as a list of SkillSpec names — a damaged section — refusing to resume without the active skills' hooks it records; the checkpoint stays pending: finish it on a worker of the release that parked it, or expire it", { reason: "skill_scopes_damaged" });
64
67
  for (const field of ["handsRoot", "handsHome", "handsCwd"]) {
65
68
  const coordinate = cp.state[field];
66
69
  if (coordinate !== undefined && validatePath(coordinate, { intent: "validate-coordinate" }) === undefined)
@@ -2,8 +2,8 @@
2
2
  * The resume ladder's CLAIM rung (E10), verbatim from `Runner.resumeStream`: the atomic
3
3
  * CAS (`claimTerminal` when the store provides it — one round trip carrying the loser's truth — else the
4
4
  * two-step `resolve` + diagnostic read), the same-Runner claim mark around it, and the loss classification
5
- * (`reopened_concurrently` for a live row whose rev moved, `already_resolved` for a consumed one, with the
6
- * dead parked-constraint entry evicted). Winning is the SOLE trigger to execute the pending action.
5
+ * (`reopened_concurrently` for a live row whose rev moved, `resume.holder_superseded` for the validated row a carried claim holder
6
+ * lost, `already_resolved` for a consumed one, with the dead parked-constraint entry evicted). Winning is the SOLE trigger to execute.
7
7
  *
8
8
  * Async (the CAS). It ends by handing off to the driver's post-claim rung (`next`) in its LAST continuation
9
9
  * — the post-consume hook fires on the tick the win was read — and returns what that rung returns.
@@ -19,6 +19,8 @@ export interface ResumeClaimInput<R> {
19
19
  store: CheckpointStore;
20
20
  /** borrowed-readonly — the twin the store persists as the resolved outcome. */
21
21
  outcomeForStore: ResumeRun["outcome"];
22
+ /** borrowed-readonly — the deployment's claim holder the resume acts under (`RunInternals.holder`), carried into the CAS. */
23
+ holder?: string | undefined;
22
24
  /** borrowed-mutable — the Runner's same-Runner claim marks: opened with the resolve attempt, released on a loss. */
23
25
  locallyClaimedTokens: Set<CheckpointToken>;
24
26
  /** borrowed-mutable — the Runner's parked-constraint registry: a terminally consumed token's entry is evicted. */
@@ -1,23 +1,30 @@
1
1
  import { CheckpointError } from "../checkpoint-store.js";
2
+ import { checkpointRevOf } from "../checkpoint-generation.js";
2
3
  export async function resumeClaim(input) {
3
- const { token, cp, store, outcomeForStore, locallyClaimedTokens, parentConstraintRegistry } = input;
4
+ const { token, cp, store, outcomeForStore, holder, locallyClaimedTokens, parentConstraintRegistry } = input;
5
+ const expect = { rev: checkpointRevOf(cp), ...(holder !== undefined ? { holder } : {}) };
4
6
  locallyClaimedTokens.add(token);
5
- let won;
6
- let claimLossStatus;
7
+ let won, loss;
7
8
  if (store.claimTerminal !== undefined) {
8
- const claim = await store.claimTerminal(token, cp.scope, { kind: "resolve", outcome: outcomeForStore, expect: { rev: cp.rev ?? 0 } });
9
+ const claim = await store.claimTerminal(token, cp.scope, { kind: "resolve", outcome: outcomeForStore, expect });
9
10
  won = claim.claimed;
10
11
  if (!claim.claimed)
11
- claimLossStatus = claim.current.status;
12
+ loss = { status: claim.current.status, rev: claim.current.status === "absent" ? undefined : claim.current.rev, sameRow: true };
12
13
  }
13
14
  else {
14
- won = await store.resolve(token, cp.scope, outcomeForStore, { rev: cp.rev ?? 0 });
15
+ won = await store.resolve(token, cp.scope, outcomeForStore, expect);
15
16
  }
16
17
  if (!won)
17
18
  locallyClaimedTokens.delete(token);
18
19
  if (!won) {
19
- const stillPending = claimLossStatus !== undefined ? claimLossStatus === "pending" : (await store.get(token))?.status === "pending";
20
- if (stillPending) {
20
+ if (loss === undefined) {
21
+ const row = await store.get(token);
22
+ loss = row ? { status: row.status, rev: checkpointRevOf(row), sameRow: row.scope === cp.scope } : { status: "absent", rev: undefined, sameRow: false };
23
+ }
24
+ if (loss.status === "pending") {
25
+ if (holder !== undefined && loss.sameRow && loss.rev === expect.rev) {
26
+ throw new CheckpointError("resume.holder_superseded", "the claim this resume acts under is no longer the deployment's current grant — nothing was applied and the checkpoint is unchanged by this resume; the run is superseded: do not retry it (the current holder delivers)");
27
+ }
21
28
  throw new CheckpointError("checkpoint.reopened_concurrently", "checkpoint changed concurrently (its revision advanced via a resolve/reopen cycle since this resume validated) — not executed; re-resume against the current state");
22
29
  }
23
30
  parentConstraintRegistry.delete(token);
@@ -7,6 +7,7 @@ const RETIRED_RUNNER_DEPS_KEYS = {
7
7
  graderEnvFactory: "the grader env reaches the repair loop as `RepairLoopConfig.graderEnv`, minted by the trusted control plane (`assertOracleIsolation` / `GraderEnv` unchanged)",
8
8
  "hands.readCyberReminder": "a Read result carries only the reminders about that read (an empty file, an offset past the end, a file already in context) — no standing content-safety tail, so there is nothing to switch; a deployment that wants that sentence states it in its own `appendSystemPrompt`",
9
9
  promptProvider: "a deployment changes prompt text through overlays: register a `prompt.compose` handler on `RunnerDeps.mods` answering `{ overlays }` (role base `replace`, a brand line `add` to the role band, a behavior or scenario `add`, a core-behavior `replace` / `append` / `drop`), choose the role base per task with `TaskSpec.promptRole`, and dispose of an MCP server's instructions with a `prompt.section` registration answering `{ text }` / `{ text: null }`",
10
+ allowImageUrl: "a remote image URL is judged by the one egress guard (https, the private-network floor) and the deployment's host floor — declare a CDN list as `RunnerDeps.hostFloor.only` (it bounds every structured egress: the fetch tool, task images, MCP http, A2A, WebSearch's SearXNG backend), or send the image inline",
10
11
  memorySessionIncarnation: "the occupant behind a session id is a cell of the session row now — `SessionMetadata.incarnation` on the metadata `Session.getMetadata()` returns (forks also `forkedFromIncarnation`), with `SessionStore.headOf` (its `incarnation`) for by-id readers; put the token the old seat answered on your sessions instead. A deployment that drops the seat without surfacing the cell loses the axis: records bind by session id alone",
11
12
  };
12
13
  export function assertNoRetiredRunnerDeps(deps) {
@@ -0,0 +1,15 @@
1
+ import type { RewindFilesRequest, RewindFilesResult } from "../file-history-store.js";
2
+ import type { SessionStore } from "../session.js";
3
+ import type { RunnerDeps } from "../types.js";
4
+ import type { SessionReadFileStates } from "./session-read-file-states.js";
5
+ /** What the Runner lends the rewind: its current deps, its session store, its read-state seats, and its lock. */
6
+ export interface RewindFilesSeats {
7
+ deps: RunnerDeps;
8
+ sessions: SessionStore;
9
+ readStates: SessionReadFileStates;
10
+ /** Whether a leg of this Runner holds or awaits `sessionId`'s lock. */
11
+ sessionBusy(sessionId: string): boolean;
12
+ /** Take `sessionId`'s lock; called synchronously after `sessionBusy` answered false, so nothing slips in between. */
13
+ takeSessionLock(sessionId: string): Promise<() => void>;
14
+ }
15
+ export declare function rewindSessionFiles(seats: RewindFilesSeats, request: RewindFilesRequest): Promise<RewindFilesResult>;
@@ -0,0 +1,132 @@
1
+ import { types } from "node:util";
2
+ import { isPlainRecord } from "../mods/kernel/receive.js";
3
+ import { hasDestroy } from "../remote-env.js";
4
+ import { readMember } from "../thrown-value.js";
5
+ import { resolveDeploymentFileHistory, storeUnconfiguredRefusal } from "./file-history-request.js";
6
+ import { prepareExecutionEnv } from "./prepare-execution-env.js";
7
+ import { noBoundaryRefusal, settleFileHistoryRestore } from "./file-history-restore.js";
8
+ import { adoptForkedFileHistory, resolveFileHistoryCoordinates } from "./prepare-file-history.js";
9
+ import { createRollbackStack } from "./rollback-stack.js";
10
+ import { settleTeardownLeg } from "./teardown-bounded.js";
11
+ const REQUEST_KEYS = new Set(["sessionId", "to", "dryRun", "signal"]);
12
+ export async function rewindSessionFiles(seats, request) {
13
+ const req = screenRewindFilesRequest(request);
14
+ const { deps } = seats;
15
+ const { wiredSeat, fileHistoryStore, captureStore } = resolveDeploymentFileHistory(deps);
16
+ if (fileHistoryStore === undefined)
17
+ throw storeUnconfiguredRefusal(wiredSeat, req.to);
18
+ if (seats.sessionBusy(req.sessionId))
19
+ throw sessionBusyRefusal(req.sessionId, req.to);
20
+ const lock = seats.takeSessionLock(req.sessionId);
21
+ const release = await lock;
22
+ try {
23
+ const session = await acquireExistingSession(seats.sessions, req.sessionId);
24
+ const report = (err) => {
25
+ try {
26
+ deps.onError?.(err, { phase: "config", sessionId: req.sessionId });
27
+ }
28
+ catch {
29
+ }
30
+ };
31
+ const rollback = createRollbackStack(report);
32
+ let envPhase;
33
+ try {
34
+ envPhase = await prepareExecutionEnv({ deps, spec: {}, internals: undefined, resume: undefined, placementRootResolved: req.sessionId, sessionId: req.sessionId, forgetOnThrow: async () => { }, rollback });
35
+ }
36
+ catch (err) {
37
+ await rollback.unwindAll();
38
+ throw err;
39
+ }
40
+ rollback.commit();
41
+ try {
42
+ return await rewindOnEnv(req, envPhase.executionEnv, envPhase.handsEnabled, envPhase.taskRootInitial, { store: fileHistoryStore, captureStore, session: session.session, seats });
43
+ }
44
+ finally {
45
+ const owned = envPhase.ownedEnvSeat.current;
46
+ if (owned !== undefined && hasDestroy(owned))
47
+ await settleTeardownLeg(() => owned.destroy(), "ownedEnv.destroy (rewindFiles)", report);
48
+ }
49
+ }
50
+ finally {
51
+ release();
52
+ }
53
+ }
54
+ async function rewindOnEnv(req, env, handsEnabled, taskRoot, ctx) {
55
+ if (!handsEnabled)
56
+ throw filesEnvUnsupportedRefusal(req.sessionId, req.to);
57
+ const { historyRoot, historyScope } = await resolveFileHistoryCoordinates(true, env, taskRoot, undefined, req.sessionId);
58
+ if (ctx.captureStore !== undefined)
59
+ await adoptForkedFileHistory(ctx.captureStore, ctx.session, req.sessionId, ctx.seats.deps.onError);
60
+ if (req.dryRun) {
61
+ if (!(await ctx.store.canRestore(historyScope, req.to)))
62
+ throw noBoundaryRefusal(req.to, req.sessionId, true);
63
+ const preview = ctx.store.diffStats === undefined ? null : await ctx.store.diffStats(historyScope, req.to, env, historyRoot);
64
+ return { dryRun: true, preview: preview ?? null };
65
+ }
66
+ const restore = await settleFileHistoryRestore({ store: ctx.store, sessionId: req.sessionId, target: req.to, before: false, env, root: historyRoot, signal: req.signal, readStates: ctx.seats.readStates });
67
+ return { dryRun: false, restore };
68
+ }
69
+ function screenRewindFilesRequest(request) {
70
+ const bad = (what) => {
71
+ const e = new Error(`Runner.rewindFiles: ${what} — nothing was rewound. The request is { sessionId, to, dryRun?, signal? }.`);
72
+ e.code = "rewind.invalid_spec";
73
+ throw e;
74
+ };
75
+ if (typeof request !== "object" || request === null)
76
+ return bad(`the request must be a plain object, got ${request === null ? "null" : typeof request}`);
77
+ if (types.isProxy(request) || !isPlainRecord(request))
78
+ return bad("the request must be a plain data object (not a Proxy, and with no prototype that could supply a member)");
79
+ let descriptors;
80
+ try {
81
+ descriptors = Object.getOwnPropertyDescriptors(request);
82
+ }
83
+ catch {
84
+ return bad("the request could not be read");
85
+ }
86
+ const keys = Reflect.ownKeys(descriptors);
87
+ const unknown = keys.filter((k) => typeof k !== "string" || !REQUEST_KEYS.has(k));
88
+ if (unknown.length > 0)
89
+ return bad(`unknown key ${unknown.map((k) => JSON.stringify(String(k))).join(", ")}`);
90
+ const read = {};
91
+ for (const k of keys) {
92
+ const d = descriptors[k];
93
+ if (!("value" in d))
94
+ return bad(`member ${JSON.stringify(k)} is an accessor, not a value`);
95
+ read[k] = d.value;
96
+ }
97
+ const { sessionId, to, dryRun, signal } = read;
98
+ if (typeof sessionId !== "string" || sessionId === "")
99
+ return bad(`sessionId must be a non-empty string, got ${shown(sessionId)}`);
100
+ if (typeof to !== "string" || to === "")
101
+ return bad(`to must be a non-empty entry id, got ${shown(to)}`);
102
+ if (dryRun !== undefined && typeof dryRun !== "boolean")
103
+ return bad(`dryRun must be a boolean when given, got ${shown(dryRun)}`);
104
+ if (signal !== undefined && !(signal instanceof AbortSignal))
105
+ return bad(`signal must be an AbortSignal when given, got ${shown(signal)}`);
106
+ return { sessionId, to, dryRun: dryRun === true, signal };
107
+ }
108
+ function shown(v) {
109
+ return typeof v === "string" ? JSON.stringify(v.slice(0, 40)) : v === null || typeof v === "boolean" || typeof v === "number" ? String(v) : `a ${typeof v}`;
110
+ }
111
+ async function acquireExistingSession(sessions, sessionId) {
112
+ try {
113
+ return await sessions.acquire(sessionId, { requireExisting: true });
114
+ }
115
+ catch (err) {
116
+ if (readMember(err, "code") !== "not_found")
117
+ throw err;
118
+ const e = new Error(`Runner.rewindFiles: session "${sessionId}" does not exist — nothing was rewound`);
119
+ e.code = "resume.session_not_found";
120
+ throw e;
121
+ }
122
+ }
123
+ function sessionBusyRefusal(sessionId, target) {
124
+ const e = new Error(`Runner.rewindFiles: a task is running or queued on session "${sessionId}" in this Runner — rewinding its files to entry "${target}" now would move them under that task, so nothing was rewound; retry once it has ended`);
125
+ e.code = "rewind.session_busy";
126
+ return e;
127
+ }
128
+ function filesEnvUnsupportedRefusal(sessionId, target) {
129
+ const e = new Error(`Runner.rewindFiles: this deployment mounts no filesystem-capable ExecutionEnv, so session "${sessionId}" has no working tree to rewind to entry "${target}" — nothing was rewound`);
130
+ e.code = "rewind.files_env_unsupported";
131
+ return e;
132
+ }
@@ -4,6 +4,7 @@ import { SKILLS_LISTING_PROBE_HEADER } from "./synthetic-tools.js";
4
4
  import { AGENT_LISTING_REMOVED_HEADER, SKILLS_LISTING_DELTA_HEADER, SKILLS_LISTING_REMOVED_HEADER, agentListingDeltaHeader, agentListingInitialHeader, createAttachmentState, replayAnnouncedListing, replayAnnouncedModels } from "./turn-attachments.js";
5
5
  import { wireOf } from "../tool-name-readings.js";
6
6
  import { rosterToolName } from "../tool-roster.js";
7
+ import { rowNotExecuted } from "./tool-not-executed.js";
7
8
  export async function runAttachmentSeats(input) {
8
9
  const { spec, prepared, resume, rs, runner, next } = input;
9
10
  rs.counters.wroteThisRun = false;
@@ -175,7 +176,7 @@ export async function runAttachmentSeats(input) {
175
176
  if ((fvMarked || text.includes("<system-reminder>[final verification]")) && rs.counters.finalVerifyInjections < 2)
176
177
  rs.counters.finalVerifyInjections += 1;
177
178
  }
178
- else if (m.role === "toolResult" && !rs.counters.wroteThisRun && (prepared.toolEffects.get(wireOf("verify.wroteThisRunSeed", { toolName: rosterToolName(prepared.toolRosterDeltas.current, m.toolName) })) ?? "write") !== "read") {
179
+ else if (m.role === "toolResult" && !rs.counters.wroteThisRun && !rowNotExecuted(m.details) && (prepared.toolEffects.get(wireOf("verify.wroteThisRunSeed", { toolName: rosterToolName(prepared.toolRosterDeltas.current, m.toolName) })) ?? "write") !== "read") {
179
180
  rs.counters.wroteThisRun = true;
180
181
  }
181
182
  }
@@ -3,6 +3,7 @@ import { type ExtraBodyDroppedSeatInput } from "./extra-body-dropped-seat.js";
3
3
  import type { PushQueue } from "../push-queue.js";
4
4
  import type { TaskEvent } from "../types.js";
5
5
  import type { RunInternals, RunState } from "./contracts.js";
6
+ import { type CapabilityWithheldRecord } from "./capability-withheld-seat.js";
6
7
  export interface RunBrainSinksInput {
7
8
  /** borrowed-mutable — the run's event queue: the `status` frames. */
8
9
  queue: PushQueue<TaskEvent>;
@@ -20,11 +21,13 @@ export interface RunBrainSinksInput {
20
21
  observeReasoningWireFacts: (facts: ReasoningWireFacts) => void;
21
22
  /** borrowed-readonly — the notice sink and the leg's ids; the fourth and fifth sinks' announcers are minted from them. */
22
23
  notice: ExtraBodyDroppedSeatInput;
24
+ /** borrowed-mutable — the session's announced record: the sixth sink's announcer says a withheld capability once per session. */
25
+ announced: CapabilityWithheldRecord;
23
26
  }
24
27
  export interface RunBrainSinksResult {
25
28
  /** Compose the three brain ALS sinks around a brain-driving call. */
26
29
  withBrainSinks: <T>(fn: () => Promise<T>) => Promise<T>;
27
- /** Compose the two leg-wide request sinks (the extraBody strip, the credential-origin refusal) around the whole leg. */
30
+ /** Compose the three leg-wide request sinks (the extraBody strip, the credential-origin refusal, the withheld capability) around the whole leg. */
28
31
  withLegRequestSinks: <T>(fn: () => Promise<T>) => Promise<T>;
29
32
  }
30
33
  export declare function runBrainSinks(input: RunBrainSinksInput): RunBrainSinksResult;
@@ -3,8 +3,9 @@ import { createExtraBodyDroppedScope } from "./extra-body-dropped-seat.js";
3
3
  import { createCredentialOriginRefusalScope } from "./credential-origin-seat.js";
4
4
  import { createSafeNotifier, observeThenableRejection } from "../safe-notify.js";
5
5
  import { emitTrace } from "../trace.js";
6
+ import { createCapabilityWithheldScope } from "./capability-withheld-seat.js";
6
7
  export function runBrainSinks(input) {
7
- const { queue, internals, rs, ident, observeReasoningWireFacts, notice } = input;
8
+ const { queue, internals, rs, ident, observeReasoningWireFacts, notice, announced } = input;
8
9
  const statusSinkNotifier = createSafeNotifier({
9
10
  onError: (f) => console.warn(`[sema-core] ${f.site}: run-internals status sink threw (contained; further failures counted, not re-disclosed): ${f.error.message}`),
10
11
  });
@@ -63,6 +64,7 @@ export function runBrainSinks(input) {
63
64
  const withBrainSinks = (fn) => runWithStatusSink(statusEmit, () => runWithBrainTelemetry(telemetryEmit, () => runWithReasoningWireFacts(observeReasoningWireFacts, fn)));
64
65
  const withExtraBodyDropped = createExtraBodyDroppedScope(notice);
65
66
  const withCredentialOriginRefusals = createCredentialOriginRefusalScope(notice);
66
- const withLegRequestSinks = (fn) => withExtraBodyDropped(() => withCredentialOriginRefusals(fn));
67
+ const withCapabilityWithheld = createCapabilityWithheldScope(notice, announced);
68
+ const withLegRequestSinks = (fn) => withExtraBodyDropped(() => withCredentialOriginRefusals(() => withCapabilityWithheld(fn)));
67
69
  return { withBrainSinks, withLegRequestSinks };
68
70
  }
@@ -11,11 +11,13 @@ import { advanceCadenceClock, reduceToolEnd } from "./turn-attachments.js";
11
11
  import { gatedCallIdOf } from "./park-commit.js";
12
12
  import { hasVerifiableStructureSignal } from "./grounding-signal.js";
13
13
  import { announceToolCall, batchResponseDigest, emitSettled } from "./tool-end-body.js";
14
- import { stampRowNotExecuted } from "./tool-not-executed.js";
14
+ import { neverExecuted, stampRowNotExecuted } from "./tool-not-executed.js";
15
+ import { extensionCallOf, noteExtensionCallDenied, requesterOf } from "../mods/extension-call.js";
15
16
  import { createResponseModelSeat } from "./response-model-seat.js";
16
17
  import { createToolCallIdFoldSeat } from "./tool-call-id-fold-seat.js";
17
18
  import { createFinishReasonSeat } from "./finish-reason-seat.js";
18
19
  import { createToolTurnIncompleteSeat } from "./tool-turn-repair-seat.js";
20
+ import { createWithheldShellEnvSeat } from "./shell-env-withheld.js";
19
21
  import { wireOf } from "../tool-name-readings.js";
20
22
  import { rosterToolName } from "../tool-roster.js";
21
23
  export function createHarnessHandlers(input) {
@@ -24,11 +26,12 @@ export function createHarnessHandlers(input) {
24
26
  const toolCallIdFoldSeat = createToolCallIdFoldSeat(deps.runnerHooks.onNotice, { sessionId: prepared.sessionId, runId: prepared.runId });
25
27
  const toolTurnIncompleteSeat = createToolTurnIncompleteSeat(deps.runnerHooks.onNotice, { sessionId: prepared.sessionId, runId: prepared.runId });
26
28
  const finishReasonSeat = createFinishReasonSeat(deps.runnerHooks.onNotice, { sessionId: prepared.sessionId, runId: prepared.runId });
29
+ const withheldShellEnvSeat = createWithheldShellEnvSeat(prepared, deps.runnerHooks.onNotice);
27
30
  const { spec, queue, internals, ident, pushContent, emitCommitted, startedToolCallIds, toolStartAt, toolProgress, writeFamilyOf, toolLabels, postToolBatchArmed, batchArgs, internalsNotifier, mediaByteCapBytes } = deps;
28
31
  const frames = { push: (f) => pushContent({ ...f, ...ident() }), structured: prepared.structuredProjector, mediaByteCapBytes };
29
32
  const startOf = (e) => {
30
33
  const label = toolLabels.get(e.toolName);
31
- return { toolCallId: e.toolCallId, spelledName: e.toolName, wireName: rosterToolName(prepared.toolRosterDeltas.current, e.toolName), ...(label !== undefined ? { label } : {}), args: e.args };
34
+ return { toolCallId: e.toolCallId, spelledName: e.toolName, wireName: rosterToolName(prepared.toolRosterDeltas.current, e.toolName), ...(label !== undefined ? { label } : {}), args: e.args, ...requesterOf(prepared.modBus, e.toolCallId) };
32
35
  };
33
36
  let lastWorkspaceCwd = prepared.cwdRef?.current;
34
37
  const announceWorkspaceMove = () => {
@@ -222,12 +225,15 @@ export function createHarnessHandlers(input) {
222
225
  const activityArg = primaryActivityArg(event.args);
223
226
  internalsNotifier.notify(() => observeThenableRejection(internals?.onActivity?.({ phase: "start", toolCallId: event.toolCallId, toolName: event.toolName, at: startAt, ...(activityArg !== undefined ? { arg: activityArg } : {}) }), internalsNotifier, "runtask.onActivity.start"), "runtask.onActivity.start");
224
227
  announceToolCall(prepared.toolOccurrences, startOf(event), frames);
228
+ withheldShellEnvSeat.onToolStart(event.toolName);
225
229
  };
226
230
  const onToolEnd = (event) => {
227
231
  const toolStarted = toolStartAt.get(event.toolCallId);
228
232
  toolStartAt.delete(event.toolCallId);
229
233
  const toolNow = Date.now();
230
- if (!rs.counters.wroteThisRun && (prepared.toolEffects.get(wireOf("verify.wroteThisRun", { toolName: rosterToolName(prepared.toolRosterDeltas.current, event.toolName) })) ?? "write") !== "read") {
234
+ const occ = prepared.toolOccurrences.get(event.toolCallId);
235
+ const ran = event.notExecuted !== true && !(occ !== undefined && neverExecuted(occ));
236
+ if (ran && !rs.counters.wroteThisRun && (prepared.toolEffects.get(wireOf("verify.wroteThisRun", { toolName: rosterToolName(prepared.toolRosterDeltas.current, event.toolName) })) ?? "write") !== "read") {
231
237
  rs.counters.wroteThisRun = true;
232
238
  }
233
239
  if (rs.attach.attachState !== undefined && !event.isError) {
@@ -236,7 +242,7 @@ export function createHarnessHandlers(input) {
236
242
  reduceToolEnd(rs.attach.attachState, det);
237
243
  }
238
244
  if (postToolBatchArmed) {
239
- if (prepared.blockedToolCalls.delete(event.toolCallId) || event.notExecuted === true) {
245
+ if (prepared.blockedToolCalls.delete(event.toolCallId) || !ran || extensionCallOf(prepared.modBus, event.toolCallId) !== undefined) {
240
246
  batchArgs?.delete(event.toolCallId);
241
247
  }
242
248
  else {
@@ -266,6 +272,8 @@ export function createHarnessHandlers(input) {
266
272
  ...(event.notExecuted === true ? { notExecuted: true } : {}),
267
273
  ...(() => { const id = prepared.abortController.signal.aborted ? gatedCallIdOf(prepared) : undefined; return id !== undefined ? { gatedCallIdOfRun: id } : {}; })(),
268
274
  }, frames);
275
+ if (settled.gate?.disposition.kind === "denied")
276
+ noteExtensionCallDenied(prepared.modBus, event.toolCallId);
269
277
  stampRowNotExecuted(event.result, settled.notExecuted === true);
270
278
  emitTrace(rs.telemetry.tracer, () => ({
271
279
  kind: "tool.call",
@@ -82,7 +82,7 @@ export interface RunLegInput<R> {
82
82
  unsubBoundary: () => void;
83
83
  /** borrowed-readonly — the git lane's harness-event release, called third. */
84
84
  unsub: () => void;
85
- /** borrowed-readonly — the Runner's deployment deps, read LIVE (`onError`, `hooks`, `onNotice`, `allowImageUrl`, `mediaByteCapBytes`; the resumed
85
+ /** borrowed-readonly — the Runner's deployment deps, read LIVE (`onError`, `hooks`, `onNotice`, `mediaByteCapBytes`; the resumed
86
86
  * decision's resolver files its execution record's word through `onNotice` too); the one home of why it is a seat and not a
87
87
  * captured object is {@link RunnerDepsSeat}. */
88
88
  runner: RunnerDepsSeat;
@@ -1,6 +1,6 @@
1
1
  import { snapshotActorAssertion } from "../../internal/llm.js";
2
2
  import { redactThenCut } from "../../agents/subagent-steps.js";
3
- import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
3
+ import { isEngineQuestionFace } from "../ask-question.js";
4
4
  import { CheckpointError, readPendingSteerQueue, realApprovalOrgFact, remainingBudgetMicroUsd } from "../checkpoint-store.js";
5
5
  import { normalizePersistedRuleHit } from "../rule-lane-reads.js";
6
6
  import { decidersNote, SETTLEMENT_NOBODY_JUDGED } from "../gate-outcome.js";
@@ -21,7 +21,7 @@ import { hasDestroy } from "../remote-env.js";
21
21
  import { advertisedWritableRootsSeat, attestationOf, exemptRootsSeat, humanRefusalSentence, licenseCovers, ownedReading, policyCannotAnswer, policyRefusalMessage, refuseOutOfContractDecision } from "../tool-policy.js";
22
22
  import { failedJudgmentDeny } from "./policy-throw.js";
23
23
  import { pathDenialCardOf } from "../../tools/fs/safety.js";
24
- import { callFaceSeat, parkedRowLiveFace, rosterEntryNamed } from "../tool-roster.js";
24
+ import { callFaceSeat, parkedRowLiveFace, rosterEntryNamed, rowMember } from "../tool-roster.js";
25
25
  import { deliverEngineNotice } from "../types.js";
26
26
  import { delimitUntrusted, inlineUntrusted, REVIEWER_NOTE_MAX_BODY, sanitizeUntrustedText } from "../untrusted-text.js";
27
27
  import { errorCodeOf } from "./terminal-account.js";
@@ -29,7 +29,8 @@ import { DEFAULT_PRECALL_OUTPUT_TOKENS, platformLimitTerminal } from "./clock-an
29
29
  import { legContextOverlayOption } from "./compaction-call-options.js";
30
30
  import { mintOutputStyleReminder, owedPostureText } from "./compaction-restate.js";
31
31
  import { advisorFrameText, registerAdvisorReceipt } from "./advisor-instructions.js";
32
- import { deepJsonEqual, resumeContinuation } from "./decide-continuation.js";
32
+ import { resumeContinuation } from "./decide-continuation.js";
33
+ import { editRewrittenSentence, sameBytes } from "../rewrite-rejudge.js";
33
34
  import { approvalWordsOf, owedApprovalWords, withApprovalWords } from "./approval-feedback.js";
34
35
  import { chainCannotJudge } from "./call-hook-stations.js";
35
36
  import { settleExecutionRecord } from "./execution-record.js";
@@ -46,12 +47,11 @@ import { settleTeardownLeg } from "./teardown-bounded.js";
46
47
  import { announceToolCall, emitSettled, toolResultMsg } from "./tool-end-body.js";
47
48
  import { rowDetailsOf, withRowNotExecuted } from "./tool-not-executed.js";
48
49
  import { announceListingTruncation } from "../skill-listing-budget.js";
49
- import { attachmentEnvelopeTags, collectDateChange, commitAgentListing, commitSkillsListing, reduceToolEnd, renderAgentListingFrame, renderOrphanedBackgroundTasks, renderSkillsListingFrame, stampWriteAnchor } from "./turn-attachments.js";
50
- import { flushOwedAnnouncedSnapshot } from "./announce-once-ledger.js";
50
+ import { attachmentEnvelopeTags, collectDateChange, commitAgentListing, commitSkillsListing, owedMcpUnavailable, reduceToolEnd, renderAgentListingFrame, renderOrphanedBackgroundTasks, renderSkillsListingFrame, stampWriteAnchor } from "./turn-attachments.js";
51
+ import { flushOwedAnnouncedSnapshot, settleMcpUnavailable } from "./announce-once-ledger.js";
51
52
  import { thrownMarksOf } from "../thrown-value.js";
52
53
  import { egressThrownText, egressValue } from "../untrusted-egress.js";
53
54
  import { ruleSourcePhrase } from "../rule-denial-sentence.js";
54
- import { wireOf } from "../tool-name-readings.js";
55
55
  export async function runLeg(input) {
56
56
  const { spec, queue, prepared, resume, rs, entryActor, effectiveTimeoutMs, timeout, pushContent, ident, emitCommitted, writeFamilyOf, startedToolCallIds, announceWorkspaceMove, withBrainSinks, flushGitMirror, loopLatch, notificationLane, unsubscribeTaskNotifications, unsubGitRetry, unsubBoundary, unsub, runner, next } = input;
57
57
  let final;
@@ -164,6 +164,9 @@ export async function runLeg(input) {
164
164
  const outputStyleWrapped = mintOutputStyleReminder(prepared);
165
165
  if (outputStyleWrapped !== undefined)
166
166
  continuation += "\n\n" + outputStyleWrapped;
167
+ const unavailableResume = owedMcpUnavailable(prepared, rs.attach.attachmentsCfg);
168
+ if (unavailableResume !== undefined)
169
+ continuation += "\n\n" + mintSystemReminder(sanitizeUntrustedText(unavailableResume.body, attachmentEnvelopeTags("mcp_unavailable")), prepared.reminderMark);
167
170
  const advisorResumeFrame = advisorFrameText(prepared);
168
171
  if (advisorResumeFrame !== undefined)
169
172
  continuation += "\n\n" + advisorResumeFrame;
@@ -279,6 +282,8 @@ export async function runLeg(input) {
279
282
  }
280
283
  if (postureText !== undefined)
281
284
  prepared.frameReceipts.pending.push({ source: "posture", text: continuation, commit: () => undefined });
285
+ if (unavailableResume !== undefined)
286
+ prepared.frameReceipts.pending.push({ source: "mcp_unavailable", text: continuation, commit: () => void (settleMcpUnavailable(prepared, unavailableResume.entries), queue.push({ type: "steering_injected", source: "mcp_unavailable", preview: redactThenCut(unavailableResume.body, 220), ...ident() }), (rs.attach.attachmentsInjected += 1)) });
282
287
  if (approvalFrames.length > 0) {
283
288
  prepared.frameReceipts.pending.push({
284
289
  source: "approval_feedback",
@@ -361,6 +366,9 @@ export async function runLeg(input) {
361
366
  const dateFrame = legToday !== undefined ? collectDateChange(rs.attach.dateState, legToday) : undefined;
362
367
  if (dateFrame !== undefined)
363
368
  firstFrames.push({ source: "date_change", body: dateFrame.body, commit: () => void (rs.attach.dateState.announcedDate = legToday), disclose: () => undefined });
369
+ const unavailable = owedMcpUnavailable(prepared, rs.attach.attachmentsCfg);
370
+ if (unavailable !== undefined)
371
+ firstFrames.push({ source: "mcp_unavailable", body: unavailable.body, commit: () => settleMcpUnavailable(prepared, unavailable.entries), disclose: () => undefined });
364
372
  if (rs.attach.attachState !== undefined) {
365
373
  const attach = rs.attach.attachState;
366
374
  if (rs.attach.agentListingOn && prepared.agentListing !== undefined) {
@@ -450,7 +458,7 @@ export async function runLeg(input) {
450
458
  }
451
459
  else {
452
460
  const images = spec.images
453
- ? await Promise.all(spec.images.map((img) => toImageContent(img, runner.deps.allowImageUrl)))
461
+ ? await Promise.all(spec.images.map((img) => toImageContent(img, prepared.hostFloor)))
454
462
  : undefined;
455
463
  if (gitLegDelivered !== undefined) {
456
464
  const delivered = gitLegDelivered;
@@ -570,7 +578,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
570
578
  const { outcome } = resume;
571
579
  if (pendingAction.kind !== "tool_approval" || outcome.gate !== "policy_ask")
572
580
  return;
573
- const mounted = () => { const tool = prepared.tools.find((x) => x.name === pendingAction.toolName); const roster = prepared.toolRosterDeltas.current; return tool === undefined || roster === undefined ? {} : { tool, entry: rosterEntryNamed(roster, pendingAction.toolName) }; };
581
+ const mounted = () => { const roster = prepared.toolRosterDeltas.current; const entry = roster === undefined ? undefined : rosterEntryNamed(roster, pendingAction.toolName); const tool = entry?.name === pendingAction.toolName ? rowMember(entry) : undefined; return tool === undefined ? {} : { tool, entry }; };
574
582
  const reopen = (miss) => { throw Object.assign(new Error(miss.message), { code: miss.code }); };
575
583
  const liveTool = mounted().tool;
576
584
  const atSession = outcome.decision === "allow" ? judgeApprovalObject(pendingAction, { tool: mounted().entry }, "session") : "match";
@@ -580,7 +588,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
580
588
  if (decidedGate === undefined) {
581
589
  throw new CheckpointError("checkpoint.invalid_outcome", "pending action reached the resolver with no settlement record on its decision (gateOutcome) — refusing to execute or settle a decision that carries no record");
582
590
  }
583
- const humanRewrite = wireOf("resume.questionArgsShown", pendingAction) === ASK_USER_QUESTION_TOOL_NAME ? undefined : outcome.updatedInput;
591
+ const humanRewrite = isEngineQuestionFace(parkedRowLiveFace(prepared.toolRosterDeltas.current, pendingAction)) ? undefined : outcome.updatedInput;
584
592
  const reading = liveTool === undefined ? undefined : ownedReading((a) => readToolCallArguments(liveTool, { type: "toolCall", id: pendingAction.toolCallId, name: pendingAction.toolName, arguments: {} }, a));
585
593
  const beltFace = () => { const f = parkedRowLiveFace(prepared.toolRosterDeltas.current, pendingAction); if (f !== undefined && reading !== undefined)
586
594
  stampArgsReading(f, reading); return f; };
@@ -652,9 +660,14 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
652
660
  emitCommitted(await prepared.session.appendMessage(resultRow(hookDenial, true)), "toolResult", pendingAction.toolCallId);
653
661
  return;
654
662
  }
655
- const rescreened = humanRewrite === undefined && screened !== undefined ? tryRead(screened.args) : undefined;
663
+ const rescreened = screened !== undefined ? tryRead(screened.args) : undefined;
656
664
  if (rescreened?.unread !== undefined)
657
665
  return settleUnreadable(rescreened.unread.error, "the arguments a PreToolUse hook rewrote it to");
666
+ if (humanRewrite !== undefined && rescreened !== undefined && !sameBytes({}, resolvedArgs, rescreened.args)) {
667
+ const text = formatHookFeedback(`${editRewrittenSentence(pendingAction.toolName)}, which a PreToolUse hook wrote — this approval is spent; the call has to be re-issued.`, prepared.reminderMark);
668
+ await settleEnd(true, { content: text, details: { editRewritten: { acceptableForm: rescreened.args } } }, "hook");
669
+ return emitCommitted(await prepared.session.appendMessage(resultRow(text, true)), "toolResult", pendingAction.toolCallId);
670
+ }
658
671
  const executedArgs = rescreened !== undefined ? rescreened.args : resolvedArgs;
659
672
  const unseen = !licenseCovers(pendingAction.boundInputHash, executedArgs);
660
673
  let beltReading;
@@ -687,19 +700,18 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
687
700
  if (unseen && prepared.basePolicyForResumeEdit) {
688
701
  const rechecked = refuseOutOfContractDecision(await beltCheck((signal) => prepared.basePolicyForResumeEdit.check(beltReq(), signal), "the deployment's tool policy re-checking a resumed call"));
689
702
  const personUnanswered = policyCannotAnswer(rechecked, outcome.hostDecision.decidedBy);
690
- const beltUnsafe = rechecked.action === "deny" ||
691
- (rechecked.updatedInput !== undefined && ((read) => read.unread !== undefined || !deepJsonEqual(read.args, executedArgs))(tryRead(rechecked.updatedInput))) ||
692
- personUnanswered;
693
- if (beltUnsafe) {
703
+ const rewrite = rechecked.updatedInput !== undefined ? tryRead(rechecked.updatedInput) : undefined;
704
+ const rewrote = rewrite !== undefined && (rewrite.unread !== undefined || !sameBytes({}, rewrite.args, executedArgs));
705
+ if (rechecked.action === "deny" || rewrote || personUnanswered) {
694
706
  const why = rechecked.action === "deny"
695
707
  ? (rechecked.message ? `: ${rechecked.message}` : "")
696
708
  : personUnanswered
697
709
  ? " (the call as it would run requires a person's approval, and this decision was the deployment's policy)"
698
710
  : " (the policy rewrote these bytes to a value that was not approved)";
699
711
  const editedDenial = formatHookFeedback(`${outcome.updatedInput !== undefined ? "The approver EDITED this call's input; the edited call" : "A PreToolUse hook REWROTE this approved call's input; the rewritten call"} is refused by the deployment's tool policy and was not executed${why}.`, prepared.reminderMark);
700
- await settleEnd(true, { content: editedDenial, ...denialCard(rechecked) }, "policy");
701
- const eid = await prepared.session.appendMessage(resultRow(editedDenial, true));
702
- emitCommitted(eid, "toolResult", pendingAction.toolCallId);
712
+ const outlet = rechecked.action !== "deny" && !personUnanswered && humanRewrite !== undefined && rewrite?.unread === undefined && rewrite !== undefined ? { details: { editRewritten: { acceptableForm: rewrite.args } } } : denialCard(rechecked);
713
+ await settleEnd(true, { content: editedDenial, ...outlet }, "policy");
714
+ emitCommitted(await prepared.session.appendMessage(resultRow(editedDenial, true)), "toolResult", pendingAction.toolCallId);
703
715
  return;
704
716
  }
705
717
  }
@@ -841,7 +853,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
841
853
  const finalize = (executed) => prepared.harness.finalizeToolCall({ type: "toolCall", id: pendingAction.toolCallId, name: spelledName, arguments: executedArgs }, executedArgs, executed);
842
854
  let res;
843
855
  try {
844
- res = await tool.execute(pendingAction.toolCallId, args, prepared.abortController.signal);
856
+ res = await (prepared.toolCallStation ?? ((_c, run) => run()))({ toolCallId: pendingAction.toolCallId, toolName: tool.name, args }, () => tool.execute(pendingAction.toolCallId, args, prepared.abortController.signal), prepared.abortController.signal);
845
857
  }
846
858
  catch (err) {
847
859
  const execError = `Error: ${egressThrownText("same-principal", err)}`;
@@ -96,6 +96,7 @@ export async function runSettleAndTeardown(input) {
96
96
  editedFiles: prepared.editedFilesSnapshot(),
97
97
  haltedOnUserRejection: prepared.batchHaltRef.current !== undefined,
98
98
  haltConsumption: prepared.harness.haltConsumption(),
99
+ answerEntryIds: prepared.harness.answerEntryIdsOf(final),
99
100
  strandedHumanAnswers,
100
101
  remoteEnvFailures: prepared.remoteEnvFailures,
101
102
  effectiveReadFace: prepared.effectiveReadFace,
@@ -283,7 +284,7 @@ export async function runSettleAndTeardown(input) {
283
284
  if (writeDateAnchor !== undefined)
284
285
  await settleTeardownLeg(writeDateAnchor, "date anchor (settle leg)", (e) => runner.deps.onError?.(e, { phase: "degraded", sessionId: prepared.sessionId }));
285
286
  if (prepared.crossBoundary !== undefined)
286
- await prepared.crossBoundary.settle();
287
+ await prepared.crossBoundary.settle(() => defaultTaskRegistry.owedDeliveries({ ...prepared.registryAccess, sessionId: prepared.sessionId }));
287
288
  const ownedEnvDying = prepared.ownedEnv !== undefined &&
288
289
  hasDestroy(prepared.ownedEnv) &&
289
290
  isIsolated(prepared.ownedEnv) &&