@sema-agent/core 7.48.0 → 7.49.1

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 (421) hide show
  1. package/CHANGELOG.md +457 -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 +21 -28
  52. package/dist/core/arg-summary.js +235 -88
  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 +43 -11
  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 +21 -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 +29 -36
  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/tool-turn-repair-seat.d.ts +28 -4
  243. package/dist/core/runner/tool-turn-repair-seat.js +36 -13
  244. package/dist/core/runner/turn-attachments.d.ts +1 -1
  245. package/dist/core/runner/write-protection-station.d.ts +21 -9
  246. package/dist/core/runner/write-protection-station.js +20 -17
  247. package/dist/core/runner-deps.d.ts +12 -22
  248. package/dist/core/secret-env.d.ts +16 -5
  249. package/dist/core/secret-env.js +23 -63
  250. package/dist/core/sensitive-path-policy.d.ts +19 -18
  251. package/dist/core/sensitive-path-policy.js +73 -49
  252. package/dist/core/session-reconcile.d.ts +3 -0
  253. package/dist/core/session-reconcile.js +5 -4
  254. package/dist/core/session-store.d.ts +5 -0
  255. package/dist/core/session-store.js +12 -0
  256. package/dist/core/session.d.ts +13 -0
  257. package/dist/core/shared-memory/normalize.d.ts +17 -4
  258. package/dist/core/shared-memory/normalize.js +7 -7
  259. package/dist/core/shell-lexer.js +5 -4
  260. package/dist/core/shell-wrapper-projection.js +1 -1
  261. package/dist/core/skill-grant.js +1 -1
  262. package/dist/core/store-contracts/checkpoint-store-contract.js +13 -0
  263. package/dist/core/store-contracts/mailbox-store-contract.d.ts +7 -14
  264. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +27 -0
  265. package/dist/core/store-contracts/session-store-incarnation-contract.js +92 -0
  266. package/dist/core/stub-env.d.ts +2 -0
  267. package/dist/core/stub-env.js +1 -0
  268. package/dist/core/synthetic-read-verdict.js +2 -2
  269. package/dist/core/task-event.d.ts +59 -5
  270. package/dist/core/task-result.d.ts +1 -1
  271. package/dist/core/task-spec.d.ts +42 -9
  272. package/dist/core/terminal-cause.d.ts +94 -11
  273. package/dist/core/tighten-task-spec.d.ts +5 -4
  274. package/dist/core/tighten-task-spec.js +20 -25
  275. package/dist/core/tool-catalog-entries.d.ts +5 -7
  276. package/dist/core/tool-catalog-entries.js +14 -15
  277. package/dist/core/tool-face.d.ts +47 -0
  278. package/dist/core/tool-face.js +5 -0
  279. package/dist/core/tool-model-gate.d.ts +5 -5
  280. package/dist/core/tool-name-aliases.d.ts +26 -2
  281. package/dist/core/tool-name-aliases.js +13 -0
  282. package/dist/core/tool-name-list.d.ts +30 -0
  283. package/dist/core/tool-name-list.js +55 -0
  284. package/dist/core/tool-name-readings.d.ts +1 -9
  285. package/dist/core/tool-name-readings.js +1 -3
  286. package/dist/core/tool-policy.d.ts +195 -85
  287. package/dist/core/tool-policy.js +165 -380
  288. package/dist/core/tool-registry.d.ts +44 -1
  289. package/dist/core/tool-registry.js +26 -0
  290. package/dist/core/tool-roster.d.ts +19 -1
  291. package/dist/core/tool-roster.js +21 -2
  292. package/dist/core/tool-spec-members.d.ts +45 -0
  293. package/dist/core/tool-spec-members.js +169 -0
  294. package/dist/core/tool-spec.d.ts +46 -8
  295. package/dist/core/tools.d.ts +6 -2
  296. package/dist/core/tools.js +8 -4
  297. package/dist/core/untrusted-egress.js +29 -26
  298. package/dist/core/untrusted-text.d.ts +13 -10
  299. package/dist/core/untrusted-text.js +6 -44
  300. package/dist/core/workflow-journal-store.d.ts +4 -1
  301. package/dist/core/write-protect.d.ts +65 -29
  302. package/dist/core/write-protect.js +235 -177
  303. package/dist/engine/compaction/compaction.d.ts +2 -2
  304. package/dist/engine/execution-env/node-execution-env.d.ts +5 -23
  305. package/dist/engine/execution-env/node-execution-env.js +16 -38
  306. package/dist/engine/execution-env/symlink-chain.d.ts +23 -0
  307. package/dist/engine/execution-env/symlink-chain.js +32 -0
  308. package/dist/engine/harness/types.d.ts +7 -0
  309. package/dist/engine/llm/tool-turns.d.ts +3 -0
  310. package/dist/engine/llm/tool-turns.js +1 -0
  311. package/dist/engine/llm/types.d.ts +59 -23
  312. package/dist/engine/loop/agent-loop.js +16 -2
  313. package/dist/engine/session/memory-repo.js +11 -3
  314. package/dist/engine/session/repo-utils.d.ts +8 -0
  315. package/dist/engine/session/repo-utils.js +13 -0
  316. package/dist/index.d.ts +20 -23
  317. package/dist/index.js +17 -20
  318. package/dist/internal/harness.d.ts +1 -1
  319. package/dist/internal/harness.js +1 -1
  320. package/dist/internal/llm.d.ts +2 -2
  321. package/dist/internal/llm.js +1 -1
  322. package/dist/orchestration/governance-baseline-validity.js +1 -1
  323. package/dist/orchestration/run-spec.js +3 -3
  324. package/dist/orchestration/run-workflow-tool.d.ts +16 -35
  325. package/dist/orchestration/run-workflow-tool.js +38 -78
  326. package/dist/orchestration/workflow-governance.d.ts +21 -25
  327. package/dist/orchestration/workflow-governance.js +38 -78
  328. package/dist/orchestration/workflow-primitives.d.ts +7 -22
  329. package/dist/orchestration/workflow-primitives.js +5 -12
  330. package/dist/orchestration/workflow-types.d.ts +1 -1
  331. package/dist/orchestration/workflow.d.ts +61 -11
  332. package/dist/orchestration/workflow.js +189 -117
  333. package/dist/scenarios/full-body.d.ts +1 -1
  334. package/dist/shell/lex.d.ts +0 -21
  335. package/dist/shell/lex.js +250 -68
  336. package/dist/shell/shell-words.d.ts +35 -0
  337. package/dist/shell/shell-words.js +65 -0
  338. package/dist/stores/file/checkpoint-store.d.ts +5 -5
  339. package/dist/stores/file/checkpoint-store.js +5 -2
  340. package/dist/stores/file/index.d.ts +0 -8
  341. package/dist/stores/file/index.js +0 -12
  342. package/dist/stores/file/session-store.d.ts +3 -0
  343. package/dist/stores/file/session-store.js +44 -19
  344. package/dist/tools/artifact/artifact-tool.js +2 -0
  345. package/dist/tools/fs/bash-program-position.d.ts +12 -4
  346. package/dist/tools/fs/bash-program-position.js +32 -9
  347. package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
  348. package/dist/tools/fs/bash-readonly-classifier.js +8 -7
  349. package/dist/tools/fs/containment-face.d.ts +4 -0
  350. package/dist/tools/fs/containment-face.js +3 -0
  351. package/dist/tools/fs/fs-shared.d.ts +10 -0
  352. package/dist/tools/fs/fs-shared.js +18 -0
  353. package/dist/tools/fs/fs-write.js +4 -2
  354. package/dist/tools/fs/index.d.ts +1 -1
  355. package/dist/tools/fs/program-read-model.d.ts +46 -20
  356. package/dist/tools/fs/program-read-model.js +50 -20
  357. package/dist/tools/fs/program-read-model.rows.d.ts +0 -14
  358. package/dist/tools/fs/program-read-model.rows.js +16 -15
  359. package/dist/tools/fs/read-deny-home.d.ts +33 -47
  360. package/dist/tools/fs/read-deny-home.js +35 -49
  361. package/dist/tools/fs/read-deny.d.ts +23 -22
  362. package/dist/tools/fs/read-deny.js +114 -89
  363. package/dist/tools/fs/removal-targets.d.ts +56 -23
  364. package/dist/tools/fs/removal-targets.js +65 -87
  365. package/dist/tools/fs/safety.d.ts +29 -22
  366. package/dist/tools/fs/safety.js +17 -11
  367. package/dist/tools/fs/search.js +10 -8
  368. package/dist/tools/fs/shell-read-argv.js +1 -1
  369. package/dist/tools/fs/shell-read-bindings.d.ts +169 -37
  370. package/dist/tools/fs/shell-read-bindings.js +324 -86
  371. package/dist/tools/fs/shell-read-builtins.d.ts +35 -0
  372. package/dist/tools/fs/shell-read-builtins.js +43 -0
  373. package/dist/tools/fs/shell-read-check.d.ts +15 -1
  374. package/dist/tools/fs/shell-read-check.js +67 -43
  375. package/dist/tools/fs/shell-read-establish.js +6 -6
  376. package/dist/tools/fs/shell-read-functions.d.ts +22 -0
  377. package/dist/tools/fs/shell-read-functions.js +29 -0
  378. package/dist/tools/fs/shell-read-judge.d.ts +51 -18
  379. package/dist/tools/fs/shell-read-judge.js +40 -4
  380. package/dist/tools/fs/shell-read-plan.d.ts +12 -6
  381. package/dist/tools/fs/shell-read-plan.js +118 -113
  382. package/dist/tools/fs/shell-read-start.d.ts +29 -6
  383. package/dist/tools/fs/shell-read-start.js +16 -9
  384. package/dist/tools/fs/shell-read-word.js +4 -0
  385. package/dist/tools/fs/shell-read-workdir.d.ts +156 -0
  386. package/dist/tools/fs/shell-read-workdir.js +281 -0
  387. package/dist/tools/fs/shell-read-write-targets.d.ts +5 -2
  388. package/dist/tools/fs/shell-read-write-targets.js +14 -5
  389. package/dist/tools/fs/shell-reentry-text.d.ts +4 -6
  390. package/dist/tools/fs/shell-reentry-text.js +3 -11
  391. package/dist/tools/task-list.d.ts +1 -2
  392. package/dist/tools/web.js +1 -1
  393. package/package.json +4 -1
  394. package/test/export-surface.snapshot.json +107 -143
  395. package/wire-changes/core@7.49.0.json +4765 -0
  396. package/dist/agents/teacher.d.ts +0 -159
  397. package/dist/agents/teacher.js +0 -577
  398. package/dist/agents/team.d.ts +0 -226
  399. package/dist/agents/team.js +0 -257
  400. package/dist/core/strategy-store.d.ts +0 -238
  401. package/dist/core/strategy-store.js +0 -253
  402. package/dist/orchestration/builtin-workflows.d.ts +0 -133
  403. package/dist/orchestration/builtin-workflows.js +0 -159
  404. package/dist/scenarios/env.d.ts +0 -40
  405. package/dist/scenarios/env.js +0 -39
  406. package/dist/scenarios/scenario-registry.d.ts +0 -110
  407. package/dist/scenarios/scenario-registry.js +0 -140
  408. package/dist/scenarios/teacher-quickstart.d.ts +0 -40
  409. package/dist/scenarios/teacher-quickstart.js +0 -12
  410. package/dist/stores/cc/lockfile.d.ts +0 -10
  411. package/dist/stores/cc/lockfile.js +0 -98
  412. package/dist/stores/cc/mailbox-store.d.ts +0 -20
  413. package/dist/stores/cc/mailbox-store.js +0 -255
  414. package/dist/stores/cc/roster-adapter.d.ts +0 -12
  415. package/dist/stores/cc/roster-adapter.js +0 -117
  416. package/dist/stores/cc/sidecar-transcript.d.ts +0 -97
  417. package/dist/stores/cc/sidecar-transcript.js +0 -264
  418. package/dist/stores/cc/task-list-store.d.ts +0 -2
  419. package/dist/stores/cc/task-list-store.js +0 -125
  420. package/dist/stores/file/strategy-store.d.ts +0 -97
  421. package/dist/stores/file/strategy-store.js +0 -341
@@ -126,6 +126,22 @@ export declare class WorkflowJournalIncompatibleError extends Error {
126
126
  readonly code = "workflow.journal_incompatible";
127
127
  constructor(fromRunId: string, ordinal: number);
128
128
  }
129
+ /**
130
+ * Thrown by `ctx.agent` / `ctx.agentStream().result()` when the journal store did not answer the append of the
131
+ * call's result within {@link RunWorkflowOptions.journalAppendTimeoutMs}. A STORE fault, not a run timeout: the
132
+ * run's `totalTimeoutMs` is independent of it, and whichever comes first speaks (the earlier deadline's error
133
+ * is the one the caller sees). The script does not run past the agent whose result may be unrecorded; it is the
134
+ * same exit a rejecting store already has. The timeout does not cancel the write: the store may still land it
135
+ * late (appends are idempotent per ordinal), so a resume of this run replays the agent if the write landed and
136
+ * re-runs it live if not.
137
+ */
138
+ export declare class WorkflowJournalAppendTimeoutError extends Error {
139
+ readonly runId: string;
140
+ readonly ordinal: number;
141
+ readonly timeoutMs: number;
142
+ readonly code = "workflow.journal_append_timeout";
143
+ constructor(runId: string, ordinal: number, timeoutMs: number);
144
+ }
129
145
  /**
130
146
  * A TRUSTED, run-scoped internal channel carrying the workflow **nesting depth** across a process boundary
131
147
  * (design/98 §0.1 BLOCKER3). It is NOT a `TaskSpec` field and NOT a `run_workflow` tool param — a worker or
@@ -215,7 +231,8 @@ export interface WorkflowAgentHandle {
215
231
  * (the worker can't address the leader except by the marker). A steer issued BEFORE the worker's loop goes
216
232
  * live is parked and delivered into the NEXT turn's context (birth-window delivery, bounded — ledger item 36); steers are
217
233
  * delivered in call order, the birth window included. Rejects with `steering.not_running` once the task has
218
- * finished (teardown included).
234
+ * finished (teardown included) — from the start on a handle a resume settled without running it (replayed from
235
+ * the journal, or settled at its parked ordinal).
219
236
  *
220
237
  * `opts.inputId` is a PASS-THROUGH of the underlying `TaskStream.steer` correlation/idempotency key
221
238
  * (design/171 §6.3 — its whole contract, value domain and typed refusals are that verb's; absent ⇒ byte-identical
@@ -230,7 +247,8 @@ export interface WorkflowAgentHandle {
230
247
  steer(content: string, opts?: {
231
248
  inputId?: string;
232
249
  }): Promise<string>;
233
- /** Await the agent's {@link TaskResult} (the same value the eager recording used; idempotent). */
250
+ /** Await the agent's {@link TaskResult} (the same value the eager recording used; idempotent). On a resume that
251
+ * replayed this call it is the journaled result, settled at once. */
234
252
  result(): Promise<TaskResult>;
235
253
  }
236
254
  export interface WorkflowRunContext {
@@ -384,17 +402,32 @@ export interface RunWorkflowOptions {
384
402
  /** Injected clock (design/87 §4.3 — testable without the wall clock). Default `Date.now`. */
385
403
  now?: () => number;
386
404
  /**
387
- * design/97 CORE-7 — the LOAD-BEARING resume journal. With a `journalStore`, every `ctx.agent` result (NOT
388
- * `ctx.agentStream` — see below) is recorded keyed by its deterministic callKey. Supplying `resumeFromRunId`
389
- * (a PRIOR run id, requires `journalStore`) replays the longest UNCHANGED PREFIX of those results instantly and
390
- * runs only the first changed/new call + everything after it live (same script + args → 100% cache hit). A
391
- * `journalStore` WITHOUT `resumeFromRunId` just records (so a future run can resume from THIS run). Replayed
392
- * agents accumulate into `run.stats` (total work) but NOT into `ctx.budget.spent()` (live spend only — a resume
393
- * is not re-charged for cached work). NOT-REPLAYED (they force divergence so the suffix runs live): `ctx.agentStream`
394
- * (a finished result can't be steered — RECORDED for the journal read-face, never replayed) and `ctx.pipeline` (latency-dependent ordinals aren't deterministic —
395
- * a CORE-7.1 follow-on adds stage-scoped deterministic keys). Sequential + `parallel(direct thunks)` replay.
405
+ * design/97 CORE-7 — the LOAD-BEARING resume journal. With a `journalStore`, every agent result — `ctx.agent` and
406
+ * `ctx.agentStream` alike — is recorded keyed by its deterministic callKey. Supplying `resumeFromRunId` (a PRIOR run
407
+ * id, requires `journalStore`) replays the longest UNCHANGED PREFIX of those results instantly and runs only the
408
+ * first changed/new call + everything after it live (same script + args → 100% cache hit). A replayed
409
+ * `ctx.agentStream` call hands back an already-settled handle: `result()` is the journaled result, `steer()` is
410
+ * refused `steering.not_running` (nothing is running). A `journalStore` WITHOUT `resumeFromRunId` just records (so
411
+ * a future run can resume from THIS run). Replayed agents accumulate into `run.stats` (total work) but NOT into
412
+ * `ctx.budget.spent()` (live spend only — a resume is not re-charged for cached work). NOT-REPLAYED (it forces
413
+ * divergence so the suffix runs live): `ctx.pipeline` (latency-dependent ordinals aren't deterministic — a
414
+ * CORE-7.1 follow-on adds stage-scoped deterministic keys). Sequential + `parallel(direct thunks)` replay.
396
415
  */
397
416
  journalStore?: WorkflowJournalStore;
417
+ /**
418
+ * How long (ms) a call waits for the journal store to answer ONE append before it is refused with
419
+ * {@link WorkflowJournalAppendTimeoutError} (`workflow.journal_append_timeout`). Default
420
+ * {@link WORKFLOW_JOURNAL_APPEND_TIMEOUT_MS}. One bound for both spawn lanes (`ctx.agent` and
421
+ * `ctx.agentStream().result()`) and every awaited append (a settled result, a refused call's failed
422
+ * entry, an oversize tombstone, a park record). Must be a finite number > 0 (a bad value is refused before the
423
+ * run starts, never replaced by the default).
424
+ *
425
+ * Independent of `totalTimeoutMs`: this one names a dead STORE, that one ends the RUN. Whichever deadline is
426
+ * earlier speaks — a run with no `totalTimeoutMs` is bounded by this alone, one whose `totalTimeoutMs` is
427
+ * shorter finalizes with the run timeout first (the late append fault is then silent). The timeout does not
428
+ * cancel the write; see {@link WorkflowJournalAppendTimeoutError}.
429
+ */
430
+ journalAppendTimeoutMs?: number;
398
431
  /** design/97 CORE-7 — resume by replaying a prior run's journal (requires `journalStore`). See `journalStore`. */
399
432
  resumeFromRunId?: string;
400
433
  /** The HOST task's effective working root — threaded into every spawned agent's trusted internals
@@ -533,6 +566,10 @@ export interface RunWorkflowOptions {
533
566
  * `run_workflow` tool wiring; a directly-started workflow may pass its own. Absent ⇒ children run
534
567
  * under only their own gates (pre-seam behavior). TRUSTED: never a script/model argument. */
535
568
  inheritedGate?: import("../core/runner/contracts.js").InheritedGate;
569
+ /** The HOST task's tool selector layers (`ToolExecuteContext.toolSelector.layers`), threaded into EVERY spawned agent's trusted
570
+ * internals as its ceiling (`RunInternals.toolCeiling`) on both spawn legs: nothing a workflow agent's spec names can widen what
571
+ * the host may use. Set by the `run_workflow` tool wiring; absent ⇒ the agents are bounded only by their own lists. TRUSTED. */
572
+ toolCeiling?: readonly import("../core/tool-face.js").ToolSelectorLayer[];
536
573
  /** RB-201 FO-3 (workflow lane) — the session's auto-mode classifier, consulted BEFORE each script-spawned
537
574
  * child starts (objective + toolset + output schema, finalized). The delegation-tool lane reviews its
538
575
  * children at one shared point; a workflow's children reach `runner.runTask` through this module instead,
@@ -639,6 +676,19 @@ export declare const WORKFLOW_AGENT_THROTTLE_BACKOFF_MS = 45000;
639
676
  * so the timer is unref'd by default and tests can drive it without waiting.
640
677
  */
641
678
  export declare const WORKFLOW_RESUME_CLAIM_FINALIZE_TIMEOUT_MS = 10000;
679
+ /**
680
+ * The default for {@link RunWorkflowOptions.journalAppendTimeoutMs}: how long a call waits for the journal store
681
+ * to answer ONE append before it is refused with {@link WorkflowJournalAppendTimeoutError}.
682
+ *
683
+ * The wait is load-bearing (the script must not run past an unrecorded agent), so the figure has to clear a
684
+ * healthy write by a wide margin: one row of at most `MAX_JOURNAL_RESULT_BYTES` to a remote, loaded database
685
+ * is seconds, never tens of seconds — a bound near that would misread a busy store as a dead one. It also has
686
+ * to be well inside the Workflow tool's 10-minute deadline, or the bound would add nothing there: a dead store
687
+ * is named after 30 s instead of silently eating the run's whole deadline. The two terminal-boundary waits
688
+ * (5 s drain, 10 s claim release) are shorter on purpose — they run after the outcome is fixed and lose
689
+ * nothing by giving up; this one decides whether the script may continue.
690
+ */
691
+ export declare const WORKFLOW_JOURNAL_APPEND_TIMEOUT_MS = 30000;
642
692
  /** F5/B4 + design/87 §4.3 — the INJECTABLE timer seam the per-agent resilience layer schedules on (the
643
693
  * stall watchdog + the throttle backoff sleep). Tests drive VIRTUAL time instead of really waiting
644
694
  * 180s/45s. Default: the real `setTimeout`/`clearTimeout`, unref'd (a pending watchdog must never hold
@@ -6,6 +6,7 @@ import { uuidv7 } from "../internal/harness.js";
6
6
  import { applyParentSpecSeat } from "../core/parent-spec-seat.js";
7
7
  import { TERMINAL_CAUSE_IS_REPLAYABLE, isTerminalCauseKind } from "../core/terminal-cause.js";
8
8
  import { terminalProjection } from "../core/runner/terminal-projection.js";
9
+ import { steeringError } from "../core/runner/steer-admission.js";
9
10
  import { builtinAgentDefinitions } from "../agents/builtin-agents.js";
10
11
  import { GENERAL_PURPOSE_SUBAGENT_TYPE, markerFragment } from "../agents/subagent.js";
11
12
  import { deploymentSubagentSystemPrompt, runnerRoleMap } from "../agents/child-model-seat.js";
@@ -240,6 +241,21 @@ export class WorkflowJournalIncompatibleError extends Error {
240
241
  this.name = "WorkflowJournalIncompatibleError";
241
242
  }
242
243
  }
244
+ export class WorkflowJournalAppendTimeoutError extends Error {
245
+ runId;
246
+ ordinal;
247
+ timeoutMs;
248
+ code = "workflow.journal_append_timeout";
249
+ constructor(runId, ordinal, timeoutMs) {
250
+ super(`the workflow journal store did not answer the append for agent #${ordinal} of run ${runId} within ${timeoutMs}ms (journalAppendTimeoutMs) — ` +
251
+ "a journal-store fault, not a run timeout. The result is not confirmed recorded: a resume of this run replays the agent only if the write " +
252
+ "landed late, otherwise it re-runs the agent live.");
253
+ this.runId = runId;
254
+ this.ordinal = ordinal;
255
+ this.timeoutMs = timeoutMs;
256
+ this.name = "WorkflowJournalAppendTimeoutError";
257
+ }
258
+ }
243
259
  class WorkflowParkRefusal extends Error {
244
260
  code;
245
261
  detail;
@@ -353,6 +369,7 @@ function readLegApprovalWaitedMs(result, announce) {
353
369
  return raw;
354
370
  }
355
371
  export const WORKFLOW_RESUME_CLAIM_FINALIZE_TIMEOUT_MS = 10_000;
372
+ export const WORKFLOW_JOURNAL_APPEND_TIMEOUT_MS = 30_000;
356
373
  const REAL_WORKFLOW_TIMERS = {
357
374
  setTimeout(fn, ms) {
358
375
  const t = setTimeout(fn, ms);
@@ -411,6 +428,14 @@ function normalizeWorkflowTimerCap(name, v) {
411
428
  }
412
429
  return normalized;
413
430
  }
431
+ function normalizeWorkflowJournalAppendTimeoutMs(v) {
432
+ if (v === undefined)
433
+ return WORKFLOW_JOURNAL_APPEND_TIMEOUT_MS;
434
+ if (!Number.isFinite(v) || v <= 0) {
435
+ throw new Error(`runWorkflow: journalAppendTimeoutMs must be a finite number > 0 (got ${v}) — a bound of zero would time out every append before the store could answer. Omit it for the default.`);
436
+ }
437
+ return normalizeWorkflowTimerCap("journalAppendTimeoutMs", v);
438
+ }
414
439
  function normalizeWorkflowStallMs(v) {
415
440
  if (v === undefined)
416
441
  return WORKFLOW_AGENT_STALL_MS;
@@ -525,6 +550,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
525
550
  const stallMs = normalizeWorkflowStallMs(opts.stallMs);
526
551
  const agentMaxRetries = normalizeWorkflowHardCap("agentMaxRetries", opts.agentMaxRetries) ?? WORKFLOW_AGENT_MAX_RETRIES;
527
552
  const throttleBackoffMs = normalizeWorkflowTimerCap("throttleBackoffMs", opts.throttleBackoffMs) ?? WORKFLOW_AGENT_THROTTLE_BACKOFF_MS;
553
+ const journalAppendTimeoutMs = normalizeWorkflowJournalAppendTimeoutMs(opts.journalAppendTimeoutMs);
528
554
  const timers = opts.timers ?? REAL_WORKFLOW_TIMERS;
529
555
  const cancelController = new AbortController();
530
556
  const timeoutController = totalTimeoutMs !== undefined ? new AbortController() : undefined;
@@ -689,6 +715,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
689
715
  ...(opts.parentCenterSourceRevision !== undefined ? { parentCenterSourceRevision: opts.parentCenterSourceRevision } : {}),
690
716
  ...(opts.onForwardEvent ? { onForwardEvent: opts.onForwardEvent } : {}),
691
717
  ...(opts.inheritedGate !== undefined ? { inheritedGate: opts.inheritedGate } : {}),
718
+ ...(opts.toolCeiling !== undefined ? { toolCeiling: opts.toolCeiling } : {}),
692
719
  ...((opts.rootSessionId ?? opts.originatingSessionId) !== undefined ? { rootSessionId: opts.rootSessionId ?? opts.originatingSessionId } : {}),
693
720
  ...(opts.placementRoot !== undefined ? { placementRoot: opts.placementRoot } : {}),
694
721
  ...(opts.originatingSessionId !== undefined ? { parentSessionId: opts.originatingSessionId } : {}),
@@ -835,15 +862,18 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
835
862
  const journalStore = opts.journalStore;
836
863
  let resumeClaim;
837
864
  const replayByOrdinal = [];
838
- let diverged = false;
865
+ let divergence;
839
866
  let parkedLeg;
840
867
  const parkedError = () => {
841
868
  const p = parkedLeg;
842
869
  return new WorkflowAgentParkedError(p.label, p.paused.terminal.gate.kind, p.paused.terminal.checkpointId);
843
870
  };
844
871
  const parkedResumeFor = (token) => opts.parkedResume?.find((d) => d.token === token);
845
- const parkedCallChangedError = (ordinal) => Object.assign(new Error(`workflow resume: ordinal ${ordinal} is PARKED on an approval checkpoint, but the call at that ordinal changed (its call key differs from the journaled one) — ` +
846
- "the script or its args were edited at a parked call, and a fresh spawn there would run beside the pinned child. Restore the call and resume again, or decide the checkpoint " +
872
+ const parkedCallChangedError = (ordinal) => Object.assign(new Error(`workflow resume: ordinal ${ordinal} is PARKED on an approval checkpoint, but the call at that ordinal changed (its call key differs from the journaled one) ` +
873
+ (divergence === undefined
874
+ ? "while no earlier call diverged from the record — the difference is in this call's own inputs (the script, its args, or a host input folded into the call identity). "
875
+ : `after replay stopped at agent #${divergence.ordinal} (${divergence.reason}) — the calls from there on ran live, so this call may have been built from a live result rather than the recorded one. `) +
876
+ "A fresh spawn there would run beside the pinned child. Resume with the calls up to it unchanged, or decide the checkpoint " +
847
877
  "through the deployment's approval channel and start a fresh run."), { code: "workflow.parked_call_changed" });
848
878
  let inFlightLegs = 0;
849
879
  let legsIdleResolve;
@@ -971,6 +1001,34 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
971
1001
  };
972
1002
  let journalTail = Promise.resolve();
973
1003
  const JOURNAL_DRAIN_MAX_MS = 5_000;
1004
+ const awaitedAppendTimers = new Set();
1005
+ const trackJournalWrite = (write, callKey) => {
1006
+ if (finalized)
1007
+ return Promise.resolve(write);
1008
+ const written = new Promise((resolve, reject) => {
1009
+ const handle = timers.setTimeout(() => {
1010
+ awaitedAppendTimers.delete(handle);
1011
+ const fault = new WorkflowJournalAppendTimeoutError(runId, callKeyOrdinal(callKey), journalAppendTimeoutMs);
1012
+ emitRunLog(`resume-journal: ${fault.message}`);
1013
+ reject(fault);
1014
+ }, journalAppendTimeoutMs);
1015
+ handle?.ref?.();
1016
+ awaitedAppendTimers.add(handle);
1017
+ const settled = () => {
1018
+ timers.clearTimeout(handle);
1019
+ awaitedAppendTimers.delete(handle);
1020
+ };
1021
+ Promise.resolve(write).then(() => {
1022
+ settled();
1023
+ resolve();
1024
+ }, (err) => {
1025
+ settled();
1026
+ reject(err);
1027
+ });
1028
+ });
1029
+ journalTail = journalTail.then(() => written).catch(() => undefined);
1030
+ return written;
1031
+ };
974
1032
  const durableApprovalInherit = (s) => s.durableApproval === undefined && opts.defaultDurableApproval !== undefined ? { durableApproval: { ...opts.defaultDurableApproval } } : {};
975
1033
  const journalDurableResult = (result) => {
976
1034
  const t = result.terminal;
@@ -999,8 +1057,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
999
1057
  run.journalSkips = (run.journalSkips ?? 0) + 1;
1000
1058
  emitRunLog(`resume-journal: agent #${callKeyOrdinal(callKey)}${label !== undefined ? ` "${label.slice(0, 80)}"` : ""} result is ${bytes} bytes, ` +
1001
1059
  `over the ${MAX_JOURNAL_RESULT_BYTES}-byte per-entry cap — NOT cached. A resume from this run re-runs this agent and everything after it live.`);
1002
- const tombstone = journalStore.append(runId, scope, { callKey, result: journalOversizeTombstone(stored, bytes) });
1003
- journalTail = journalTail.then(() => tombstone).catch(() => undefined);
1060
+ const tombstone = trackJournalWrite(journalStore.append(runId, scope, { callKey, result: journalOversizeTombstone(stored, bytes) }), callKey);
1004
1061
  try {
1005
1062
  await tombstone;
1006
1063
  if (dbg)
@@ -1012,8 +1069,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1012
1069
  }
1013
1070
  return;
1014
1071
  }
1015
- const p = journalStore.append(runId, scope, { callKey, result: stored });
1016
- journalTail = journalTail.then(() => p).catch(() => undefined);
1072
+ const p = trackJournalWrite(journalStore.append(runId, scope, { callKey, result: stored }), callKey);
1017
1073
  try {
1018
1074
  await p;
1019
1075
  if (dbg)
@@ -1028,9 +1084,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1028
1084
  const journalAppendParked = async (callKey, paused) => {
1029
1085
  if (!journalStore)
1030
1086
  return false;
1031
- const p = journalStore.append(runId, scope, { callKey, parked: paused });
1032
- journalTail = journalTail.then(() => p).catch(() => undefined);
1033
- await p;
1087
+ await trackJournalWrite(journalStore.append(runId, scope, { callKey, parked: paused }), callKey);
1034
1088
  return true;
1035
1089
  };
1036
1090
  const parkAgentLeg = async (rec, paused, activityTail, chargeLive) => {
@@ -1097,7 +1151,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1097
1151
  bceSpawn(callKey, label, agentOpts.agentType, d.kind === "repark", (d.kind === "repark" ? d.paused.sessionId : d.result.sessionId) || undefined, model);
1098
1152
  if (d.kind === "repark")
1099
1153
  return await parkAgentLeg(rec, d.paused, [], false);
1100
- await settleAgentResult(rec, d.result, [], agentOpts, "awaited");
1154
+ await settleAgentResult(rec, d.result, [], agentOpts);
1101
1155
  return d.result;
1102
1156
  };
1103
1157
  const createActivityCapture = (callKey, label, groupId, rec) => {
@@ -1243,11 +1297,10 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1243
1297
  }
1244
1298
  run.timeoutInterruption = { timeoutMs: totalTimeoutMs, agentsCompleted, agentsFailed, agentsInFlight, ...(approvalWaitedMs !== undefined ? { approvalWaitedMs } : {}) };
1245
1299
  };
1246
- let divergenceNoted = false;
1247
1300
  const noteDivergence = (ordinal, reason) => {
1248
- if (opts.resumeFromRunId === undefined || divergenceNoted)
1301
+ if (opts.resumeFromRunId === undefined || divergence !== undefined)
1249
1302
  return;
1250
- divergenceNoted = true;
1303
+ divergence = { ordinal, reason };
1251
1304
  if (run.resume) {
1252
1305
  run.resume.divergedAtOrdinal = ordinal;
1253
1306
  run.resume.divergedReason = reason;
@@ -1426,7 +1479,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1426
1479
  };
1427
1480
  return { onTurnEndUsage, rollbackUsageBeat, observedTokens: () => beatTokens };
1428
1481
  };
1429
- const settleAgentResult = async (rec, result, activityTail, agentOpts, journal) => {
1482
+ const settleAgentResult = async (rec, result, activityTail, agentOpts) => {
1430
1483
  const s = result.stats;
1431
1484
  accumulateStats(result, true);
1432
1485
  rec.status = result.terminal.kind === "completed" ? "completed" : "failed";
@@ -1445,15 +1498,98 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1445
1498
  emit({ type: "agent_end", runId, label: rec.label, phase: rec.phase, ...(rec.groupId !== undefined ? { groupId: rec.groupId } : {}), status: rec.status, output, ...(rec.errorCode !== undefined ? { errorCode: rec.errorCode } : {}), ...(result.stats.toolCalls !== undefined ? { toolCalls: result.stats.toolCalls } : {}), ...(result.model !== undefined ? { modelResolved: result.model } : {}), ts: rec.endedAt });
1446
1499
  void persist("update");
1447
1500
  bceTerminal(rec.callKey, rec.status === "completed" ? "completed" : "failed", output, result.sessionId || undefined, rec.stats);
1448
- if (journal === "awaited")
1449
- await journalAppend(rec.callKey, result, rec.label);
1450
- else {
1451
- void journalAppend(rec.callKey, result, rec.label).catch(() => undefined);
1452
- }
1501
+ await journalAppend(rec.callKey, result, rec.label);
1453
1502
  if (agentOpts.schema && result.terminal.kind === "completed" && result.structuredOutput === undefined) {
1454
1503
  throw new WorkflowAgentSchemaError(rec.label, result);
1455
1504
  }
1456
1505
  };
1506
+ const resumeArmOf = (callKey) => {
1507
+ const ordinal = run.agents.length;
1508
+ let drive;
1509
+ const truth = opts.resumeFromRunId !== undefined ? parkedByOrdinal[ordinal] : undefined;
1510
+ if (truth !== undefined) {
1511
+ const d = disposeParkedOrdinal(truth, ordinal, callKey);
1512
+ if (d.kind !== "drive")
1513
+ return { kind: "dispose", d };
1514
+ drive = d.drive;
1515
+ }
1516
+ if (parkedLeg !== undefined && drive === undefined)
1517
+ throw parkedError();
1518
+ if (drive !== undefined || opts.resumeFromRunId === undefined || divergence !== undefined)
1519
+ return { kind: "live", drive };
1520
+ const cached = replayByOrdinal[ordinal];
1521
+ if (cached && cached.callKey === callKey && cached.result !== undefined && TERMINAL_CAUSE_IS_REPLAYABLE[cached.result.terminal.kind]) {
1522
+ return { kind: "replay", result: cached.result };
1523
+ }
1524
+ noteDivergence(ordinal, cached === undefined
1525
+ ? run.resume?.journalEntries === 0
1526
+ ? "the journal loaded no entries"
1527
+ : ordinal >= replayByOrdinal.length
1528
+ ? "a new call past the journaled prefix — the prior run ended before this point (the intended extend-the-script resume shape)"
1529
+ : "no journal entry at this ordinal (never recorded, e.g. an oversize result under a pre-tombstone engine, or dropped)"
1530
+ : cached.callKey !== callKey
1531
+ ? "the call changed — its call key changed from the journaled call's while no earlier call diverged from the record, so the difference is in this call's own inputs (the script, its args, or a host input folded into the call identity)"
1532
+ : cached.result?.terminal?.kind === "failed" && cached.result.terminal.code === JOURNAL_OVERSIZE_ERROR_CODE
1533
+ ? "the prior result exceeded the journal size cap and was never cached"
1534
+ : `the journaled result was ${cached.result?.terminal?.kind ?? "(no terminal record)"}, not completed`);
1535
+ return { kind: "live", drive: undefined };
1536
+ };
1537
+ const replayAgent = async (call, r, agentOpts) => {
1538
+ const { label, callKey, groupId, phase, phaseInstance, prompt } = call;
1539
+ if (finalized)
1540
+ return r;
1541
+ const rs = r.stats;
1542
+ const cachedOutput = boundedRedactedSummary(r.structuredOutput ?? r.result, MAX_TRANSCRIPT_CHARS);
1543
+ const at = now();
1544
+ const replayModel = r.model;
1545
+ const replayRec = {
1546
+ label,
1547
+ callKey,
1548
+ ...(groupId !== undefined ? { groupId } : {}),
1549
+ phase,
1550
+ prompt,
1551
+ ...(replayModel !== undefined ? { model: replayModel } : {}),
1552
+ replayed: true,
1553
+ status: r.terminal.kind === "completed" ? "completed" : "failed",
1554
+ taskStatus: terminalProjection(r.terminal).status,
1555
+ ...(r.sessionId ? { sessionId: r.sessionId } : {}),
1556
+ ...(r.runId ? { taskRunId: r.runId } : {}),
1557
+ queuedAt: at,
1558
+ startedAt: at,
1559
+ endedAt: at,
1560
+ stats: { tokens: rs.tokens ?? 0, turns: rs.turns ?? 0, costMicroUsd: rs.costMicroUsd },
1561
+ ...(rs.toolCalls !== undefined ? { toolCalls: rs.toolCalls } : {}),
1562
+ output: cachedOutput,
1563
+ };
1564
+ if (run.resume)
1565
+ run.resume.replayed += 1;
1566
+ run.agents.push(replayRec);
1567
+ if (phaseInstance)
1568
+ agentPhaseOf.set(replayRec, phaseInstance);
1569
+ emit({ type: "agent_start", runId, label, phase, ...(groupId !== undefined ? { groupId } : {}), callKey, prompt, ...(replayModel !== undefined ? { model: replayModel } : {}), replayed: true, ts: at });
1570
+ emit({ type: "agent_end", runId, label, phase, ...(groupId !== undefined ? { groupId } : {}), status: replayRec.status, output: cachedOutput, ...(rs.toolCalls !== undefined ? { toolCalls: rs.toolCalls } : {}), replayed: true, ts: at });
1571
+ bceSpawn(callKey, label, agentOpts.agentType, true, r.sessionId || undefined, replayModel);
1572
+ bceTerminal(callKey, replayRec.status === "completed" ? "completed" : "failed", cachedOutput, r.sessionId || undefined, replayRec.stats);
1573
+ accumulateStats(r, false);
1574
+ void persist("update");
1575
+ await journalAppend(callKey, r);
1576
+ if (agentOpts.schema && r.terminal.kind === "completed" && r.structuredOutput === undefined) {
1577
+ throw new WorkflowAgentSchemaError(label, r);
1578
+ }
1579
+ return r;
1580
+ };
1581
+ const settledHandle = (label, callKey, settled) => {
1582
+ settled.catch(() => undefined);
1583
+ return {
1584
+ runId,
1585
+ label,
1586
+ callKey,
1587
+ steer: async () => {
1588
+ throw steeringError(`the task has already finished — workflow agent "${label}" was settled on this resume without running`);
1589
+ },
1590
+ result: () => settled,
1591
+ };
1592
+ };
1457
1593
  const ctx = {
1458
1594
  runId,
1459
1595
  budget,
@@ -1464,77 +1600,13 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1464
1600
  async agent(spec, agentOpts = {}) {
1465
1601
  const effectiveSignal = assertAgentSpawnAllowed("ctx.agent", spec, agentOpts);
1466
1602
  const { label, phase, phaseInstance, groupId, inheritedModelSnap, inheritedModelRef, inheritedModelError, inheritedThinkingSnap, callKey, prompt, model } = prepareAgentCall(spec, agentOpts);
1467
- let drive;
1468
- const cached = opts.resumeFromRunId !== undefined ? replayByOrdinal[run.agents.length] : undefined;
1469
- const truth = opts.resumeFromRunId !== undefined ? parkedByOrdinal[run.agents.length] : undefined;
1470
- if (truth !== undefined) {
1471
- const d = disposeParkedOrdinal(truth, run.agents.length, callKey);
1472
- if (d.kind !== "drive")
1473
- return await recordParkDisposition(d, { label, callKey, groupId, phase, phaseInstance, prompt }, agentOpts);
1474
- drive = d.drive;
1475
- }
1476
- if (parkedLeg !== undefined && drive === undefined)
1477
- throw parkedError();
1478
- if (opts.resumeFromRunId !== undefined && !diverged) {
1479
- if (drive === undefined && cached && cached.callKey === callKey && cached.result !== undefined && TERMINAL_CAUSE_IS_REPLAYABLE[cached.result.terminal.kind]) {
1480
- if (finalized)
1481
- return cached.result;
1482
- const r = cached.result;
1483
- const rs = r.stats;
1484
- const cachedOutput = boundedRedactedSummary(r.structuredOutput ?? r.result, MAX_TRANSCRIPT_CHARS);
1485
- const at = now();
1486
- const replayModel = r.model;
1487
- const replayRec = {
1488
- label,
1489
- callKey,
1490
- ...(groupId !== undefined ? { groupId } : {}),
1491
- phase,
1492
- prompt,
1493
- ...(replayModel !== undefined ? { model: replayModel } : {}),
1494
- replayed: true,
1495
- status: r.terminal.kind === "completed" ? "completed" : "failed",
1496
- taskStatus: terminalProjection(r.terminal).status,
1497
- ...(r.sessionId ? { sessionId: r.sessionId } : {}),
1498
- ...(r.runId ? { taskRunId: r.runId } : {}),
1499
- queuedAt: at,
1500
- startedAt: at,
1501
- endedAt: at,
1502
- stats: { tokens: rs.tokens ?? 0, turns: rs.turns ?? 0, costMicroUsd: rs.costMicroUsd },
1503
- ...(rs.toolCalls !== undefined ? { toolCalls: rs.toolCalls } : {}),
1504
- output: cachedOutput,
1505
- };
1506
- if (run.resume)
1507
- run.resume.replayed += 1;
1508
- run.agents.push(replayRec);
1509
- if (phaseInstance)
1510
- agentPhaseOf.set(replayRec, phaseInstance);
1511
- emit({ type: "agent_start", runId, label, phase, ...(groupId !== undefined ? { groupId } : {}), callKey, prompt, ...(replayModel !== undefined ? { model: replayModel } : {}), replayed: true, ts: at });
1512
- emit({ type: "agent_end", runId, label, phase, ...(groupId !== undefined ? { groupId } : {}), status: replayRec.status, output: cachedOutput, ...(rs.toolCalls !== undefined ? { toolCalls: rs.toolCalls } : {}), replayed: true, ts: at });
1513
- bceSpawn(callKey, label, agentOpts.agentType, true, r.sessionId || undefined, replayModel);
1514
- bceTerminal(callKey, replayRec.status === "completed" ? "completed" : "failed", cachedOutput, r.sessionId || undefined, replayRec.stats);
1515
- accumulateStats(r, false);
1516
- void persist("update");
1517
- await journalAppend(callKey, r);
1518
- if (agentOpts.schema && r.terminal.kind === "completed" && r.structuredOutput === undefined) {
1519
- throw new WorkflowAgentSchemaError(label, r);
1520
- }
1521
- return r;
1522
- }
1523
- if (drive === undefined) {
1524
- noteDivergence(run.agents.length, cached === undefined
1525
- ? run.resume?.journalEntries === 0
1526
- ? "the journal loaded no entries"
1527
- : run.agents.length >= replayByOrdinal.length
1528
- ? "a new call past the journaled prefix — the prior run ended before this point (the intended extend-the-script resume shape)"
1529
- : "no journal entry at this ordinal (never recorded, e.g. an oversize result under a pre-tombstone engine, or dropped)"
1530
- : cached.callKey !== callKey
1531
- ? "the call key changed — the script or its args differ here"
1532
- : cached.result?.terminal?.kind === "failed" && cached.result.terminal.code === JOURNAL_OVERSIZE_ERROR_CODE
1533
- ? "the prior result exceeded the journal size cap and was never cached"
1534
- : `the journaled result was ${cached.result?.terminal?.kind ?? "(no terminal record)"}, not completed`);
1535
- diverged = true;
1536
- }
1537
- }
1603
+ const call = { label, callKey, groupId, phase, phaseInstance, prompt };
1604
+ const arm = resumeArmOf(callKey);
1605
+ if (arm.kind === "dispose")
1606
+ return await recordParkDisposition(arm.d, call, agentOpts);
1607
+ if (arm.kind === "replay")
1608
+ return await replayAgent(call, arm.result, agentOpts);
1609
+ const drive = arm.drive;
1538
1610
  if (budgetTotal !== null && spent() >= budgetTotal) {
1539
1611
  throw new WorkflowBudgetExceededError(spent(), budgetTotal);
1540
1612
  }
@@ -1773,6 +1845,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1773
1845
  catch (err) {
1774
1846
  if (drive !== undefined && !finalized && !thrownIs(err, WorkflowAgentParkedError)) {
1775
1847
  emitRunLog(`[park] the parked leg "${label}" could not be driven — the resume was refused before the checkpoint was consumed (${withoutToken(errText(err), drive.token)}); the park stands.`);
1848
+ release();
1776
1849
  return await parkAgentLeg(rec, drive.paused, activityTail, false);
1777
1850
  }
1778
1851
  if (!finalized) {
@@ -1811,6 +1884,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1811
1884
  }
1812
1885
  emit({ type: "agent_end", runId, label, phase, ...(groupId !== undefined ? { groupId } : {}), status: "failed", ...(rec.output !== undefined ? { output: rec.output } : {}), ...(rec.errorCode !== undefined ? { errorCode: rec.errorCode } : {}), ts: rec.endedAt });
1813
1886
  void persist("update");
1887
+ release();
1814
1888
  const journaled = journalAppend(callKey, salvaged ?? {
1815
1889
  taskId: callKey,
1816
1890
  sessionId: "",
@@ -1841,29 +1915,22 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1841
1915
  emitRunLog(`[park] the parked leg "${label}" was driven but the approved action never started (${result.terminal.kind === "failed" ? result.terminal.code : ""}); the park stands.`);
1842
1916
  return await parkAgentLeg(rec, drive.paused, activityTail, false);
1843
1917
  }
1844
- await settleAgentResult(rec, result, activityTail, agentOpts, "awaited");
1918
+ await settleAgentResult(rec, result, activityTail, agentOpts);
1845
1919
  return result;
1846
1920
  },
1847
1921
  async agentStream(spec, agentOpts = {}) {
1848
1922
  const effectiveSignal = assertAgentSpawnAllowed("ctx.agentStream", spec, agentOpts);
1923
+ const { label, phase, phaseInstance, groupId, inheritedModelSnap, inheritedModelRef, inheritedModelError, inheritedThinkingSnap, callKey, prompt, model } = prepareAgentCall(spec, agentOpts);
1924
+ const call = { label, callKey, groupId, phase, phaseInstance, prompt };
1925
+ const arm = resumeArmOf(callKey);
1926
+ if (arm.kind === "dispose")
1927
+ return settledHandle(label, callKey, Promise.resolve(await recordParkDisposition(arm.d, call, agentOpts)));
1928
+ if (arm.kind === "replay")
1929
+ return settledHandle(label, callKey, replayAgent(call, arm.result, agentOpts));
1930
+ const drive = arm.drive;
1849
1931
  if (budgetTotal !== null && spent() >= budgetTotal) {
1850
1932
  throw new WorkflowBudgetExceededError(spent(), budgetTotal);
1851
1933
  }
1852
- const { label, phase, phaseInstance, groupId, inheritedModelSnap, inheritedModelRef, inheritedModelError, inheritedThinkingSnap, callKey, prompt, model } = prepareAgentCall(spec, agentOpts);
1853
- let drive;
1854
- const truth = opts.resumeFromRunId !== undefined ? parkedByOrdinal[run.agents.length] : undefined;
1855
- if (truth !== undefined) {
1856
- const d = disposeParkedOrdinal(truth, run.agents.length, callKey);
1857
- if (d.kind !== "drive") {
1858
- const settled = await recordParkDisposition(d, { label, callKey, groupId, phase, phaseInstance, prompt }, agentOpts);
1859
- return { runId, label, callKey, steer: async () => Promise.reject(new Error(`workflow agent "${label}" settled at its parked ordinal — nothing to steer`)), result: async () => settled };
1860
- }
1861
- drive = d.drive;
1862
- }
1863
- if (drive === undefined) {
1864
- noteDivergence(run.agents.length, "ctx.agentStream results are never replayed");
1865
- diverged = true;
1866
- }
1867
1934
  const rec = { label, callKey, ...(groupId !== undefined ? { groupId } : {}), phase, prompt, ...(model !== undefined ? { model } : {}), status: "running", queuedAt: now() };
1868
1935
  const { tail: activityTail, onActivity } = createActivityCapture(callKey, label, groupId, rec);
1869
1936
  run.agents.push(rec);
@@ -1991,19 +2058,22 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
1991
2058
  const spawnMessage = thrownMessageOf(err);
1992
2059
  if (!finalized && rec.errorMessage === undefined && spawnMessage !== undefined)
1993
2060
  rec.errorMessage = boundedRedactedSummary(spawnMessage, MAX_TRANSCRIPT_CHARS);
1994
- if (!finalized && thrownIs(err, WorkflowAgentBlockedError)) {
2061
+ const refusal = !finalized && thrownIs(err, WorkflowAgentBlockedError) ? err : undefined;
2062
+ if (refusal !== undefined) {
1995
2063
  rec.errorCode = WORKFLOW_SPAWN_BLOCKED_ERROR_CODE;
1996
- rec.errorMessage = boundedRedactedSummary(err.message, MAX_TRANSCRIPT_CHARS);
1997
- void journalAppend(callKey, {
2064
+ rec.errorMessage = boundedRedactedSummary(refusal.message, MAX_TRANSCRIPT_CHARS);
2065
+ }
2066
+ recordFailed();
2067
+ releaseLeg();
2068
+ if (refusal !== undefined) {
2069
+ await journalAppend(callKey, {
1998
2070
  taskId: callKey,
1999
2071
  sessionId: "",
2000
- terminal: { kind: "failed", code: WORKFLOW_SPAWN_BLOCKED_ERROR_CODE, message: boundedRedactedSummary(err.message, 500) },
2001
- result: boundedRedactedSummary(err.message, 500),
2072
+ terminal: { kind: "failed", code: WORKFLOW_SPAWN_BLOCKED_ERROR_CODE, message: boundedRedactedSummary(refusal.message, 500) },
2073
+ result: boundedRedactedSummary(refusal.message, 500),
2002
2074
  stats: { turns: 0, tokens: 0, costMicroUsd: 0, usageMissing: true },
2003
2075
  }).catch(() => undefined);
2004
2076
  }
2005
- recordFailed();
2006
- releaseLeg();
2007
2077
  bceTerminal(callKey, "failed", thrownText(err), undefined, undefined);
2008
2078
  throw err;
2009
2079
  }
@@ -2044,7 +2114,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
2044
2114
  }
2045
2115
  recordFailed();
2046
2116
  releaseLeg();
2047
- void journalAppend(callKey, {
2117
+ await journalAppend(callKey, {
2048
2118
  taskId: callKey,
2049
2119
  sessionId: "",
2050
2120
  terminal: { kind: "failed", message: boundedRedactedSummary(thrownText(err), 500) },
@@ -2066,7 +2136,7 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
2066
2136
  emitRunLog(`[park] the parked leg "${label}" was driven but the approved action never started (${result.terminal.kind === "failed" ? result.terminal.code : ""}); the park stands.`);
2067
2137
  return await parkAgentLeg(rec, drive.paused, activityTail, false);
2068
2138
  }
2069
- await settleAgentResult(rec, result, activityTail, agentOpts, "best-effort");
2139
+ await settleAgentResult(rec, result, activityTail, agentOpts);
2070
2140
  return result;
2071
2141
  })();
2072
2142
  completion.catch(() => undefined);
@@ -2096,7 +2166,6 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
2096
2166
  assertFanOutCallables("pipeline", "stage", stages);
2097
2167
  const errorsOut = fanOutOpts?.errors;
2098
2168
  noteDivergence(run.agents.length, "ctx.pipeline ordinals are latency-dependent, so its calls always run live on a resume");
2099
- diverged = true;
2100
2169
  const settled = await Promise.all(itemList.map((item, index) => stages
2101
2170
  .reduce((acc, stage) => acc.then((prev) => stage(prev, item, index)), Promise.resolve(item))
2102
2171
  .then((v) => ({ ok: true, v }), (e) => ({ ok: false, e, i: index }))));
@@ -2464,6 +2533,9 @@ export function startWorkflow(runner, fn, opts = {}, internals) {
2464
2533
  resolve();
2465
2534
  });
2466
2535
  });
2536
+ for (const pending of awaitedAppendTimers)
2537
+ timers.clearTimeout(pending);
2538
+ awaitedAppendTimers.clear();
2467
2539
  if (resumeClaim !== undefined) {
2468
2540
  const granted = await finalizeWithin(timers, resumeClaim.verdict.then((v) => v.granted, () => false), false);
2469
2541
  if (granted) {
@@ -56,7 +56,7 @@ export interface CodeToolsConfig {
56
56
  }
57
57
  /**
58
58
  * Single-source bundle of the `code` scenario's `spec.tools`-class tools, so each deployment doesn't re-wire it
59
- * (the single-source discipline; mirrors the blessed `SCENARIO_REGISTRY` "data (named bundles)" precedent).
59
+ * (the single-source discipline: a scenario is data — a named bundle).
60
60
  * Profile-as-data — the engine iterates `spec.tools` branch-free; nothing keys off the scenario name. A trusted
61
61
  * assembler (service) calls this, sets `systemPrompt = CODE_SYSTEM_PROMPT` (or `role = CODE_ROLE`) +
62
62
  * `enablePlanMode:true`, and wires the deps seams (executionEnv/onQuestion/lspManager/skillSpecs/memoryStore/