@sema-agent/core 7.48.0 → 7.49.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 +418 -0
  2. package/README.md +2 -2
  3. package/dist/agents/cascade.d.ts +2 -5
  4. package/dist/agents/child-failure.d.ts +20 -0
  5. package/dist/agents/child-failure.js +28 -0
  6. package/dist/agents/cross-session-ref.d.ts +11 -3
  7. package/dist/agents/cross-session-ref.js +6 -0
  8. package/dist/agents/cumulative-stats.d.ts +12 -15
  9. package/dist/agents/cumulative-stats.js +1 -1
  10. package/dist/agents/extra-tool-names.js +1 -1
  11. package/dist/agents/inherited-tool-pool.d.ts +17 -13
  12. package/dist/agents/inherited-tool-pool.js +4 -3
  13. package/dist/agents/peer-session-drain.d.ts +3 -2
  14. package/dist/agents/peer-session-drain.js +5 -4
  15. package/dist/agents/send-message-tool.js +2 -9
  16. package/dist/agents/subagent.d.ts +10 -29
  17. package/dist/agents/subagent.js +65 -53
  18. package/dist/agents/suspend-guard.d.ts +1 -1
  19. package/dist/agents/tool-filter.d.ts +76 -65
  20. package/dist/agents/tool-filter.js +122 -92
  21. package/dist/agents/verify.d.ts +4 -7
  22. package/dist/agents/verify.js +6 -7
  23. package/dist/bench/metrics.d.ts +1 -2
  24. package/dist/brain/anthropic.js +133 -79
  25. package/dist/brain/errors.d.ts +53 -6
  26. package/dist/brain/errors.js +22 -2
  27. package/dist/brain/input-too-long.d.ts +40 -19
  28. package/dist/brain/input-too-long.js +3 -16
  29. package/dist/brain/open-responses.js +19 -10
  30. package/dist/brain/openai.js +123 -32
  31. package/dist/brain/provider-dialect.d.ts +214 -0
  32. package/dist/brain/provider-dialect.js +186 -0
  33. package/dist/brain/request-params.d.ts +27 -8
  34. package/dist/brain/request-params.js +7 -12
  35. package/dist/brain/request-route.d.ts +84 -0
  36. package/dist/brain/request-route.js +41 -0
  37. package/dist/brain/retry.d.ts +8 -0
  38. package/dist/brain/retry.js +10 -4
  39. package/dist/brain/route-adjudicator.d.ts +7 -0
  40. package/dist/brain/route-adjudicator.js +5 -1
  41. package/dist/brain/status-sink.d.ts +20 -0
  42. package/dist/brain/status-sink.js +11 -0
  43. package/dist/brain/stream-engine.d.ts +52 -1
  44. package/dist/brain/stream-engine.js +81 -24
  45. package/dist/brain/stream-shared.d.ts +57 -11
  46. package/dist/brain/stream-shared.js +28 -2
  47. package/dist/core/a2a.d.ts +1 -0
  48. package/dist/core/agent-config-dir.js +3 -2
  49. package/dist/core/allow-entry.d.ts +21 -12
  50. package/dist/core/allow-entry.js +38 -31
  51. package/dist/core/arg-summary.d.ts +17 -24
  52. package/dist/core/arg-summary.js +169 -68
  53. package/dist/core/ask-origin.d.ts +42 -24
  54. package/dist/core/ask-origin.js +18 -13
  55. package/dist/core/auto-mode-prompt-assets.d.ts +2 -2
  56. package/dist/core/auto-mode-prompt-assets.js +1 -1
  57. package/dist/core/auto-mode-prompt.d.ts +11 -1
  58. package/dist/core/auto-mode-prompt.js +13 -10
  59. package/dist/core/auto-mode-rebuild.d.ts +7 -0
  60. package/dist/core/auto-mode-rebuild.js +4 -1
  61. package/dist/core/canonical-json.d.ts +3 -0
  62. package/dist/core/canonical-json.js +2 -1
  63. package/dist/core/checkpoint-requirements.d.ts +892 -0
  64. package/dist/core/checkpoint-requirements.js +333 -0
  65. package/dist/core/checkpoint-store.d.ts +94 -65
  66. package/dist/core/checkpoint-store.js +14 -26
  67. package/dist/core/child-clamp-seats.d.ts +228 -69
  68. package/dist/core/child-clamp-seats.js +211 -17
  69. package/dist/core/classifier-unavailable-arm.d.ts +5 -1
  70. package/dist/core/classifier-unavailable-arm.js +3 -3
  71. package/dist/core/compliance.d.ts +3 -0
  72. package/dist/core/compliance.js +9 -4
  73. package/dist/core/credential-vocabulary.d.ts +140 -0
  74. package/dist/core/credential-vocabulary.js +131 -0
  75. package/dist/core/decision-receipt.js +1 -1
  76. package/dist/core/effective-path-target.d.ts +73 -16
  77. package/dist/core/effective-path-target.js +63 -33
  78. package/dist/core/engine-notice.d.ts +32 -7
  79. package/dist/core/file-history-store.js +2 -2
  80. package/dist/core/fs-write-gate-policy.d.ts +4 -0
  81. package/dist/core/fs-write-gate-policy.js +22 -5
  82. package/dist/core/gate-bounded-await.d.ts +28 -13
  83. package/dist/core/gate-bounded-await.js +41 -4
  84. package/dist/core/gate-fold.d.ts +1 -1
  85. package/dist/core/gate-fold.js +24 -25
  86. package/dist/core/gate-lanes.js +16 -15
  87. package/dist/core/gate-outcome.d.ts +20 -5
  88. package/dist/core/gate-outcome.js +5 -0
  89. package/dist/core/governance-codes.d.ts +11 -4
  90. package/dist/core/governance-codes.js +14 -3
  91. package/dist/core/hooks.d.ts +4 -0
  92. package/dist/core/locked-config.d.ts +8 -0
  93. package/dist/core/locked-config.js +14 -2
  94. package/dist/core/lsp.js +3 -5
  95. package/dist/core/mailbox-store.d.ts +3 -4
  96. package/dist/core/mcp-connection-pool.d.ts +75 -0
  97. package/dist/core/mcp-connection-pool.js +128 -0
  98. package/dist/core/mcp-failure.d.ts +2 -1
  99. package/dist/core/mcp-failure.js +13 -2
  100. package/dist/core/mcp.d.ts +4 -0
  101. package/dist/core/mcp.js +70 -43
  102. package/dist/core/memory-engine/content-origin.js +2 -14
  103. package/dist/core/memory-engine/engine.d.ts +32 -22
  104. package/dist/core/memory-engine/engine.js +103 -55
  105. package/dist/core/memory-engine/file-backend.d.ts +13 -30
  106. package/dist/core/memory-engine/file-backend.js +37 -252
  107. package/dist/core/memory-engine/index.d.ts +1 -1
  108. package/dist/core/memory-engine/index.js +1 -1
  109. package/dist/core/memory-engine/layout.d.ts +139 -9
  110. package/dist/core/memory-engine/layout.js +350 -7
  111. package/dist/core/memory-engine/scope-contract.d.ts +10 -0
  112. package/dist/core/memory-engine/scope-contract.js +8 -0
  113. package/dist/core/memory-engine/session-incarnation.d.ts +14 -4
  114. package/dist/core/memory-engine/session-incarnation.js +5 -2
  115. package/dist/core/memory-engine/types.d.ts +10 -1
  116. package/dist/core/memory.js +5 -17
  117. package/dist/core/model-seat.d.ts +4 -4
  118. package/dist/core/model-seat.js +1 -1
  119. package/dist/core/mounted-mcp.d.ts +57 -0
  120. package/dist/core/mounted-mcp.js +19 -0
  121. package/dist/core/namespaced-rule-name.d.ts +29 -0
  122. package/dist/core/namespaced-rule-name.js +52 -0
  123. package/dist/core/park-selfcheck.d.ts +1 -1
  124. package/dist/core/park-selfcheck.js +16 -6
  125. package/dist/core/path-guard-rows.d.ts +99 -0
  126. package/dist/core/path-guard-rows.js +45 -0
  127. package/dist/core/path-identity.d.ts +22 -16
  128. package/dist/core/path-identity.js +10 -10
  129. package/dist/core/path-rule-binding.d.ts +2 -1
  130. package/dist/core/path-rule-binding.js +3 -1
  131. package/dist/core/pause-registry.d.ts +16 -2
  132. package/dist/core/pause-registry.js +6 -0
  133. package/dist/core/permission-rule-consent.js +0 -7
  134. package/dist/core/permission-rule-model.d.ts +68 -24
  135. package/dist/core/permission-rule-model.js +105 -24
  136. package/dist/core/permission-rule-store.js +2 -2
  137. package/dist/core/permission-rules.d.ts +3 -30
  138. package/dist/core/permission-rules.js +4 -54
  139. package/dist/core/read-root-candidate.d.ts +1 -3
  140. package/dist/core/read-root-candidate.js +4 -15
  141. package/dist/core/real-approval.d.ts +4 -3
  142. package/dist/core/retired-keys.d.ts +13 -0
  143. package/dist/core/retired-keys.js +14 -0
  144. package/dist/core/roles.d.ts +2 -3
  145. package/dist/core/roles.js +15 -6
  146. package/dist/core/runner/assemble-result.d.ts +0 -7
  147. package/dist/core/runner/assemble-result.js +19 -31
  148. package/dist/core/runner/caller-roster.d.ts +78 -0
  149. package/dist/core/runner/caller-roster.js +219 -0
  150. package/dist/core/runner/checkpoint-scope.d.ts +16 -16
  151. package/dist/core/runner/checkpoint-scope.js +2 -2
  152. package/dist/core/runner/child-tree.js +2 -2
  153. package/dist/core/runner/contracts.d.ts +68 -35
  154. package/dist/core/runner/decide-continuation.d.ts +51 -3
  155. package/dist/core/runner/decide-continuation.js +76 -21
  156. package/dist/core/runner/denial-limit-arms.d.ts +17 -5
  157. package/dist/core/runner/denial-limit-arms.js +11 -9
  158. package/dist/core/runner/extra-body-dropped-seat.d.ts +8 -0
  159. package/dist/core/runner/extra-body-dropped-seat.js +22 -0
  160. package/dist/core/runner/finish-reason-seat.d.ts +9 -0
  161. package/dist/core/runner/finish-reason-seat.js +40 -0
  162. package/dist/core/runner/gate-exit.d.ts +44 -32
  163. package/dist/core/runner/gate-exit.js +112 -25
  164. package/dist/core/runner/inherited-ask-grants.js +6 -4
  165. package/dist/core/runner/mcp-redial.d.ts +3 -3
  166. package/dist/core/runner/mcp-redial.js +3 -4
  167. package/dist/core/runner/permission-rule-lanes.d.ts +1 -2
  168. package/dist/core/runner/permission-rule-lanes.js +5 -4
  169. package/dist/core/runner/prepare-artifact.d.ts +4 -0
  170. package/dist/core/runner/prepare-artifact.js +2 -1
  171. package/dist/core/runner/prepare-ask-lane.d.ts +2 -0
  172. package/dist/core/runner/prepare-ask-lane.js +12 -6
  173. package/dist/core/runner/prepare-boundary-parks.d.ts +5 -8
  174. package/dist/core/runner/prepare-boundary-parks.js +4 -7
  175. package/dist/core/runner/prepare-caps-and-workflow.d.ts +11 -15
  176. package/dist/core/runner/prepare-caps-and-workflow.js +19 -27
  177. package/dist/core/runner/prepare-config-doors.d.ts +9 -9
  178. package/dist/core/runner/prepare-config-doors.js +10 -5
  179. package/dist/core/runner/prepare-defer-classify.d.ts +2 -2
  180. package/dist/core/runner/prepare-defer-classify.js +5 -3
  181. package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
  182. package/dist/core/runner/prepare-delegation-surface.js +3 -3
  183. package/dist/core/runner/prepare-gate-stations.d.ts +4 -4
  184. package/dist/core/runner/prepare-gate-stations.js +9 -7
  185. package/dist/core/runner/prepare-hands-readface.d.ts +7 -7
  186. package/dist/core/runner/prepare-hands-readface.js +7 -7
  187. package/dist/core/runner/prepare-inherited-gate.d.ts +7 -6
  188. package/dist/core/runner/prepare-inherited-gate.js +14 -15
  189. package/dist/core/runner/prepare-listings.d.ts +7 -24
  190. package/dist/core/runner/prepare-listings.js +4 -5
  191. package/dist/core/runner/prepare-memory-engine-session.d.ts +2 -0
  192. package/dist/core/runner/prepare-memory-engine-session.js +4 -3
  193. package/dist/core/runner/prepare-memory.d.ts +6 -0
  194. package/dist/core/runner/prepare-memory.js +13 -13
  195. package/dist/core/runner/prepare-offload-wrappers.d.ts +5 -0
  196. package/dist/core/runner/prepare-offload-wrappers.js +3 -3
  197. package/dist/core/runner/prepare-park-ask.d.ts +7 -8
  198. package/dist/core/runner/prepare-park-ask.js +17 -10
  199. package/dist/core/runner/prepare-policy-chain.js +24 -44
  200. package/dist/core/runner/prepare-project-context.d.ts +1 -1
  201. package/dist/core/runner/prepare-project-context.js +3 -4
  202. package/dist/core/runner/prepare-protocol-tools.d.ts +9 -3
  203. package/dist/core/runner/prepare-protocol-tools.js +3 -4
  204. package/dist/core/runner/prepare-run-refs.d.ts +3 -0
  205. package/dist/core/runner/prepare-run-refs.js +2 -1
  206. package/dist/core/runner/prepare-safety-scan.d.ts +4 -8
  207. package/dist/core/runner/prepare-safety-scan.js +1 -2
  208. package/dist/core/runner/prepare-suspend-saga.d.ts +7 -1
  209. package/dist/core/runner/prepare-suspend-saga.js +28 -12
  210. package/dist/core/runner/prepare-task.d.ts +1 -1
  211. package/dist/core/runner/prepare-task.js +67 -56
  212. package/dist/core/runner/prepare-wiring-manifest.d.ts +11 -10
  213. package/dist/core/runner/prepare-wiring-manifest.js +5 -8
  214. package/dist/core/runner/resume-apply.js +7 -14
  215. package/dist/core/runner/resume-checkpoint-screen.js +11 -4
  216. package/dist/core/runner/resume-internals-and-config.js +2 -2
  217. package/dist/core/runner/resume-policy-outcome.js +5 -32
  218. package/dist/core/runner/resume-review-outcome.js +4 -1
  219. package/dist/core/runner/retired-runner-deps.d.ts +6 -0
  220. package/dist/core/runner/retired-runner-deps.js +10 -1
  221. package/dist/core/runner/run-brain-sinks.d.ts +4 -0
  222. package/dist/core/runner/run-brain-sinks.js +5 -2
  223. package/dist/core/runner/run-harness-handlers.js +27 -34
  224. package/dist/core/runner/run-leg.d.ts +0 -2
  225. package/dist/core/runner/run-leg.js +32 -33
  226. package/dist/core/runner/run-terminal-adoption.js +4 -3
  227. package/dist/core/runner/runtask.js +8 -8
  228. package/dist/core/runner/session-rule-policy.js +5 -5
  229. package/dist/core/runner/stream-settle-backstop.js +7 -4
  230. package/dist/core/runner/sub-agent-deny-lists.d.ts +51 -12
  231. package/dist/core/runner/sub-agent-deny-lists.js +111 -80
  232. package/dist/core/runner/terminal-account.d.ts +48 -0
  233. package/dist/core/runner/terminal-account.js +186 -0
  234. package/dist/core/runner/tool-end-body.d.ts +54 -17
  235. package/dist/core/runner/tool-end-body.js +27 -2
  236. package/dist/core/runner/tool-face-overlay.d.ts +3 -1
  237. package/dist/core/runner/tool-face-overlay.js +6 -4
  238. package/dist/core/runner/tool-occurrence.d.ts +106 -0
  239. package/dist/core/runner/tool-occurrence.js +123 -0
  240. package/dist/core/runner/tool-progress-lane.d.ts +16 -8
  241. package/dist/core/runner/tool-progress-lane.js +25 -34
  242. package/dist/core/runner/turn-attachments.d.ts +1 -1
  243. package/dist/core/runner/write-protection-station.d.ts +21 -9
  244. package/dist/core/runner/write-protection-station.js +20 -17
  245. package/dist/core/runner-deps.d.ts +12 -22
  246. package/dist/core/secret-env.d.ts +16 -5
  247. package/dist/core/secret-env.js +23 -63
  248. package/dist/core/sensitive-path-policy.d.ts +19 -18
  249. package/dist/core/sensitive-path-policy.js +73 -49
  250. package/dist/core/session-reconcile.d.ts +3 -0
  251. package/dist/core/session-reconcile.js +5 -4
  252. package/dist/core/session-store.d.ts +5 -0
  253. package/dist/core/session-store.js +12 -0
  254. package/dist/core/session.d.ts +13 -0
  255. package/dist/core/shared-memory/normalize.d.ts +17 -4
  256. package/dist/core/shared-memory/normalize.js +7 -7
  257. package/dist/core/shell-lexer.js +5 -4
  258. package/dist/core/skill-grant.js +1 -1
  259. package/dist/core/store-contracts/checkpoint-store-contract.js +13 -0
  260. package/dist/core/store-contracts/mailbox-store-contract.d.ts +7 -14
  261. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +27 -0
  262. package/dist/core/store-contracts/session-store-incarnation-contract.js +92 -0
  263. package/dist/core/stub-env.d.ts +2 -0
  264. package/dist/core/stub-env.js +1 -0
  265. package/dist/core/synthetic-read-verdict.js +2 -2
  266. package/dist/core/task-event.d.ts +59 -5
  267. package/dist/core/task-result.d.ts +1 -1
  268. package/dist/core/task-spec.d.ts +42 -9
  269. package/dist/core/terminal-cause.d.ts +94 -11
  270. package/dist/core/tighten-task-spec.d.ts +5 -4
  271. package/dist/core/tighten-task-spec.js +20 -25
  272. package/dist/core/tool-catalog-entries.d.ts +5 -7
  273. package/dist/core/tool-catalog-entries.js +14 -15
  274. package/dist/core/tool-face.d.ts +47 -0
  275. package/dist/core/tool-face.js +5 -0
  276. package/dist/core/tool-model-gate.d.ts +5 -5
  277. package/dist/core/tool-name-aliases.d.ts +26 -2
  278. package/dist/core/tool-name-aliases.js +13 -0
  279. package/dist/core/tool-name-list.d.ts +30 -0
  280. package/dist/core/tool-name-list.js +55 -0
  281. package/dist/core/tool-name-readings.d.ts +1 -9
  282. package/dist/core/tool-name-readings.js +1 -3
  283. package/dist/core/tool-policy.d.ts +195 -85
  284. package/dist/core/tool-policy.js +165 -380
  285. package/dist/core/tool-registry.d.ts +44 -1
  286. package/dist/core/tool-registry.js +26 -0
  287. package/dist/core/tool-roster.d.ts +19 -1
  288. package/dist/core/tool-roster.js +21 -2
  289. package/dist/core/tool-spec-members.d.ts +45 -0
  290. package/dist/core/tool-spec-members.js +169 -0
  291. package/dist/core/tool-spec.d.ts +46 -8
  292. package/dist/core/tools.d.ts +6 -2
  293. package/dist/core/tools.js +8 -4
  294. package/dist/core/untrusted-egress.js +29 -26
  295. package/dist/core/untrusted-text.d.ts +13 -10
  296. package/dist/core/untrusted-text.js +6 -44
  297. package/dist/core/workflow-journal-store.d.ts +4 -1
  298. package/dist/core/write-protect.d.ts +65 -29
  299. package/dist/core/write-protect.js +235 -177
  300. package/dist/engine/compaction/compaction.d.ts +2 -2
  301. package/dist/engine/execution-env/node-execution-env.d.ts +5 -23
  302. package/dist/engine/execution-env/node-execution-env.js +16 -38
  303. package/dist/engine/execution-env/symlink-chain.d.ts +23 -0
  304. package/dist/engine/execution-env/symlink-chain.js +32 -0
  305. package/dist/engine/harness/types.d.ts +7 -0
  306. package/dist/engine/llm/tool-turns.d.ts +3 -0
  307. package/dist/engine/llm/tool-turns.js +1 -0
  308. package/dist/engine/llm/types.d.ts +59 -23
  309. package/dist/engine/loop/agent-loop.js +16 -2
  310. package/dist/engine/session/memory-repo.js +11 -3
  311. package/dist/engine/session/repo-utils.d.ts +8 -0
  312. package/dist/engine/session/repo-utils.js +13 -0
  313. package/dist/index.d.ts +20 -23
  314. package/dist/index.js +17 -20
  315. package/dist/internal/harness.d.ts +1 -1
  316. package/dist/internal/harness.js +1 -1
  317. package/dist/internal/llm.d.ts +2 -2
  318. package/dist/internal/llm.js +1 -1
  319. package/dist/orchestration/governance-baseline-validity.js +1 -1
  320. package/dist/orchestration/run-spec.js +3 -3
  321. package/dist/orchestration/run-workflow-tool.d.ts +16 -35
  322. package/dist/orchestration/run-workflow-tool.js +38 -78
  323. package/dist/orchestration/workflow-governance.d.ts +21 -25
  324. package/dist/orchestration/workflow-governance.js +38 -78
  325. package/dist/orchestration/workflow-primitives.d.ts +7 -22
  326. package/dist/orchestration/workflow-primitives.js +5 -12
  327. package/dist/orchestration/workflow-types.d.ts +1 -1
  328. package/dist/orchestration/workflow.d.ts +61 -11
  329. package/dist/orchestration/workflow.js +189 -117
  330. package/dist/scenarios/full-body.d.ts +1 -1
  331. package/dist/shell/lex.d.ts +0 -21
  332. package/dist/shell/lex.js +250 -68
  333. package/dist/shell/shell-words.d.ts +35 -0
  334. package/dist/shell/shell-words.js +65 -0
  335. package/dist/stores/file/checkpoint-store.d.ts +5 -5
  336. package/dist/stores/file/checkpoint-store.js +5 -2
  337. package/dist/stores/file/index.d.ts +0 -8
  338. package/dist/stores/file/index.js +0 -12
  339. package/dist/stores/file/session-store.d.ts +3 -0
  340. package/dist/stores/file/session-store.js +44 -19
  341. package/dist/tools/artifact/artifact-tool.js +2 -0
  342. package/dist/tools/fs/bash-program-position.d.ts +10 -3
  343. package/dist/tools/fs/bash-program-position.js +21 -9
  344. package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
  345. package/dist/tools/fs/bash-readonly-classifier.js +8 -7
  346. package/dist/tools/fs/containment-face.d.ts +4 -0
  347. package/dist/tools/fs/containment-face.js +3 -0
  348. package/dist/tools/fs/fs-shared.d.ts +10 -0
  349. package/dist/tools/fs/fs-shared.js +18 -0
  350. package/dist/tools/fs/fs-write.js +4 -2
  351. package/dist/tools/fs/index.d.ts +1 -1
  352. package/dist/tools/fs/program-read-model.d.ts +39 -18
  353. package/dist/tools/fs/program-read-model.js +29 -19
  354. package/dist/tools/fs/program-read-model.rows.d.ts +0 -14
  355. package/dist/tools/fs/program-read-model.rows.js +5 -5
  356. package/dist/tools/fs/read-deny-home.d.ts +33 -47
  357. package/dist/tools/fs/read-deny-home.js +35 -49
  358. package/dist/tools/fs/read-deny.d.ts +23 -22
  359. package/dist/tools/fs/read-deny.js +114 -89
  360. package/dist/tools/fs/removal-targets.d.ts +56 -23
  361. package/dist/tools/fs/removal-targets.js +65 -87
  362. package/dist/tools/fs/safety.d.ts +29 -22
  363. package/dist/tools/fs/safety.js +17 -11
  364. package/dist/tools/fs/search.js +10 -8
  365. package/dist/tools/fs/shell-read-argv.js +1 -1
  366. package/dist/tools/fs/shell-read-bindings.d.ts +169 -37
  367. package/dist/tools/fs/shell-read-bindings.js +324 -86
  368. package/dist/tools/fs/shell-read-builtins.d.ts +35 -0
  369. package/dist/tools/fs/shell-read-builtins.js +43 -0
  370. package/dist/tools/fs/shell-read-check.d.ts +15 -1
  371. package/dist/tools/fs/shell-read-check.js +51 -42
  372. package/dist/tools/fs/shell-read-establish.js +6 -6
  373. package/dist/tools/fs/shell-read-functions.d.ts +22 -0
  374. package/dist/tools/fs/shell-read-functions.js +29 -0
  375. package/dist/tools/fs/shell-read-judge.d.ts +48 -18
  376. package/dist/tools/fs/shell-read-judge.js +33 -4
  377. package/dist/tools/fs/shell-read-plan.d.ts +12 -6
  378. package/dist/tools/fs/shell-read-plan.js +118 -113
  379. package/dist/tools/fs/shell-read-start.d.ts +29 -6
  380. package/dist/tools/fs/shell-read-start.js +16 -9
  381. package/dist/tools/fs/shell-read-word.js +4 -0
  382. package/dist/tools/fs/shell-read-workdir.d.ts +156 -0
  383. package/dist/tools/fs/shell-read-workdir.js +281 -0
  384. package/dist/tools/fs/shell-read-write-targets.d.ts +5 -2
  385. package/dist/tools/fs/shell-read-write-targets.js +14 -5
  386. package/dist/tools/fs/shell-reentry-text.d.ts +4 -6
  387. package/dist/tools/fs/shell-reentry-text.js +3 -11
  388. package/dist/tools/task-list.d.ts +1 -2
  389. package/dist/tools/web.js +1 -1
  390. package/package.json +4 -1
  391. package/test/export-surface.snapshot.json +107 -143
  392. package/wire-changes/core@7.49.0.json +4765 -0
  393. package/dist/agents/teacher.d.ts +0 -159
  394. package/dist/agents/teacher.js +0 -577
  395. package/dist/agents/team.d.ts +0 -226
  396. package/dist/agents/team.js +0 -257
  397. package/dist/core/strategy-store.d.ts +0 -238
  398. package/dist/core/strategy-store.js +0 -253
  399. package/dist/orchestration/builtin-workflows.d.ts +0 -133
  400. package/dist/orchestration/builtin-workflows.js +0 -159
  401. package/dist/scenarios/env.d.ts +0 -40
  402. package/dist/scenarios/env.js +0 -39
  403. package/dist/scenarios/scenario-registry.d.ts +0 -110
  404. package/dist/scenarios/scenario-registry.js +0 -140
  405. package/dist/scenarios/teacher-quickstart.d.ts +0 -40
  406. package/dist/scenarios/teacher-quickstart.js +0 -12
  407. package/dist/stores/cc/lockfile.d.ts +0 -10
  408. package/dist/stores/cc/lockfile.js +0 -98
  409. package/dist/stores/cc/mailbox-store.d.ts +0 -20
  410. package/dist/stores/cc/mailbox-store.js +0 -255
  411. package/dist/stores/cc/roster-adapter.d.ts +0 -12
  412. package/dist/stores/cc/roster-adapter.js +0 -117
  413. package/dist/stores/cc/sidecar-transcript.d.ts +0 -97
  414. package/dist/stores/cc/sidecar-transcript.js +0 -264
  415. package/dist/stores/cc/task-list-store.d.ts +0 -2
  416. package/dist/stores/cc/task-list-store.js +0 -125
  417. package/dist/stores/file/strategy-store.d.ts +0 -97
  418. package/dist/stores/file/strategy-store.js +0 -341
@@ -1,7 +1,8 @@
1
1
  import { persistedReadDenyEntryProblem } from "../../tools/fs/read-deny.js";
2
- import { isAbsolutePathForm } from "../../tools/fs/safety.js";
2
+ import { validatePath } from "../effective-path-target.js";
3
3
  import { isAskOrigin } from "../ask-origin.js";
4
4
  import { CHECKPOINT_FEATURES, CheckpointError, checkpointVersionOf, MAX_SUPPORTED_CHECKPOINT_VERSION, realApprovalOrgFact } from "../checkpoint-store.js";
5
+ import { judgeCheckpointRequirements } from "../checkpoint-requirements.js";
5
6
  import { constraintChainDigest, constraintChainEntryOfSuppliedLayer } from "../tool-policy.js";
6
7
  import { readFrozenSkillGrants } from "../skill-grant.js";
7
8
  import { chainInstallationGaps, chainInstallationRefusal } from "./child-tree.js";
@@ -9,8 +10,13 @@ export function resumeCheckpointScreen(input) {
9
10
  const { cp, resumeSignal, internals, runner } = input;
10
11
  const { realApproval: realApprovalRow, face: faceRow, f012: f012Row } = CHECKPOINT_FEATURES;
11
12
  if (checkpointVersionOf(cp) > MAX_SUPPORTED_CHECKPOINT_VERSION) {
12
- throw new CheckpointError("checkpoint.unsupported_version", `checkpoint version ${checkpointVersionOf(cp)} is newer than this worker supports (max ${MAX_SUPPORTED_CHECKPOINT_VERSION})`, { reason: "version_newer" });
13
+ throw new CheckpointError("checkpoint.unsupported_version", `checkpoint requires reader capabilities this worker lacks (row format v${checkpointVersionOf(cp)}; this worker reads up to v${MAX_SUPPORTED_CHECKPOINT_VERSION}) — resume it on a worker at or above the version that parked it`, { reason: "version_newer" });
13
14
  }
15
+ const requirements = judgeCheckpointRequirements(cp);
16
+ if (requirements.kind === "lacking")
17
+ throw new CheckpointError("checkpoint.unsupported_version", `checkpoint requires reader capabilities this worker lacks (${requirements.words.join(", ")}) — resume it on a worker at or above the version that parked it`, { reason: "version_newer", requires: requirements.words });
18
+ if (requirements.kind === "damaged")
19
+ throw new CheckpointError("checkpoint.invalid_outcome", `this checkpoint's reader-requirement list does not match the row (${requirements.why}) — refusing to resume a damaged row (corruption guard), the checkpoint stays pending; no worker can resume it: start the task again`, { reason: "requirements_damaged" });
14
20
  const preCasGateBit = cp.gate.kind === "irreversible_ask" ? cp.gate.realApproval : undefined;
15
21
  const preCasBitWellFormed = preCasGateBit !== undefined && typeof preCasGateBit === "object" && isAskOrigin(preCasGateBit.origin);
16
22
  const faceSaysGoverned = (cp.state.readFace?.realApproval) === true;
@@ -37,7 +43,8 @@ export function resumeCheckpointScreen(input) {
37
43
  (faceCandidate.denyEntries === undefined ||
38
44
  (Array.isArray(faceCandidate.denyEntries) &&
39
45
  faceCandidate.denyEntries.every((e) => persistedReadDenyEntryProblem(e) === null)));
40
- if (checkpointVersionOf(cp) >= faceRow.version ? !faceWellFormed : faceSectionRaw !== undefined) {
46
+ const v = checkpointVersionOf(cp);
47
+ if (v === faceRow.version ? !faceWellFormed : v < faceRow.version ? faceSectionRaw !== undefined : faceSectionRaw !== undefined && !faceWellFormed) {
41
48
  throw new CheckpointError("checkpoint.invalid_outcome", checkpointVersionOf(cp) >= faceRow.version
42
49
  ? `a v${checkpointVersionOf(cp)} checkpoint must carry a well-formed read-face section (state.readFace) — this row's is missing or malformed; refusing to resume a damaged read-face row (corruption / downgrade guard), the checkpoint stays pending`
43
50
  : `a v${checkpointVersionOf(cp)} checkpoint carries a read-face section no release of that version ever minted — refusing to honor a fabricated read-face state (corruption / forgery guard), the checkpoint stays pending`, { reason: checkpointVersionOf(cp) >= faceRow.version ? "read_face_damaged" : "read_face_forged" });
@@ -53,7 +60,7 @@ export function resumeCheckpointScreen(input) {
53
60
  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" });
54
61
  for (const field of ["handsRoot", "handsHome", "handsCwd"]) {
55
62
  const coordinate = cp.state[field];
56
- if (coordinate !== undefined && (typeof coordinate !== "string" || !isAbsolutePathForm(coordinate)))
63
+ if (coordinate !== undefined && validatePath(coordinate, { intent: "validate-coordinate" }) === undefined)
57
64
  throw new CheckpointError("checkpoint.invalid_outcome", `this checkpoint's state.${field} is not an absolute path — refusing to resume a row whose hands' coordinates are damaged (corruption guard), the checkpoint stays pending`, { reason: "hands_coordinates_damaged" });
58
65
  }
59
66
  }
@@ -1,12 +1,12 @@
1
1
  import { CheckpointError, readPendingSteerQueue } from "../checkpoint-store.js";
2
2
  import { GLOBAL_USAGE_KEY, resolveUsageWindows, usageRetryAfterMs } from "../usage-window-store.js";
3
3
  import { placementValueOrAbsent } from "./checkpoint-scope.js";
4
- import { assertNoRetiredRunnerDeps } from "./retired-runner-deps.js";
4
+ import { assertNoRetiredResumeSeats } from "./retired-runner-deps.js";
5
5
  import { resolveMicroCompactKnob } from "./prepare-config-doors.js";
6
6
  export function resumeInternalsAndConfig(input) {
7
7
  const { cp, config, internals, outcomeGate, runner } = input;
8
8
  let windowEntrance;
9
- assertNoRetiredRunnerDeps(runner.deps);
9
+ assertNoRetiredResumeSeats(runner.deps, config, internals);
10
10
  resolveMicroCompactKnob(runner.deps.microCompact);
11
11
  if (runner.deps.lockedConfig?.keys?.includes("toolPolicy") === true && config.basePolicyForResumeEdit !== undefined) {
12
12
  throw new CheckpointError("checkpoint.invalid_outcome", "TaskSpec.basePolicyForResumeEdit is administratively locked by this deployment (locked key \"toolPolicy\") — a task-supplied " +
@@ -1,11 +1,9 @@
1
1
  import { canonicalizeCapturedPlainData, classifyQuestionOutcome, isLiveQuestionFace } from "../ask-question.js";
2
- import { isHostDecider } from "../gate-outcome.js";
3
2
  import { CHECKPOINT_FEATURES, CheckpointError, checkpointVersionOf, winnerFromOutcome } from "../checkpoint-store.js";
4
- import { policyCannotAnswer, screenApproverAttribution } from "../tool-policy.js";
5
3
  import { sanitizeUntrustedText } from "../untrusted-text.js";
6
- import { assertOutcomeText, describeSuppliedValue, pendingContentAskCallId, sameWinner } from "./decide-continuation.js";
4
+ import { assertOutcomeText, captureHostDecision, describeSuppliedValue, pendingContentAskCallId, refuseSuppliedKeys, sameWinner, SUPPLIED_RECORD_KEY } from "./decide-continuation.js";
7
5
  const REFUSED_DECIDE_KEYS = [
8
- ["gateOutcome", "the settlement record is minted by core from the host's decision facts and the row's origin, never supplied"],
6
+ SUPPLIED_RECORD_KEY,
9
7
  ["settledBy", 'a retired key — the host supplies decision FACTS as hostDecision{decidedBy: "person" | "sla_timeout" | "policy", approver?} and core mints the settlement word from them'],
10
8
  ["approver", "a retired key — the attribution rides the facts it belongs to, as hostDecision.approver"],
11
9
  ];
@@ -43,35 +41,10 @@ export function resumePolicyOutcome(input) {
43
41
  if (decision !== "allow" && decision !== "deny") {
44
42
  throw new CheckpointError("checkpoint.invalid_outcome", `resume decision "${describeSuppliedValue(decision)}" is outside the policy_ask domain — a decide is exactly "allow" or "deny"; refusing pre-CAS, the checkpoint stays pending`);
45
43
  }
46
- for (const [key, why] of REFUSED_DECIDE_KEYS) {
47
- if (Reflect.get(decide, key) !== undefined) {
48
- throw new CheckpointError("checkpoint.invalid_outcome", `resume carries \`${key}\` — ${why}; refusing pre-CAS, the checkpoint stays pending`, { field: "hostDecision" });
49
- }
50
- }
51
- const hostDecisionRaw = decide.hostDecision;
52
- if (typeof hostDecisionRaw !== "object" || hostDecisionRaw === null) {
53
- throw new CheckpointError("checkpoint.invalid_outcome", `resume carries no hostDecision — a policy_ask decide names who decided it ({ decidedBy: "person" | "sla_timeout" | "policy", approver? }); refusing pre-CAS, the checkpoint stays pending`, { field: "hostDecision" });
54
- }
55
- const decidedBy = hostDecisionRaw.decidedBy;
56
- if (!isHostDecider(decidedBy)) {
57
- throw new CheckpointError("checkpoint.invalid_outcome", `resume hostDecision.decidedBy "${describeSuppliedValue(decidedBy)}" is outside the closed set — it is exactly "person", "sla_timeout" or "policy"; refusing pre-CAS, the checkpoint stays pending`, { field: "hostDecision" });
58
- }
59
- const cannotAllow = decision !== "allow"
60
- ? undefined
61
- : decidedBy === "sla_timeout"
62
- ? ` — that word names a wait that ended with nobody answering, and it cannot approve an action that EXECUTES (an allow is decided by "person" or "policy")`
63
- : policyCannotAnswer(cp, decidedBy)
64
- ? ` on a row that requires real approval — a policy's answer is not a person's, and this row demands a person (decide it as "person", or refuse it as "policy")`
65
- : undefined;
66
- if (cannotAllow !== undefined)
67
- throw new CheckpointError("checkpoint.invalid_outcome", `resume carries decision "allow" decided by "${decidedBy}"${cannotAllow}; refusing pre-CAS, the checkpoint stays pending`, { field: "hostDecision" });
68
- const attribution = screenApproverAttribution(hostDecisionRaw.approver);
69
- if (attribution.defect !== undefined) {
70
- throw new CheckpointError("checkpoint.invalid_outcome", `resume carries an approver attribution this engine refuses: ${attribution.defect}; refusing pre-CAS, the checkpoint stays pending`, { field: "approver" });
71
- }
44
+ refuseSuppliedKeys(decide, REFUSED_DECIDE_KEYS);
45
+ const hostDecision = captureHostDecision(cp, decide.hostDecision, "policy_ask", { word: decision, allows: decision === "allow" });
72
46
  const reason = decide.reason;
73
47
  assertOutcomeText(reason, "reason");
74
- const approverCell = attribution.approver !== undefined ? { approver: attribution.approver } : {};
75
48
  plainPolicyOutcome = {
76
49
  gate: "policy_ask",
77
50
  boundCallId: decide.boundCallId,
@@ -80,7 +53,7 @@ export function resumePolicyOutcome(input) {
80
53
  ...(updatedInput !== undefined ? { updatedInput } : {}),
81
54
  ...(reason !== undefined ? { reason } : {}),
82
55
  ...(redeemedAnswer !== undefined ? { answer: redeemedAnswer } : {}),
83
- hostDecision: { decidedBy, ...approverCell },
56
+ hostDecision,
84
57
  };
85
58
  if (plainPolicyOutcome.decision === "deny" && plainPolicyOutcome.reason && sanitizeUntrustedText(plainPolicyOutcome.reason) !== plainPolicyOutcome.reason) {
86
59
  throw new CheckpointError("checkpoint.invalid_outcome", "resume deny/reject reason must not contain a </system-reminder> tag");
@@ -1,7 +1,7 @@
1
1
  import { CheckpointError } from "../checkpoint-store.js";
2
2
  import { isGateKind, PAUSE_REGISTRY, resumeGateMatches } from "../pause-registry.js";
3
3
  import { sanitizeUntrustedText } from "../untrusted-text.js";
4
- import { assertOutcomeText, describeSuppliedValue } from "./decide-continuation.js";
4
+ import { assertOutcomeText, captureHostDecision, describeSuppliedValue, refuseSuppliedKeys, SUPPLIED_RECORD_KEY } from "./decide-continuation.js";
5
5
  export function resumeReviewOutcome(input) {
6
6
  const { cp, outcome, outcomeGate, wakeMessage } = input;
7
7
  const gateMatch = isGateKind(cp.gate.kind) && resumeGateMatches(cp.gate.kind, outcomeGate);
@@ -20,6 +20,8 @@ export function resumeReviewOutcome(input) {
20
20
  if (decision !== "approve" && decision !== "edit" && decision !== "reject") {
21
21
  throw new CheckpointError("checkpoint.invalid_outcome", `resume decision "${describeSuppliedValue(decision)}" is outside the plan_review domain — a plan review is exactly "approve", "edit" or "reject"; refusing pre-CAS, the checkpoint stays pending`);
22
22
  }
23
+ refuseSuppliedKeys(decide, [SUPPLIED_RECORD_KEY]);
24
+ const hostDecision = captureHostDecision(cp, decide.hostDecision, "plan_review", { word: decision, allows: decision !== "reject" });
23
25
  assertOutcomeText(editedPlan, "editedPlan");
24
26
  assertOutcomeText(reason, "reason");
25
27
  plainReviewOutcome = {
@@ -27,6 +29,7 @@ export function resumeReviewOutcome(input) {
27
29
  decision,
28
30
  ...(editedPlan !== undefined ? { editedPlan } : {}),
29
31
  ...(reason !== undefined ? { reason } : {}),
32
+ hostDecision,
30
33
  };
31
34
  }
32
35
  else if (cp.gate.kind === "needs_review") {
@@ -1,5 +1,11 @@
1
1
  import type { RunnerDeps } from "../types.js";
2
+ import type { ResumeTaskConfig, RunInternals } from "./contracts.js";
2
3
  /** Runs on the caller's own argument at `new Runner` (the only point that still sees an inherited or
3
4
  * non-enumerable seat — construction spreads deps into plain objects), and again in the pre-first-await
4
5
  * config-doors phase and pre-CAS on a resume. */
5
6
  export declare function assertNoRetiredRunnerDeps(deps: RunnerDeps): void;
7
+ /** The resume ladder's pre-claim door: the retired seats of the deps, then the retired members of the caller policies this
8
+ * resume installs (the prepare's own resolution, `callerPolicySeats`) and of the inherited constraints it is handed. The edit
9
+ * re-check runs the resume-edit policy before the claim, and a refusal after the claim would burn the token on a store
10
+ * without `reopen`. */
11
+ export declare function assertNoRetiredResumeSeats(deps: RunnerDeps, config: ResumeTaskConfig, internals: RunInternals | undefined): void;
@@ -1,10 +1,19 @@
1
- import { assertNoRetiredKeys } from "../retired-keys.js";
1
+ import { assertNoRetiredKeys, assertNoRetiredToolPolicyKeys } from "../retired-keys.js";
2
+ import { assertCallerPoliciesCurrent, callerPolicySeats } from "../locked-config.js";
2
3
  const RETIRED_RUNNER_DEPS_KEYS = {
3
4
  legacyRewindBoundaryProbe: "the rewind refusal always names both possibilities (never existed / retired whole-tree era); a deployment that holds that era's table answers the question on its own surface",
4
5
  peerAdmission: "the peer lane's knob table is `RunnerDeps.peerLane` (the same fields: admission gate, delivery budgets, listing window)",
6
+ builtinWorkflows: "the engine ships no built-in named workflows — the Workflow tool's `{name}` resolves only `RunnerDeps.workflowScriptStore`; register any named workflow there",
5
7
  graderEnvFactory: "the grader env reaches the repair loop as `RepairLoopConfig.graderEnv`, minted by the trusted control plane (`assertOracleIsolation` / `GraderEnv` unchanged)",
6
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
+ 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.incarnationOf` 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",
7
10
  };
8
11
  export function assertNoRetiredRunnerDeps(deps) {
9
12
  assertNoRetiredKeys(deps, RETIRED_RUNNER_DEPS_KEYS, "RunnerDeps");
10
13
  }
14
+ export function assertNoRetiredResumeSeats(deps, config, internals) {
15
+ assertNoRetiredRunnerDeps(deps);
16
+ assertCallerPoliciesCurrent(callerPolicySeats(config, deps, deps.lockedConfig?.keys?.includes("toolPolicy") === true));
17
+ for (const constraint of internals?.inheritedGate?.parentConstraints ?? [])
18
+ assertNoRetiredToolPolicyKeys(constraint.policy);
19
+ }
@@ -1,4 +1,5 @@
1
1
  import type { ReasoningWireFacts } from "../../brain/reasoning.js";
2
+ import { type ExtraBodyDroppedSeatInput } from "./extra-body-dropped-seat.js";
2
3
  import type { PushQueue } from "../push-queue.js";
3
4
  import type { TaskEvent } from "../types.js";
4
5
  import type { RunInternals, RunState } from "./contracts.js";
@@ -19,11 +20,14 @@ export interface RunBrainSinksInput {
19
20
  parentToolCallId: string | undefined;
20
21
  /** borrowed-readonly — the reasoning lane's wire-facts consumer, the third sink the composition installs. */
21
22
  observeReasoningWireFacts: (facts: ReasoningWireFacts) => void;
23
+ /** borrowed-readonly — the notice sink and the leg's ids; the fourth sink's announcer is minted from them. */
24
+ notice: ExtraBodyDroppedSeatInput;
22
25
  }
23
26
  export interface RunBrainSinksResult {
24
27
  /** The subagent's human display name for its `task_progress` ticks, or undefined. */
25
28
  subagentName: string | undefined;
26
29
  /** Compose the three brain ALS sinks around a brain-driving call. */
27
30
  withBrainSinks: <T>(fn: () => Promise<T>) => Promise<T>;
31
+ withExtraBodyDroppedSink: <T>(fn: () => Promise<T>) => Promise<T>;
28
32
  }
29
33
  export declare function runBrainSinks(input: RunBrainSinksInput): RunBrainSinksResult;
@@ -1,9 +1,10 @@
1
1
  import { runWithBrainTelemetry, runWithReasoningWireFacts, runWithStatusSink } from "../../brain/status-sink.js";
2
+ import { createExtraBodyDroppedScope } from "./extra-body-dropped-seat.js";
2
3
  import { createSafeNotifier, observeThenableRejection } from "../safe-notify.js";
3
4
  import { emitTrace } from "../trace.js";
4
5
  import { inlineUntrusted } from "../untrusted-text.js";
5
6
  export function runBrainSinks(input) {
6
- const { queue, internals, rs, ident, parentToolCallId, observeReasoningWireFacts } = input;
7
+ const { queue, internals, rs, ident, parentToolCallId, observeReasoningWireFacts, notice } = input;
7
8
  const subagentName = parentToolCallId !== undefined && internals?.agentName !== undefined ? inlineUntrusted(internals.agentName.slice(0, 320), 80) : undefined;
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}`),
@@ -22,6 +23,8 @@ export function runBrainSinks(input) {
22
23
  ...(s.maxRetries !== undefined ? { maxRetries: s.maxRetries } : {}),
23
24
  ...(s.errClass !== undefined ? { errClass: s.errClass } : {}),
24
25
  ...(s.errorStatus !== undefined ? { errorStatus: s.errorStatus } : {}),
26
+ ...(s.providerCondition !== undefined ? { providerCondition: s.providerCondition } : {}),
27
+ ...(s.providerConditionSource !== undefined ? { providerConditionSource: s.providerConditionSource } : {}),
25
28
  ...ident(),
26
29
  };
27
30
  Object.freeze(frame);
@@ -59,5 +62,5 @@ export function runBrainSinks(input) {
59
62
  : { kind: "vision.placeholder", version: 1, taskId: rs.telemetry.taskId, count: t.count, ts: Date.now() });
60
63
  };
61
64
  const withBrainSinks = (fn) => runWithStatusSink(statusEmit, () => runWithBrainTelemetry(telemetryEmit, () => runWithReasoningWireFacts(observeReasoningWireFacts, fn)));
62
- return { subagentName, withBrainSinks };
65
+ return { subagentName, withBrainSinks, withExtraBodyDroppedSink: createExtraBodyDroppedScope(notice) };
63
66
  }
@@ -9,9 +9,10 @@ import { usageCostMicroUsd } from "./usage-accounting.js";
9
9
  import { advanceCadenceClock, reduceToolEnd } from "./turn-attachments.js";
10
10
  import { gatedCallIdOf } from "./park-commit.js";
11
11
  import { hasVerifiableStructureSignal } from "./grounding-signal.js";
12
- import { batchResponseDigest, toolEndBodyFrom } from "./tool-end-body.js";
12
+ import { announceToolCall, batchResponseDigest, emitSettled } from "./tool-end-body.js";
13
13
  import { createResponseModelSeat } from "./response-model-seat.js";
14
14
  import { createToolCallIdFoldSeat } from "./tool-call-id-fold-seat.js";
15
+ import { createFinishReasonSeat } from "./finish-reason-seat.js";
15
16
  import { createToolTurnIncompleteSeat } from "./tool-turn-repair-seat.js";
16
17
  import { wireOf } from "../tool-name-readings.js";
17
18
  import { rosterToolName } from "../tool-roster.js";
@@ -20,7 +21,13 @@ export function createHarnessHandlers(input) {
20
21
  const responseModelSeat = createResponseModelSeat(deps.runnerHooks.onNotice, { sessionId: prepared.sessionId, runId: prepared.runId });
21
22
  const toolCallIdFoldSeat = createToolCallIdFoldSeat(deps.runnerHooks.onNotice, { sessionId: prepared.sessionId, runId: prepared.runId });
22
23
  const toolTurnIncompleteSeat = createToolTurnIncompleteSeat(deps.runnerHooks.onNotice, { sessionId: prepared.sessionId, runId: prepared.runId });
24
+ const finishReasonSeat = createFinishReasonSeat(deps.runnerHooks.onNotice, { sessionId: prepared.sessionId, runId: prepared.runId });
23
25
  const { spec, queue, internals, ident, parentToolCallId, subagentName, pushContent, emitCommitted, startedToolCallIds, toolStartAt, toolProgress, writeFamilyOf, toolLabels, postToolBatchHook, batchArgs, internalsNotifier } = deps;
26
+ const frames = { push: (f) => pushContent({ ...f, ...ident() }), structured: prepared.structuredProjector };
27
+ const startOf = (e) => {
28
+ const label = toolLabels.get(e.toolName);
29
+ return { toolCallId: e.toolCallId, spelledName: e.toolName, wireName: rosterToolName(prepared.toolRosterDeltas.current, e.toolName), ...(label !== undefined ? { label } : {}), args: e.args };
30
+ };
24
31
  let lastWorkspaceCwd = prepared.cwdRef?.current;
25
32
  const announceWorkspaceMove = () => {
26
33
  const cwdNow = prepared.cwdRef?.current;
@@ -155,6 +162,7 @@ export function createHarnessHandlers(input) {
155
162
  rs.turn.turnResponseModel = responseModelSeat.observe(m);
156
163
  toolCallIdFoldSeat.observe(m);
157
164
  toolTurnIncompleteSeat.observe(m);
165
+ finishReasonSeat.observe(m);
158
166
  }
159
167
  if (m.role === "assistant") {
160
168
  const rep = m.repetition;
@@ -202,7 +210,6 @@ export function createHarnessHandlers(input) {
202
210
  const startAt = Date.now();
203
211
  toolStartAt.set(event.toolCallId, startAt);
204
212
  startedToolCallIds.add(event.toolCallId);
205
- toolProgress.noteStart(event.toolCallId, event.toolName);
206
213
  batchArgs?.set(event.toolCallId, event.args);
207
214
  stats.toolCalls += 1;
208
215
  if (spec.finalVerification === true && !(rs.counters.finalVerifyInjections === 0 ? rs.counters.groundingSignalPreR9 : rs.counters.groundingSignalPostR9) && hasVerifiableStructureSignal(event.args)) {
@@ -213,19 +220,11 @@ export function createHarnessHandlers(input) {
213
220
  }
214
221
  const activityArg = primaryActivityArg(event.args);
215
222
  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");
216
- pushContent({
217
- type: "tool_start",
218
- toolCallId: event.toolCallId,
219
- toolName: event.toolName,
220
- ...(toolLabels.get(event.toolName) !== undefined ? { label: toolLabels.get(event.toolName) } : {}),
221
- args: event.args,
222
- ...ident(),
223
- });
223
+ announceToolCall(prepared.toolOccurrences, startOf(event), frames);
224
224
  };
225
225
  const onToolEnd = (event) => {
226
226
  const toolStarted = toolStartAt.get(event.toolCallId);
227
227
  toolStartAt.delete(event.toolCallId);
228
- toolProgress.noteEnd(event.toolCallId);
229
228
  const toolNow = Date.now();
230
229
  if (!rs.counters.wroteThisRun && (prepared.toolEffects.get(wireOf("verify.wroteThisRun", { toolName: rosterToolName(prepared.toolRosterDeltas.current, event.toolName) })) ?? "write") !== "read") {
231
230
  rs.counters.wroteThisRun = true;
@@ -251,18 +250,6 @@ export function createHarnessHandlers(input) {
251
250
  batchArgs?.delete(event.toolCallId);
252
251
  }
253
252
  }
254
- emitTrace(rs.telemetry.tracer, () => ({
255
- kind: "tool.call",
256
- version: 1,
257
- taskId: rs.telemetry.taskId,
258
- name: event.toolName,
259
- toolCallId: event.toolCallId,
260
- turn: stats.turns + 1,
261
- durationMs: toolStarted !== undefined ? toolNow - toolStarted : 0,
262
- ok: !event.isError,
263
- ts: toolNow,
264
- }));
265
- internalsNotifier.notify(() => observeThenableRejection(internals?.onActivity?.({ phase: "end", toolCallId: event.toolCallId, toolName: event.toolName, isError: event.isError, at: toolNow }), internalsNotifier, "runtask.onActivity.end"), "runtask.onActivity.end");
266
253
  if (prepared.lspDiagnostics && !event.isError) {
267
254
  const name = event.toolName;
268
255
  if (name === "Edit" || name === "Write" || name === "NotebookEdit") {
@@ -272,18 +259,24 @@ export function createHarnessHandlers(input) {
272
259
  prepared.lspDiagnostics.nudge(p);
273
260
  }
274
261
  }
275
- const gate = prepared.gateOutcomes.get(event.toolCallId);
276
- if (gate !== undefined)
277
- prepared.gateOutcomes.delete(event.toolCallId);
278
- pushContent({
279
- type: "tool_end",
280
- toolCallId: event.toolCallId,
281
- toolName: event.toolName,
282
- ...(toolLabels.get(event.toolName) !== undefined ? { label: toolLabels.get(event.toolName) } : {}),
262
+ const settled = emitSettled(prepared.toolOccurrences, startOf(event), {
263
+ result: event.result,
283
264
  isError: event.isError,
284
- ...toolEndBodyFrom(event.result, event.isError, prepared.structuredProjector, gate, prepared.abortController.signal.aborted ? gatedCallIdOf(prepared) : undefined),
285
- ...ident(),
286
- });
265
+ ...(event.notExecuted === true ? { notExecuted: true } : {}),
266
+ ...(() => { const id = prepared.abortController.signal.aborted ? gatedCallIdOf(prepared) : undefined; return id !== undefined ? { gatedCallIdOfRun: id } : {}; })(),
267
+ }, frames);
268
+ emitTrace(rs.telemetry.tracer, () => ({
269
+ kind: "tool.call",
270
+ version: 1,
271
+ taskId: rs.telemetry.taskId,
272
+ name: event.toolName,
273
+ toolCallId: event.toolCallId,
274
+ turn: stats.turns + 1,
275
+ durationMs: toolStarted !== undefined ? toolNow - toolStarted : 0,
276
+ ok: !settled.isError,
277
+ ts: toolNow,
278
+ }));
279
+ internalsNotifier.notify(() => observeThenableRejection(internals?.onActivity?.({ phase: "end", toolCallId: event.toolCallId, toolName: event.toolName, isError: settled.isError, at: toolNow }), internalsNotifier, "runtask.onActivity.end"), "runtask.onActivity.end");
287
280
  announceWorkspaceMove();
288
281
  if (spec.outputSchema && event.toolName === OUTPUT_TOOL_NAME) {
289
282
  if (event.isError) {
@@ -38,8 +38,6 @@ export interface RunLegInput<R> {
38
38
  resume: ResumeRun | undefined;
39
39
  /** borrowed-mutable — the run's mutable state: the limit flags and the platform terminal are written by the entrance gates. */
40
40
  rs: RunState;
41
- /** borrowed-readonly — the trusted spawn-side fact the rejection boundary reads (a delegated child's bare refusal halts no batch). */
42
- isDelegatedChild: boolean;
43
41
  /** borrowed-readonly — the API-boundary attribution snapshot of the objective's actor (the objective leg's speaker envelope). */
44
42
  entryActor: ActorAssertion | undefined;
45
43
  /** borrowed-readonly — the effective walltime window (undefined = unbounded): `<= 0` refuses the first turn. */
@@ -13,18 +13,18 @@ import { SKILL_TOOL_NAME } from "./synthetic-tools.js";
13
13
  import { computeCostMicroUsd } from "../pricing.js";
14
14
  import { mintSystemReminder } from "../reminder-mint.js";
15
15
  import { hasDestroy } from "../remote-env.js";
16
- import { advertisedWritableRootsSeat, policyCannotAnswer, policyRefusalMessage, refuseOutOfContractDecision } from "../tool-policy.js";
16
+ import { advertisedWritableRootsSeat, exemptRootsSeat, humanRefusalSentence, policyCannotAnswer, policyRefusalMessage, refuseOutOfContractDecision } from "../tool-policy.js";
17
17
  import { callFaceSeat, judgeParkedToolIdentity, parkedRowLiveFace, rosterEntryNamed } from "../tool-roster.js";
18
18
  import { deliverEngineNotice } from "../types.js";
19
19
  import { delimitUntrusted, inlineUntrusted, REVIEWER_NOTE_MAX_BODY, sanitizeUntrustedText } from "../untrusted-text.js";
20
- import { errorCodeOf } from "./assemble-result.js";
20
+ import { errorCodeOf } from "./terminal-account.js";
21
21
  import { DEFAULT_PRECALL_OUTPUT_TOKENS, platformLimitTerminal } from "./clock-and-limits.js";
22
22
  import { mintOutputStyleReminder, owedPostureText } from "./compaction-restate.js";
23
23
  import { deepJsonEqual, resumeContinuation } from "./decide-continuation.js";
24
24
  import { chainCannotJudge } from "./call-hook-stations.js";
25
25
  import { settleExecutionRecord } from "./execution-record.js";
26
26
  import { holdPrompt } from "./prompt-block.js";
27
- import { mintGateOutcome } from "./gate-exit.js";
27
+ import { frozenInputSnapshot } from "./gate-exit.js";
28
28
  import { withGateTimeout } from "../gate-bounded-await.js";
29
29
  import { resolveGitLegDelivery, wrapGitFrame } from "./git-leg-delivery.js";
30
30
  import { GIT_STATUS_ECHO_PREVIEW } from "./git-status-frame.js";
@@ -32,7 +32,7 @@ import { toImageContent } from "./image.js";
32
32
  import { maybeHumanRejectionHalt } from "./prepare-gate-stations.js";
33
33
  import { nextHumanInputSeq } from "./steer-admission.js";
34
34
  import { settleTeardownLeg } from "./teardown-bounded.js";
35
- import { toolEndBodyFrom, toolResultMsg } from "./tool-end-body.js";
35
+ import { announceToolCall, emitSettled, toolResultMsg } from "./tool-end-body.js";
36
36
  import { announceListingTruncation } from "../skill-listing-budget.js";
37
37
  import { attachmentEnvelopeTags, collectDateChange, commitAgentListing, commitSkillsListing, reduceToolEnd, renderAgentListingFrame, renderOrphanedBackgroundTasks, renderSkillsListingFrame, stampWriteAnchor } from "./turn-attachments.js";
38
38
  import { flushOwedAnnouncedSnapshot } from "./announce-once-ledger.js";
@@ -40,7 +40,7 @@ import { asThrownError, thrownMarksOf, thrownText } from "../thrown-value.js";
40
40
  import { ruleSourcePhrase } from "../rule-denial-sentence.js";
41
41
  import { wireOf } from "../tool-name-readings.js";
42
42
  export async function runLeg(input) {
43
- const { spec, queue, prepared, resume, rs, isDelegatedChild, entryActor, effectiveTimeoutMs, timeout, pushContent, ident, emitCommitted, writeFamilyOf, startedToolCallIds, announceWorkspaceMove, withBrainSinks, flushGitMirror, loopLatch, notificationLane, unsubscribeTaskNotifications, unsubGitRetry, unsubBoundary, unsub, runner, next } = input;
43
+ 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;
44
44
  let final;
45
45
  let threw;
46
46
  let abortedLive = false;
@@ -112,7 +112,7 @@ export async function runLeg(input) {
112
112
  rs.limits.budgetAxis = "cost";
113
113
  }
114
114
  else {
115
- let continuation = resumeContinuation(resume, prepared.reminderMark, prepared.fullShellReachable);
115
+ let continuation = resumeContinuation(resume, prepared.reminderMark, prepared.fullShellReachable, prepared.hookIdentity.isDelegatedChild);
116
116
  const bgSnapshot = resume.cp.state.runningBackgroundTasks;
117
117
  let orphanTasks = [];
118
118
  if (bgSnapshot !== undefined && bgSnapshot.length > 0) {
@@ -239,7 +239,7 @@ export async function runLeg(input) {
239
239
  }
240
240
  const pending = resume.cp.pendingAction;
241
241
  const rejectionHalt = pending.kind === "tool_approval" && resume.outcome.gate === "policy_ask"
242
- ? maybeHumanRejectionHalt({ gate: resume.outcome.gateOutcome, isDelegatedChild, toolName: pending.toolName, toolCallId: pending.toolCallId })
242
+ ? maybeHumanRejectionHalt({ gate: resume.outcome.gateOutcome, isDelegatedChild: prepared.hookIdentity.isDelegatedChild, toolName: pending.toolName, toolCallId: pending.toolCallId })
243
243
  : undefined;
244
244
  if (rejectionHalt !== undefined && pending.kind === "tool_approval")
245
245
  prepared.batchHaltRef.current = { rejectedToolCallId: pending.toolCallId };
@@ -572,27 +572,26 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
572
572
  const resolvedArgs = humanRewrite !== undefined ? humanRewrite : pendingAction.args;
573
573
  const pendingLabel = (() => { const l = prepared.tools.find((t) => t.name === pendingAction.toolName)?.label; return l !== undefined && l !== pendingAction.toolName ? { label: l } : {}; })();
574
574
  const spelledName = pendingAction.names?.[0] ?? pendingAction.toolName;
575
- emit({ type: "tool_start", toolCallId: pendingAction.toolCallId, toolName: spelledName, ...pendingLabel, args: resolvedArgs });
576
- const settleEnd = async (isError, result, gate = decidedGate) => {
577
- prepared.toolProgressRef.current?.noteEnd(pendingAction.toolCallId);
578
- emit({ type: "tool_end", toolCallId: pendingAction.toolCallId, toolName: spelledName, ...pendingLabel, isError, ...toolEndBodyFrom(result, isError, prepared.structuredProjector, gate) });
575
+ const occurrences = prepared.toolOccurrences;
576
+ const callStart = { toolCallId: pendingAction.toolCallId, spelledName, wireName: pendingAction.toolName, ...pendingLabel, args: resolvedArgs };
577
+ announceToolCall(occurrences, callStart, { push: emit });
578
+ occurrences.gateRound(pendingAction.toolCallId, decidedGate, frozenInputSnapshot(resolvedArgs));
579
+ const settleEnd = async (isError, result, refusedBy) => {
580
+ if (refusedBy !== undefined)
581
+ occurrences.refuse(pendingAction.toolCallId, refusedBy);
582
+ const gate = emitSettled(occurrences, callStart, { result, isError }, { push: emit, structured: prepared.structuredProjector }).gate ?? decidedGate;
579
583
  const word = await resume.recordExecutionOutcome(gate);
580
584
  settleExecutionRecord(runner.deps.onNotice, word, { toolName: pendingAction.toolName, gate, sessionId: prepared.sessionId, runId: prepared.runId, scope: resume.cp.scope, ...(resume.cp.checkpointId !== undefined ? { checkpointId: resume.cp.checkpointId } : {}) });
581
585
  };
582
- const vetoed = (layer) => mintGateOutcome({
583
- deniedBy: layer,
584
- ...(outcome.gateOutcome?.settlement !== undefined && outcome.gateOutcome.origin !== undefined ? { settled: { settlement: outcome.gateOutcome.settlement, origin: outcome.gateOutcome.origin } } : {}),
585
- });
586
586
  if (outcome.decision === "deny") {
587
587
  const settlementKind = outcome.gateOutcome?.settlement?.kind;
588
- const defaultDenial = settlementKind === "park_sla_expired"
589
- ? `No one answered the approval request for the pending tool call "${pendingAction.toolName}" — the approval window elapsed with no answer, so it was not executed.`
590
- : `The pending tool call "${pendingAction.toolName}" was denied by an approver.`;
591
588
  const reason = settlementKind === "policy_refused"
592
589
  ? policyRefusalMessage(pendingAction.toolName, undefined, decidersNote(outcome.reason))
593
- : outcome.reason
594
- ? delimitUntrusted("reviewer note", outcome.reason, REVIEWER_NOTE_MAX_BODY)
595
- : defaultDenial;
590
+ : settlementKind === "park_sla_expired"
591
+ ? outcome.reason
592
+ ? delimitUntrusted("reviewer note", outcome.reason, REVIEWER_NOTE_MAX_BODY)
593
+ : `No one answered the approval request for the pending tool call "${pendingAction.toolName}" — the approval window elapsed with no answer, so it was not executed.`
594
+ : humanRefusalSentence("tool use", outcome.reason, prepared.hookIdentity.isDelegatedChild);
596
595
  await settleEnd(true, { content: formatHookFeedback(reason, prepared.reminderMark) });
597
596
  const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, formatHookFeedback(reason, prepared.reminderMark), true));
598
597
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
@@ -608,18 +607,18 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
608
607
  const screened = await prepared.approvedCallScreen?.({ toolCallId: pendingAction.toolCallId, toolName: pendingAction.toolName, args: structuredClone(resolvedArgs), decidedBy: outcome.hostDecision.decidedBy });
609
608
  if (screened !== undefined && "refused" in screened) {
610
609
  const hookDenial = formatHookFeedback(screened.refused, prepared.reminderMark);
611
- await settleEnd(true, { content: hookDenial }, vetoed("hook"));
610
+ await settleEnd(true, { content: hookDenial }, "hook");
612
611
  emitCommitted(await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, hookDenial, true)), "toolResult", pendingAction.toolCallId);
613
612
  return;
614
613
  }
615
614
  const executedArgs = humanRewrite !== undefined ? resolvedArgs : screened !== undefined ? screened.args : resolvedArgs;
616
615
  const unseen = !deepJsonEqual(executedArgs, pendingAction.args);
617
616
  let beltReading;
618
- const beltReq = () => ({ toolName: pendingAction.toolName, args: executedArgs, toolCallId: pendingAction.toolCallId, ...callFaceSeat(parkedRowLiveFace(prepared.toolRosterDeltas.current, pendingAction)), budget: beltBudget, ...(prepared.cwdRef !== undefined ? { cwd: prepared.cwdRef.current } : {}), ...(prepared.handsRoot !== undefined ? { root: prepared.handsRoot } : {}), ...advertisedWritableRootsSeat(prepared.advertisedWritableDirs), ...(beltReading !== undefined ? { targetReading: beltReading } : {}) });
617
+ const beltReq = () => ({ toolName: pendingAction.toolName, args: executedArgs, toolCallId: pendingAction.toolCallId, ...callFaceSeat(parkedRowLiveFace(prepared.toolRosterDeltas.current, pendingAction)), budget: beltBudget, ...(prepared.cwdRef !== undefined ? { cwd: prepared.cwdRef.current } : {}), ...(prepared.handsRoot !== undefined ? { root: prepared.handsRoot } : {}), ...advertisedWritableRootsSeat(prepared.advertisedWritableDirs), ...exemptRootsSeat(prepared.exemptRoots), ...(beltReading !== undefined ? { targetReading: beltReading } : {}) });
619
618
  const unjudgeable = unseen ? chainCannotJudge(resume.cp.state.inheritedGate) : undefined;
620
619
  if (unjudgeable !== undefined) {
621
620
  const chainDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: its input changed after the approval and the inherited ancestor chain cannot judge the changed input (${unjudgeable}). This approval is spent — the call has to be re-issued.`, prepared.reminderMark);
622
- await settleEnd(true, { content: chainDenial }, vetoed("policy"));
621
+ await settleEnd(true, { content: chainDenial }, "policy");
623
622
  emitCommitted(await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, chainDenial, true)), "toolResult", pendingAction.toolCallId);
624
623
  return;
625
624
  }
@@ -644,7 +643,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
644
643
  ? " (the call as it would run requires a person's approval, and this decision was the deployment's policy)"
645
644
  : " (the policy rewrote these bytes to a value that was not approved)";
646
645
  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);
647
- await settleEnd(true, { content: editedDenial }, vetoed("policy"));
646
+ await settleEnd(true, { content: editedDenial }, "policy");
648
647
  const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, editedDenial, true));
649
648
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
650
649
  return;
@@ -654,7 +653,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
654
653
  const gateOrgGoverned = realApprovalOrgFact(gateRealApproval) !== undefined;
655
654
  if (gateOrgGoverned && prepared.permissionRuleOrg === undefined) {
656
655
  const unwiredDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: its approval was minted under organization governance (${gateRealApproval.origin}), and this worker has no org adjudication wiring — a governed approval may only be redeemed where governance can be enforced. This approval is spent; re-issue the call on an org-wired worker.`, prepared.reminderMark);
657
- await settleEnd(true, { content: unwiredDenial }, vetoed("org"));
656
+ await settleEnd(true, { content: unwiredDenial }, "org");
658
657
  const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, unwiredDenial, true));
659
658
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
660
659
  return;
@@ -688,7 +687,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
688
687
  ? ` Governance disclosures: ${inlineUntrusted(org.disclosures.join("; "), ORG_DISCLOSURE_MAX_CHARS)}.`
689
688
  : "";
690
689
  const orgDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: ${blocked}.${orgDisclosures} This approval is spent — the call has to be re-issued and ${unanswered ? "decided by a person" : "approved again once organization policy permits it"}.`, prepared.reminderMark);
691
- await settleEnd(true, { content: orgDenial }, vetoed("org"));
690
+ await settleEnd(true, { content: orgDenial }, "org");
692
691
  const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, orgDenial, true));
693
692
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
694
693
  return;
@@ -698,7 +697,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
698
697
  const narrowed = refuseOutOfContractDecision(await prepared.denyNarrowingPolicy.check(beltReq(), prepared.abortController.signal));
699
698
  if (narrowed.action === "deny") {
700
699
  const narrowedDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" is now denied by ${ruleSourcePhrase("narrowing")} and was not executed${narrowed.message ? `: ${narrowed.message}` : ""}.`, prepared.reminderMark);
701
- await settleEnd(true, { content: narrowedDenial }, vetoed("policy"));
700
+ await settleEnd(true, { content: narrowedDenial }, "policy");
702
701
  const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, narrowedDenial, true));
703
702
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
704
703
  return;
@@ -707,7 +706,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
707
706
  const skillRefusal = skillRowRefusal(prepared.skillGrants, beltReq());
708
707
  if (skillRefusal !== undefined) {
709
708
  const skillDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: ${skillRefusal.message}. This approval is spent — the call has to be re-issued.`, prepared.reminderMark);
710
- await settleEnd(true, { content: skillDenial }, vetoed("policy"));
709
+ await settleEnd(true, { content: skillDenial }, "policy");
711
710
  emitCommitted(await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, skillDenial, true)), "toolResult", pendingAction.toolCallId);
712
711
  return;
713
712
  }
@@ -730,7 +729,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
730
729
  ? `a standing deny rule of yours (${disclosedRuleSet(read.hit?.rules ?? [])}) now refuses it`
731
730
  : `it could not be read against your standing deny/ask rules (${read.reason})`;
732
731
  const ruleDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: ${why}. This approval is spent — the call has to be re-issued and approved again.`, prepared.reminderMark);
733
- await settleEnd(true, { content: ruleDenial }, vetoed("persisted_rule"));
732
+ await settleEnd(true, { content: ruleDenial }, "persisted_rule");
734
733
  const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, ruleDenial, true));
735
734
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
736
735
  return;
@@ -754,7 +753,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
754
753
  }
755
754
  if (!answered || verdict.disposition === "refuse" || (unseen && verdict.disposition !== "vouch")) {
756
755
  const readDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: ${verdict.sentence ?? "the read boundary does not vouch for what it reads on this leg"} This approval is spent — the call has to be re-issued and approved again.`, prepared.reminderMark);
757
- await settleEnd(true, { content: readDenial, ...(verdict.details !== undefined ? { details: verdict.details } : {}) }, vetoed("read_boundary"));
756
+ await settleEnd(true, { content: readDenial, ...(verdict.details !== undefined ? { details: verdict.details } : {}) }, "read_boundary");
758
757
  const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, readDenial, true));
759
758
  emitCommitted(eid, "toolResult", pendingAction.toolCallId);
760
759
  return;
@@ -765,7 +764,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
765
764
  const grantRefusal = parkedSkillApprovalRefusal(pendingAction, executedArgs, prepared.skillSpecs, SKILL_TOOL_NAME, "execution");
766
765
  if (grantRefusal !== undefined) {
767
766
  const grantDenial = formatHookFeedback(grantRefusal, prepared.reminderMark);
768
- await settleEnd(true, { content: grantDenial }, vetoed("policy"));
767
+ await settleEnd(true, { content: grantDenial }, "policy");
769
768
  emitCommitted(await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, grantDenial, true)), "toolResult", pendingAction.toolCallId);
770
769
  return;
771
770
  }
@@ -778,7 +777,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
778
777
  const args = executedArgs;
779
778
  screened?.admit();
780
779
  onExecuteStart?.(pendingAction.toolCallId);
781
- prepared.toolProgressRef.current?.noteStart(pendingAction.toolCallId, pendingAction.toolName);
780
+ occurrences.execute(pendingAction.toolCallId);
782
781
  prepared.suspendProgressRef.executedApproved = true;
783
782
  const finalize = (executed) => prepared.harness.finalizeToolCall({ type: "toolCall", id: pendingAction.toolCallId, name: spelledName, arguments: executedArgs }, executedArgs, executed);
784
783
  let res;
@@ -2,13 +2,14 @@ import { DEFAULT_COMPACTION_INSTRUCTIONS, maybeCompact } from "../auto-compactio
2
2
  import { eventDefaultOn } from "../../prompt-assembly/event-registry.js";
3
3
  import { appendInterruptionMarker, reconcileInterruptedSession } from "../session-reconcile.js";
4
4
  import { emitTrace } from "../trace.js";
5
- import { answerSettled, errorCodeOf } from "./assemble-result.js";
5
+ import { answerSettled } from "./assemble-result.js";
6
+ import { errorCodeOf } from "./terminal-account.js";
6
7
  import { awaitChargeWithSlowDisclosure, discloseUnevaluableWindow } from "./clock-and-limits.js";
7
8
  import { buildWorkingFileAttachments, centerAdoptionOption, contextInstructionFilesOption, emitInputTruncated, forkContextOption, legCompactionSettings, legContextOverlayOption } from "./compaction-call-options.js";
8
9
  import { compactionHookOptions, recordCompactionReuse, seamCCompactionOptions } from "./compaction-seams.js";
9
10
  import { compactionRestateOptions } from "./compaction-restate.js";
10
11
  import { MAX_CONSECUTIVE_COMPACTION_FAILURES } from "./compaction-knobs.js";
11
- import { reconciledToolEndBody } from "./tool-end-body.js";
12
+ import { emitSettled, reconciledEnd } from "./tool-end-body.js";
12
13
  import { asThrownError, thrownText } from "../thrown-value.js";
13
14
  export async function runTerminalAdoption(input) {
14
15
  const { spec, queue, prepared, rs, stats, ident, emitCommitted, startedToolCallIds, toolLabels, timeout, compactionBrain, compactionBreaker, windowSafetyOptions, undrainedUserAtEnd, userInputLostAtEnd, final, abortedLive, userInterruptedLive, runner, sessions, next } = input;
@@ -42,7 +43,7 @@ export async function runTerminalAdoption(input) {
42
43
  const report = await reconcileInterruptedSession(prepared.session, prepared.toolEffects, undefined, startedToolCallIds);
43
44
  orphansClosed = report.recovered.length;
44
45
  for (const orphan of report.recovered) {
45
- queue.push({ type: "tool_end", toolCallId: orphan.toolCallId, toolName: orphan.toolName, ...(toolLabels.has(orphan.toolName) ? { label: toolLabels.get(orphan.toolName) } : {}), isError: true, ...reconciledToolEndBody(orphan, prepared.structuredProjector), ...ident() });
46
+ emitSettled(prepared.toolOccurrences, { toolCallId: orphan.toolCallId, spelledName: orphan.toolName, ...(toolLabels.has(orphan.toolName) ? { label: toolLabels.get(orphan.toolName) } : {}), args: orphan.args }, reconciledEnd(orphan), { push: (f) => queue.push({ ...f, ...ident() }), structured: prepared.structuredProjector });
46
47
  emitCommitted(orphan.entryId, "toolResult", orphan.toolCallId);
47
48
  }
48
49
  reconcileComplete = true;