@namzu/sdk 43.0.0 → 44.0.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 (2096) hide show
  1. package/CHANGELOG.md +506 -0
  2. package/README.md +41 -34
  3. package/dist/advisory/budget.js +3 -3
  4. package/dist/advisory/budget.js.map +1 -1
  5. package/dist/advisory/context.d.ts +5 -5
  6. package/dist/advisory/context.d.ts.map +1 -1
  7. package/dist/advisory/context.js +6 -6
  8. package/dist/advisory/context.js.map +1 -1
  9. package/dist/advisory/evaluator.js +2 -2
  10. package/dist/advisory/evaluator.js.map +1 -1
  11. package/dist/advisory/parse.d.ts +1 -1
  12. package/dist/advisory/parse.js +1 -1
  13. package/dist/agents/AbstractAgent.d.ts +47 -40
  14. package/dist/agents/AbstractAgent.d.ts.map +1 -1
  15. package/dist/agents/AbstractAgent.js +60 -46
  16. package/dist/agents/AbstractAgent.js.map +1 -1
  17. package/dist/agents/PipelineAgent.d.ts +7 -7
  18. package/dist/agents/PipelineAgent.d.ts.map +1 -1
  19. package/dist/agents/PipelineAgent.js +75 -23
  20. package/dist/agents/PipelineAgent.js.map +1 -1
  21. package/dist/agents/ReactiveAgent.d.ts +7 -7
  22. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  23. package/dist/agents/ReactiveAgent.js +32 -25
  24. package/dist/agents/ReactiveAgent.js.map +1 -1
  25. package/dist/agents/RouterAgent.d.ts +7 -7
  26. package/dist/agents/RouterAgent.d.ts.map +1 -1
  27. package/dist/agents/RouterAgent.js +29 -32
  28. package/dist/agents/RouterAgent.js.map +1 -1
  29. package/dist/agents/SupervisorAgent.d.ts +13 -10
  30. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  31. package/dist/agents/SupervisorAgent.js +50 -36
  32. package/dist/agents/SupervisorAgent.js.map +1 -1
  33. package/dist/agents/budget.d.ts +17 -4
  34. package/dist/agents/budget.d.ts.map +1 -1
  35. package/dist/agents/budget.js +55 -14
  36. package/dist/agents/budget.js.map +1 -1
  37. package/dist/agents/defineAgent.d.ts +2 -2
  38. package/dist/agents/defineAgent.d.ts.map +1 -1
  39. package/dist/agents/defineAgent.js.map +1 -1
  40. package/dist/agents/handle.d.ts +12 -14
  41. package/dist/agents/handle.d.ts.map +1 -1
  42. package/dist/agents/handle.js +6 -6
  43. package/dist/agents/handle.js.map +1 -1
  44. package/dist/agents/lock.js +4 -4
  45. package/dist/agents/lock.js.map +1 -1
  46. package/dist/agents/runAgent.d.ts +42 -29
  47. package/dist/agents/runAgent.d.ts.map +1 -1
  48. package/dist/agents/runAgent.js +53 -14
  49. package/dist/agents/runAgent.js.map +1 -1
  50. package/dist/agents/storage.d.ts +21 -0
  51. package/dist/agents/storage.d.ts.map +1 -0
  52. package/dist/agents/storage.js +33 -0
  53. package/dist/agents/storage.js.map +1 -0
  54. package/dist/authorization/command-line.d.ts +1 -1
  55. package/dist/authorization/command-line.js +1 -1
  56. package/dist/authorization/gate.js +1 -1
  57. package/dist/authorization/gate.js.map +1 -1
  58. package/dist/authorization/permission-presets.d.ts +4 -4
  59. package/dist/authorization/permission-presets.d.ts.map +1 -1
  60. package/dist/authorization/permission-presets.js +2 -2
  61. package/dist/bridge/a2a/client.d.ts +1 -1
  62. package/dist/bridge/a2a/client.js +2 -2
  63. package/dist/bridge/a2a/client.js.map +1 -1
  64. package/dist/bridge/a2a/context.d.ts +26 -0
  65. package/dist/bridge/a2a/context.d.ts.map +1 -0
  66. package/dist/bridge/a2a/context.js +20 -0
  67. package/dist/bridge/a2a/context.js.map +1 -0
  68. package/dist/bridge/a2a/index.d.ts +4 -2
  69. package/dist/bridge/a2a/index.d.ts.map +1 -1
  70. package/dist/bridge/a2a/index.js +6 -2
  71. package/dist/bridge/a2a/index.js.map +1 -1
  72. package/dist/bridge/a2a/mapper.d.ts +12 -4
  73. package/dist/bridge/a2a/mapper.d.ts.map +1 -1
  74. package/dist/bridge/a2a/mapper.js +38 -31
  75. package/dist/bridge/a2a/mapper.js.map +1 -1
  76. package/dist/bridge/a2a/task.d.ts +39 -7
  77. package/dist/bridge/a2a/task.d.ts.map +1 -1
  78. package/dist/bridge/a2a/task.js +52 -31
  79. package/dist/bridge/a2a/task.js.map +1 -1
  80. package/dist/bridge/acp/permission.d.ts +2 -2
  81. package/dist/bridge/acp/server.d.ts +22 -8
  82. package/dist/bridge/acp/server.d.ts.map +1 -1
  83. package/dist/bridge/acp/server.js +18 -5
  84. package/dist/bridge/acp/server.js.map +1 -1
  85. package/dist/bridge/acp/update.d.ts +4 -4
  86. package/dist/bridge/acp/update.d.ts.map +1 -1
  87. package/dist/bridge/acp/update.js +6 -6
  88. package/dist/bridge/acp/update.js.map +1 -1
  89. package/dist/bridge/external-session.d.ts +43 -0
  90. package/dist/bridge/external-session.d.ts.map +1 -0
  91. package/dist/bridge/external-session.js +28 -0
  92. package/dist/bridge/external-session.js.map +1 -0
  93. package/dist/bridge/sse/index.d.ts +1 -1
  94. package/dist/bridge/sse/index.d.ts.map +1 -1
  95. package/dist/bridge/sse/index.js +1 -1
  96. package/dist/bridge/sse/index.js.map +1 -1
  97. package/dist/bridge/sse/mapper.d.ts +21 -13
  98. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  99. package/dist/bridge/sse/mapper.js +99 -129
  100. package/dist/bridge/sse/mapper.js.map +1 -1
  101. package/dist/bus/breaker.d.ts +6 -6
  102. package/dist/bus/breaker.d.ts.map +1 -1
  103. package/dist/bus/breaker.js +28 -27
  104. package/dist/bus/breaker.js.map +1 -1
  105. package/dist/bus/index.d.ts +2 -2
  106. package/dist/bus/index.d.ts.map +1 -1
  107. package/dist/bus/index.js +6 -6
  108. package/dist/bus/index.js.map +1 -1
  109. package/dist/bus/lock.d.ts +5 -5
  110. package/dist/bus/lock.d.ts.map +1 -1
  111. package/dist/bus/lock.js.map +1 -1
  112. package/dist/bus/ownership.d.ts +8 -8
  113. package/dist/bus/ownership.d.ts.map +1 -1
  114. package/dist/bus/ownership.js.map +1 -1
  115. package/dist/compaction/consolidation.d.ts +23 -11
  116. package/dist/compaction/consolidation.d.ts.map +1 -1
  117. package/dist/compaction/consolidation.js +43 -13
  118. package/dist/compaction/consolidation.js.map +1 -1
  119. package/dist/compaction/context-window.d.ts +4 -4
  120. package/dist/compaction/context-window.js +4 -4
  121. package/dist/compaction/index.d.ts +1 -1
  122. package/dist/compaction/index.d.ts.map +1 -1
  123. package/dist/compaction/index.js +2 -2
  124. package/dist/compaction/index.js.map +1 -1
  125. package/dist/compaction/manager.d.ts +4 -4
  126. package/dist/compaction/manager.js +4 -4
  127. package/dist/compaction/manual.d.ts +2 -2
  128. package/dist/compaction/manual.js +3 -3
  129. package/dist/compaction/manual.js.map +1 -1
  130. package/dist/compaction/plan.d.ts +5 -5
  131. package/dist/compaction/plan.js +4 -4
  132. package/dist/compaction/plan.js.map +1 -1
  133. package/dist/compaction/reducer.d.ts +8 -8
  134. package/dist/compaction/reducer.d.ts.map +1 -1
  135. package/dist/compaction/retention.js +2 -2
  136. package/dist/compaction/salience/bm25.d.ts +2 -2
  137. package/dist/compaction/salience/bm25.js +2 -2
  138. package/dist/compaction/salience/goal.d.ts +3 -3
  139. package/dist/compaction/salience/goal.js +3 -3
  140. package/dist/compaction/salience/minhash.d.ts +1 -1
  141. package/dist/compaction/salience/minhash.js +1 -1
  142. package/dist/compaction/salience/score.d.ts +2 -2
  143. package/dist/compaction/salience/score.js +3 -3
  144. package/dist/compaction/salience/score.js.map +1 -1
  145. package/dist/compaction/salience/tokenize.d.ts +1 -1
  146. package/dist/compaction/salience/tokenize.js +1 -1
  147. package/dist/compaction/verifier.d.ts +6 -6
  148. package/dist/compaction/verifier.js +5 -5
  149. package/dist/compaction/verifier.js.map +1 -1
  150. package/dist/compaction/wire.d.ts +1 -1
  151. package/dist/config/registry.d.ts +4 -4
  152. package/dist/config/registry.js +2 -2
  153. package/dist/config/runtime.d.ts +24 -24
  154. package/dist/config/runtime.js +3 -3
  155. package/dist/connector/http-operation.d.ts +1 -1
  156. package/dist/connector/http-operation.js +1 -1
  157. package/dist/connector/mcp/adapter.js +1 -1
  158. package/dist/connector/mcp/client.d.ts +1 -1
  159. package/dist/connector/mcp/client.js +1 -1
  160. package/dist/connector/mcp/discovery.d.ts +1 -1
  161. package/dist/connector/mcp/discovery.js +1 -1
  162. package/dist/connector/mcp/discovery.js.map +1 -1
  163. package/dist/connector/mcp/policy.d.ts +1 -1
  164. package/dist/connector/mcp/prompt-adapter.d.ts +1 -1
  165. package/dist/connector/mcp/prompt-adapter.js +3 -3
  166. package/dist/connector/mcp/prompt-adapter.js.map +1 -1
  167. package/dist/constants/a2a/index.d.ts +8 -2
  168. package/dist/constants/a2a/index.d.ts.map +1 -1
  169. package/dist/constants/a2a/index.js +9 -2
  170. package/dist/constants/a2a/index.js.map +1 -1
  171. package/dist/constants/continuation.d.ts +1 -1
  172. package/dist/constants/continuation.js +1 -1
  173. package/dist/constants/index.d.ts +0 -1
  174. package/dist/constants/index.d.ts.map +1 -1
  175. package/dist/constants/index.js +0 -1
  176. package/dist/constants/index.js.map +1 -1
  177. package/dist/constants/limits.d.ts +2 -2
  178. package/dist/constants/limits.js +2 -2
  179. package/dist/constants/telemetry/index.d.ts +9 -3
  180. package/dist/constants/telemetry/index.d.ts.map +1 -1
  181. package/dist/constants/telemetry/index.js +14 -12
  182. package/dist/constants/telemetry/index.js.map +1 -1
  183. package/dist/constants/tools/index.d.ts +2 -2
  184. package/dist/constants/tools/index.js +2 -2
  185. package/dist/contracts/a2a.d.ts +2 -2
  186. package/dist/contracts/api.d.ts +11 -126
  187. package/dist/contracts/api.d.ts.map +1 -1
  188. package/dist/contracts/index.d.ts +3 -2
  189. package/dist/contracts/index.d.ts.map +1 -1
  190. package/dist/contracts/index.js +7 -2
  191. package/dist/contracts/index.js.map +1 -1
  192. package/dist/contracts/schemas.d.ts +6 -165
  193. package/dist/contracts/schemas.d.ts.map +1 -1
  194. package/dist/contracts/schemas.js +6 -36
  195. package/dist/contracts/schemas.js.map +1 -1
  196. package/dist/contracts/session/api.d.ts +94 -0
  197. package/dist/contracts/session/api.d.ts.map +1 -0
  198. package/dist/contracts/session/api.js +10 -0
  199. package/dist/contracts/session/api.js.map +1 -0
  200. package/dist/contracts/session/index.d.ts +7 -0
  201. package/dist/contracts/session/index.d.ts.map +1 -0
  202. package/dist/contracts/session/index.js +7 -0
  203. package/dist/contracts/session/index.js.map +1 -0
  204. package/dist/contracts/session/schemas.d.ts +173 -0
  205. package/dist/contracts/session/schemas.d.ts.map +1 -0
  206. package/dist/contracts/session/schemas.js +52 -0
  207. package/dist/contracts/session/schemas.js.map +1 -0
  208. package/dist/contracts/session/turn-status.d.ts +45 -0
  209. package/dist/contracts/session/turn-status.d.ts.map +1 -0
  210. package/dist/contracts/session/turn-status.js +46 -0
  211. package/dist/contracts/session/turn-status.js.map +1 -0
  212. package/dist/contracts/session/turn.d.ts +64 -0
  213. package/dist/contracts/session/turn.d.ts.map +1 -0
  214. package/dist/contracts/session/turn.js +2 -0
  215. package/dist/contracts/session/turn.js.map +1 -0
  216. package/dist/directory/derive-supervisor.d.ts +1 -1
  217. package/dist/directory/derive-supervisor.js +2 -2
  218. package/dist/directory/derive-supervisor.js.map +1 -1
  219. package/dist/directory/derive.d.ts +2 -2
  220. package/dist/directory/derive.d.ts.map +1 -1
  221. package/dist/directory/derive.js +2 -2
  222. package/dist/directory/derive.js.map +1 -1
  223. package/dist/directory/index.d.ts +2 -2
  224. package/dist/directory/index.d.ts.map +1 -1
  225. package/dist/directory/index.js +1 -1
  226. package/dist/directory/index.js.map +1 -1
  227. package/dist/directory/load.js +2 -2
  228. package/dist/directory/load.js.map +1 -1
  229. package/dist/directory/types.d.ts +2 -2
  230. package/dist/directory/types.d.ts.map +1 -1
  231. package/dist/eval/experiment.d.ts +5 -5
  232. package/dist/eval/experiment.d.ts.map +1 -1
  233. package/dist/eval/experiment.js +18 -18
  234. package/dist/eval/experiment.js.map +1 -1
  235. package/dist/eval/from-turn.d.ts +30 -0
  236. package/dist/eval/from-turn.d.ts.map +1 -0
  237. package/dist/eval/from-turn.js +46 -0
  238. package/dist/eval/from-turn.js.map +1 -0
  239. package/dist/eval/harness-verification.js +7 -7
  240. package/dist/eval/harness-verification.js.map +1 -1
  241. package/dist/eval/index.d.ts +2 -2
  242. package/dist/eval/index.d.ts.map +1 -1
  243. package/dist/eval/index.js +1 -1
  244. package/dist/eval/index.js.map +1 -1
  245. package/dist/eval/judge.d.ts +3 -3
  246. package/dist/eval/judge.d.ts.map +1 -1
  247. package/dist/eval/judge.js +6 -6
  248. package/dist/eval/judge.js.map +1 -1
  249. package/dist/eval/scorers.d.ts +8 -8
  250. package/dist/eval/scorers.d.ts.map +1 -1
  251. package/dist/eval/scorers.js +21 -21
  252. package/dist/eval/scorers.js.map +1 -1
  253. package/dist/eval/types.d.ts +12 -12
  254. package/dist/eval/types.d.ts.map +1 -1
  255. package/dist/eval/uncertainty.d.ts +2 -2
  256. package/dist/eval/uncertainty.js +2 -2
  257. package/dist/execution/code-runtime/types.d.ts +4 -4
  258. package/dist/execution/code-runtime/types.js +2 -2
  259. package/dist/execution/code-runtime/worker.d.ts +1 -1
  260. package/dist/execution/code-runtime/worker.js +1 -1
  261. package/dist/invariants/index.d.ts +1 -1
  262. package/dist/manager/agent/child-session.d.ts +49 -0
  263. package/dist/manager/agent/child-session.d.ts.map +1 -0
  264. package/dist/manager/agent/child-session.js +94 -0
  265. package/dist/manager/agent/child-session.js.map +1 -0
  266. package/dist/manager/agent/lifecycle.d.ts +90 -13
  267. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  268. package/dist/manager/agent/lifecycle.js +332 -88
  269. package/dist/manager/agent/lifecycle.js.map +1 -1
  270. package/dist/manager/index.d.ts +1 -2
  271. package/dist/manager/index.d.ts.map +1 -1
  272. package/dist/manager/index.js +1 -2
  273. package/dist/manager/index.js.map +1 -1
  274. package/dist/manager/plan/lifecycle.d.ts +11 -7
  275. package/dist/manager/plan/lifecycle.d.ts.map +1 -1
  276. package/dist/manager/plan/lifecycle.js +12 -9
  277. package/dist/manager/plan/lifecycle.js.map +1 -1
  278. package/dist/manager/resident/consumption.d.ts +12 -6
  279. package/dist/manager/resident/consumption.d.ts.map +1 -1
  280. package/dist/manager/resident/consumption.js +7 -5
  281. package/dist/manager/resident/consumption.js.map +1 -1
  282. package/dist/manager/resident/evidence-recall.d.ts +5 -5
  283. package/dist/manager/resident/evidence-recall.d.ts.map +1 -1
  284. package/dist/manager/resident/evidence-recall.js +9 -9
  285. package/dist/manager/resident/evidence-recall.js.map +1 -1
  286. package/dist/manager/resident/host.d.ts +2 -2
  287. package/dist/manager/resident/host.d.ts.map +1 -1
  288. package/dist/manager/resident/host.js +1 -1
  289. package/dist/manager/resident/learning-cycle.d.ts +8 -4
  290. package/dist/manager/resident/learning-cycle.d.ts.map +1 -1
  291. package/dist/manager/resident/learning-cycle.js +4 -2
  292. package/dist/manager/resident/learning-cycle.js.map +1 -1
  293. package/dist/manager/resident/learning-observation.d.ts +12 -7
  294. package/dist/manager/resident/learning-observation.d.ts.map +1 -1
  295. package/dist/manager/resident/learning-observation.js +8 -4
  296. package/dist/manager/resident/learning-observation.js.map +1 -1
  297. package/dist/manager/resident/learning-store.d.ts +13 -0
  298. package/dist/manager/resident/learning-store.d.ts.map +1 -1
  299. package/dist/manager/resident/learning-store.js +35 -16
  300. package/dist/manager/resident/learning-store.js.map +1 -1
  301. package/dist/manager/resident/learning.d.ts +14 -14
  302. package/dist/manager/resident/outbox.d.ts +4 -4
  303. package/dist/manager/resident/store.d.ts +8 -8
  304. package/dist/manager/resident/tool-evidence.d.ts +15 -10
  305. package/dist/manager/resident/tool-evidence.d.ts.map +1 -1
  306. package/dist/manager/resident/tool-evidence.js +14 -14
  307. package/dist/manager/resident/tool-evidence.js.map +1 -1
  308. package/dist/manager/session/turn-recorder.d.ts +261 -0
  309. package/dist/manager/session/turn-recorder.d.ts.map +1 -0
  310. package/dist/manager/session/turn-recorder.js +1115 -0
  311. package/dist/manager/session/turn-recorder.js.map +1 -0
  312. package/dist/plugin/lifecycle.d.ts +4 -4
  313. package/dist/plugin/lifecycle.d.ts.map +1 -1
  314. package/dist/plugin/lifecycle.js +17 -10
  315. package/dist/plugin/lifecycle.js.map +1 -1
  316. package/dist/plugin/shell-hook.d.ts +35 -12
  317. package/dist/plugin/shell-hook.d.ts.map +1 -1
  318. package/dist/plugin/shell-hook.js +52 -20
  319. package/dist/plugin/shell-hook.js.map +1 -1
  320. package/dist/pricing/index.d.ts +4 -4
  321. package/dist/pricing/index.js +5 -5
  322. package/dist/pricing/index.js.map +1 -1
  323. package/dist/probe/context.d.ts +3 -2
  324. package/dist/probe/context.d.ts.map +1 -1
  325. package/dist/probe/context.js +2 -1
  326. package/dist/probe/context.js.map +1 -1
  327. package/dist/probe/registry.js +1 -1
  328. package/dist/probe/registry.js.map +1 -1
  329. package/dist/prompt/coding-agent-doctrine.d.ts +1 -1
  330. package/dist/prompt/coding-agent-doctrine.js +1 -1
  331. package/dist/prompt/contributions.d.ts +27 -6
  332. package/dist/prompt/contributions.d.ts.map +1 -1
  333. package/dist/prompt/contributions.js +1 -1
  334. package/dist/prompt/contributions.js.map +1 -1
  335. package/dist/prompt/resident-learning.js +2 -2
  336. package/dist/prompt/resident-learning.js.map +1 -1
  337. package/dist/provider/collect-chat-completion.d.ts +2 -2
  338. package/dist/provider/collect-chat-completion.js +3 -3
  339. package/dist/provider/collect-chat-completion.js.map +1 -1
  340. package/dist/provider/conformance.d.ts +8 -1
  341. package/dist/provider/conformance.d.ts.map +1 -1
  342. package/dist/provider/conformance.js.map +1 -1
  343. package/dist/provider/errors.d.ts +1 -1
  344. package/dist/provider/errors.js +2 -2
  345. package/dist/provider/fallback.d.ts +4 -4
  346. package/dist/provider/fallback.js +6 -6
  347. package/dist/provider/fallback.js.map +1 -1
  348. package/dist/provider/idle-timeout.d.ts +2 -2
  349. package/dist/provider/idle-timeout.d.ts.map +1 -1
  350. package/dist/provider/idle-timeout.js +3 -3
  351. package/dist/provider/idle-timeout.js.map +1 -1
  352. package/dist/provider/instrumentation.d.ts +5 -2
  353. package/dist/provider/instrumentation.d.ts.map +1 -1
  354. package/dist/provider/instrumentation.js +9 -5
  355. package/dist/provider/instrumentation.js.map +1 -1
  356. package/dist/provider/mock.d.ts +1 -1
  357. package/dist/provider/mock.js +1 -1
  358. package/dist/provider/retry.d.ts +2 -2
  359. package/dist/provider/retry.js +6 -6
  360. package/dist/provider/retry.js.map +1 -1
  361. package/dist/provider/stream-text.d.ts +1 -1
  362. package/dist/provider/stream-text.d.ts.map +1 -1
  363. package/dist/provider/stream-text.js +1 -1
  364. package/dist/provider/stream-text.js.map +1 -1
  365. package/dist/provider/thinking-support.js +2 -2
  366. package/dist/provider/thinking-support.js.map +1 -1
  367. package/dist/provider/token-budget.d.ts +2 -2
  368. package/dist/provider/token-budget.d.ts.map +1 -1
  369. package/dist/provider/token-budget.js.map +1 -1
  370. package/dist/public-runtime.d.ts +69 -55
  371. package/dist/public-runtime.d.ts.map +1 -1
  372. package/dist/public-runtime.js +104 -99
  373. package/dist/public-runtime.js.map +1 -1
  374. package/dist/public-tools.d.ts +2 -2
  375. package/dist/public-tools.d.ts.map +1 -1
  376. package/dist/public-tools.js +7 -7
  377. package/dist/public-tools.js.map +1 -1
  378. package/dist/public-types.d.ts +18 -16
  379. package/dist/public-types.d.ts.map +1 -1
  380. package/dist/rag/embedding.js +1 -1
  381. package/dist/rag/embedding.js.map +1 -1
  382. package/dist/read-model/index.d.ts +2 -2
  383. package/dist/read-model/index.d.ts.map +1 -1
  384. package/dist/read-model/index.js +1 -1
  385. package/dist/read-model/index.js.map +1 -1
  386. package/dist/read-model/registry.d.ts +11 -11
  387. package/dist/read-model/registry.d.ts.map +1 -1
  388. package/dist/read-model/registry.js +2 -2
  389. package/dist/read-model/registry.js.map +1 -1
  390. package/dist/read-model/session-status.d.ts +34 -0
  391. package/dist/read-model/session-status.d.ts.map +1 -0
  392. package/dist/read-model/session-status.js +58 -0
  393. package/dist/read-model/session-status.js.map +1 -0
  394. package/dist/registry/command/kernel-commands.d.ts +4 -4
  395. package/dist/registry/command/kernel-commands.d.ts.map +1 -1
  396. package/dist/registry/command/kernel-commands.js +6 -6
  397. package/dist/registry/command/kernel-commands.js.map +1 -1
  398. package/dist/registry/tool/dialect.js +1 -1
  399. package/dist/registry/tool/execute.d.ts +2 -2
  400. package/dist/registry/tool/execute.d.ts.map +1 -1
  401. package/dist/registry/tool/execute.js +19 -7
  402. package/dist/registry/tool/execute.js.map +1 -1
  403. package/dist/registry/tool/portable.d.ts +1 -1
  404. package/dist/registry/tool/portable.js +1 -1
  405. package/dist/registry/tool/presentation.d.ts +1 -1
  406. package/dist/registry/tool/presentation.js +1 -1
  407. package/dist/registry/tool/schema.js +1 -1
  408. package/dist/registry/tool/screen.js +3 -3
  409. package/dist/registry/tool/screen.js.map +1 -1
  410. package/dist/runtime/bidi/index.d.ts +2 -2
  411. package/dist/runtime/bidi/index.d.ts.map +1 -1
  412. package/dist/runtime/bidi/index.js +1 -1
  413. package/dist/runtime/bidi/index.js.map +1 -1
  414. package/dist/runtime/bidi/session.d.ts +14 -11
  415. package/dist/runtime/bidi/session.d.ts.map +1 -1
  416. package/dist/runtime/bidi/session.js +27 -21
  417. package/dist/runtime/bidi/session.js.map +1 -1
  418. package/dist/runtime/jobs/awaited-jobs.d.ts +15 -15
  419. package/dist/runtime/jobs/awaited-jobs.d.ts.map +1 -1
  420. package/dist/runtime/jobs/awaited-jobs.js +13 -13
  421. package/dist/runtime/jobs/awaited-jobs.js.map +1 -1
  422. package/dist/runtime/jobs/registry.d.ts +10 -10
  423. package/dist/runtime/jobs/registry.d.ts.map +1 -1
  424. package/dist/runtime/jobs/registry.js +5 -5
  425. package/dist/runtime/jobs/registry.js.map +1 -1
  426. package/dist/runtime/query/abandon-turn.d.ts +35 -0
  427. package/dist/runtime/query/abandon-turn.d.ts.map +1 -0
  428. package/dist/runtime/query/abandon-turn.js +81 -0
  429. package/dist/runtime/query/abandon-turn.js.map +1 -0
  430. package/dist/runtime/query/approval-policy.d.ts +10 -10
  431. package/dist/runtime/query/approval-policy.d.ts.map +1 -1
  432. package/dist/runtime/query/approval-policy.js +5 -5
  433. package/dist/runtime/query/approval-policy.js.map +1 -1
  434. package/dist/runtime/query/callback-inference.d.ts +1 -1
  435. package/dist/runtime/query/callback-inference.d.ts.map +1 -1
  436. package/dist/runtime/query/callback-inference.js +4 -4
  437. package/dist/runtime/query/callback-inference.js.map +1 -1
  438. package/dist/runtime/query/cancelled-before-start.d.ts +20 -20
  439. package/dist/runtime/query/cancelled-before-start.d.ts.map +1 -1
  440. package/dist/runtime/query/cancelled-before-start.js +72 -55
  441. package/dist/runtime/query/cancelled-before-start.js.map +1 -1
  442. package/dist/runtime/query/checkpoint.d.ts +153 -220
  443. package/dist/runtime/query/checkpoint.d.ts.map +1 -1
  444. package/dist/runtime/query/checkpoint.js +399 -370
  445. package/dist/runtime/query/checkpoint.js.map +1 -1
  446. package/dist/runtime/query/compact-session.d.ts +20 -0
  447. package/dist/runtime/query/compact-session.d.ts.map +1 -0
  448. package/dist/runtime/query/compact-session.js +81 -0
  449. package/dist/runtime/query/compact-session.js.map +1 -0
  450. package/dist/runtime/query/context.d.ts +42 -85
  451. package/dist/runtime/query/context.d.ts.map +1 -1
  452. package/dist/runtime/query/context.js +36 -75
  453. package/dist/runtime/query/context.js.map +1 -1
  454. package/dist/runtime/query/events.d.ts +54 -26
  455. package/dist/runtime/query/events.d.ts.map +1 -1
  456. package/dist/runtime/query/events.js +121 -114
  457. package/dist/runtime/query/events.js.map +1 -1
  458. package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
  459. package/dist/runtime/query/executor/tool-call-admission.js +6 -5
  460. package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
  461. package/dist/runtime/query/executor.d.ts +56 -34
  462. package/dist/runtime/query/executor.d.ts.map +1 -1
  463. package/dist/runtime/query/executor.js +165 -85
  464. package/dist/runtime/query/executor.js.map +1 -1
  465. package/dist/runtime/query/file-evidence-seed.d.ts +1 -1
  466. package/dist/runtime/query/file-evidence-seed.d.ts.map +1 -1
  467. package/dist/runtime/query/file-evidence-seed.js +1 -1
  468. package/dist/runtime/query/finalize-turn.d.ts +55 -0
  469. package/dist/runtime/query/finalize-turn.d.ts.map +1 -0
  470. package/dist/runtime/query/finalize-turn.js +129 -0
  471. package/dist/runtime/query/finalize-turn.js.map +1 -0
  472. package/dist/runtime/query/fork/list.d.ts +15 -0
  473. package/dist/runtime/query/fork/list.d.ts.map +1 -0
  474. package/dist/runtime/query/fork/list.js +11 -0
  475. package/dist/runtime/query/fork/list.js.map +1 -0
  476. package/dist/runtime/query/fork/mutate.d.ts +17 -0
  477. package/dist/runtime/query/fork/mutate.d.ts.map +1 -0
  478. package/dist/runtime/query/fork/mutate.js +69 -0
  479. package/dist/runtime/query/fork/mutate.js.map +1 -0
  480. package/dist/runtime/query/fork/prepare.d.ts +52 -0
  481. package/dist/runtime/query/fork/prepare.d.ts.map +1 -0
  482. package/dist/runtime/query/fork/prepare.js +43 -0
  483. package/dist/runtime/query/fork/prepare.js.map +1 -0
  484. package/dist/runtime/query/guard.d.ts +16 -16
  485. package/dist/runtime/query/guard.d.ts.map +1 -1
  486. package/dist/runtime/query/guard.js +16 -16
  487. package/dist/runtime/query/guard.js.map +1 -1
  488. package/dist/runtime/query/guardrail-presets.d.ts +10 -10
  489. package/dist/runtime/query/guardrail-presets.js +12 -12
  490. package/dist/runtime/query/guardrail-presets.js.map +1 -1
  491. package/dist/runtime/query/guardrails.d.ts +4 -4
  492. package/dist/runtime/query/guardrails.js +11 -11
  493. package/dist/runtime/query/guardrails.js.map +1 -1
  494. package/dist/runtime/query/index.d.ts +178 -155
  495. package/dist/runtime/query/index.d.ts.map +1 -1
  496. package/dist/runtime/query/index.js +1294 -1260
  497. package/dist/runtime/query/index.js.map +1 -1
  498. package/dist/runtime/query/iteration/index.d.ts +16 -16
  499. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  500. package/dist/runtime/query/iteration/index.js +285 -243
  501. package/dist/runtime/query/iteration/index.js.map +1 -1
  502. package/dist/runtime/query/iteration/outstanding-work.d.ts +22 -22
  503. package/dist/runtime/query/iteration/outstanding-work.d.ts.map +1 -1
  504. package/dist/runtime/query/iteration/outstanding-work.js +63 -63
  505. package/dist/runtime/query/iteration/outstanding-work.js.map +1 -1
  506. package/dist/runtime/query/iteration/phases/advisory.js +16 -16
  507. package/dist/runtime/query/iteration/phases/advisory.js.map +1 -1
  508. package/dist/runtime/query/iteration/phases/checkpoint.d.ts +2 -2
  509. package/dist/runtime/query/iteration/phases/checkpoint.d.ts.map +1 -1
  510. package/dist/runtime/query/iteration/phases/checkpoint.js +25 -8
  511. package/dist/runtime/query/iteration/phases/checkpoint.js.map +1 -1
  512. package/dist/runtime/query/iteration/phases/compaction.d.ts +2 -2
  513. package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
  514. package/dist/runtime/query/iteration/phases/compaction.js +74 -72
  515. package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
  516. package/dist/runtime/query/iteration/phases/context.d.ts +32 -29
  517. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  518. package/dist/runtime/query/iteration/phases/context.js +29 -29
  519. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  520. package/dist/runtime/query/iteration/phases/plan.d.ts +2 -2
  521. package/dist/runtime/query/iteration/phases/plan.d.ts.map +1 -1
  522. package/dist/runtime/query/iteration/phases/plan.js +5 -4
  523. package/dist/runtime/query/iteration/phases/plan.js.map +1 -1
  524. package/dist/runtime/query/iteration/phases/tool-review.d.ts +2 -2
  525. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  526. package/dist/runtime/query/iteration/phases/tool-review.js +129 -24
  527. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  528. package/dist/runtime/query/iteration/phases/working-memory.d.ts +27 -3
  529. package/dist/runtime/query/iteration/phases/working-memory.d.ts.map +1 -1
  530. package/dist/runtime/query/iteration/phases/working-memory.js +54 -20
  531. package/dist/runtime/query/iteration/phases/working-memory.js.map +1 -1
  532. package/dist/runtime/query/iteration/step-context.d.ts +11 -0
  533. package/dist/runtime/query/iteration/step-context.d.ts.map +1 -0
  534. package/dist/runtime/query/iteration/step-context.js +14 -0
  535. package/dist/runtime/query/iteration/step-context.js.map +1 -0
  536. package/dist/runtime/query/iteration/step-shaping.d.ts +4 -3
  537. package/dist/runtime/query/iteration/step-shaping.d.ts.map +1 -1
  538. package/dist/runtime/query/iteration/step-shaping.js +20 -19
  539. package/dist/runtime/query/iteration/step-shaping.js.map +1 -1
  540. package/dist/runtime/query/iteration/stream-turn.d.ts +5 -3
  541. package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
  542. package/dist/runtime/query/iteration/stream-turn.js +32 -28
  543. package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
  544. package/dist/runtime/query/plugin-hooks.js +1 -1
  545. package/dist/runtime/query/plugin-hooks.js.map +1 -1
  546. package/dist/runtime/query/prepare-turn.d.ts +105 -0
  547. package/dist/runtime/query/prepare-turn.d.ts.map +1 -0
  548. package/dist/runtime/query/prepare-turn.js +779 -0
  549. package/dist/runtime/query/prepare-turn.js.map +1 -0
  550. package/dist/runtime/query/project-instructions.d.ts +5 -4
  551. package/dist/runtime/query/project-instructions.d.ts.map +1 -1
  552. package/dist/runtime/query/project-instructions.js.map +1 -1
  553. package/dist/runtime/query/prompt-cache.js +1 -1
  554. package/dist/runtime/query/prompt-cache.js.map +1 -1
  555. package/dist/runtime/query/prompt.d.ts +3 -3
  556. package/dist/runtime/query/prompt.d.ts.map +1 -1
  557. package/dist/runtime/query/prompt.js +3 -3
  558. package/dist/runtime/query/prompt.js.map +1 -1
  559. package/dist/runtime/query/question-park.d.ts +7 -7
  560. package/dist/runtime/query/question-park.d.ts.map +1 -1
  561. package/dist/runtime/query/question-park.js +5 -5
  562. package/dist/runtime/query/question-park.js.map +1 -1
  563. package/dist/runtime/query/release-turn.d.ts +53 -0
  564. package/dist/runtime/query/release-turn.d.ts.map +1 -0
  565. package/dist/runtime/query/release-turn.js +95 -0
  566. package/dist/runtime/query/release-turn.js.map +1 -0
  567. package/dist/runtime/query/repeat-call.d.ts +2 -2
  568. package/dist/runtime/query/repeat-call.js +7 -7
  569. package/dist/runtime/query/repeat-call.js.map +1 -1
  570. package/dist/runtime/query/result.d.ts +25 -17
  571. package/dist/runtime/query/result.d.ts.map +1 -1
  572. package/dist/runtime/query/result.js +110 -115
  573. package/dist/runtime/query/result.js.map +1 -1
  574. package/dist/runtime/query/resume-pending.d.ts +34 -17
  575. package/dist/runtime/query/resume-pending.d.ts.map +1 -1
  576. package/dist/runtime/query/resume-pending.js +70 -30
  577. package/dist/runtime/query/resume-pending.js.map +1 -1
  578. package/dist/runtime/query/resume-session.d.ts +65 -0
  579. package/dist/runtime/query/resume-session.d.ts.map +1 -0
  580. package/dist/runtime/query/resume-session.js +88 -0
  581. package/dist/runtime/query/resume-session.js.map +1 -0
  582. package/dist/runtime/query/review-policy.d.ts +57 -16
  583. package/dist/runtime/query/review-policy.d.ts.map +1 -1
  584. package/dist/runtime/query/review-policy.js +115 -11
  585. package/dist/runtime/query/review-policy.js.map +1 -1
  586. package/dist/runtime/query/sandbox-lifecycle.d.ts +5 -5
  587. package/dist/runtime/query/sandbox-lifecycle.d.ts.map +1 -1
  588. package/dist/runtime/query/sandbox-lifecycle.js +4 -4
  589. package/dist/runtime/query/sandbox-lifecycle.js.map +1 -1
  590. package/dist/runtime/query/session-storage.d.ts +75 -0
  591. package/dist/runtime/query/session-storage.d.ts.map +1 -0
  592. package/dist/runtime/query/session-storage.js +236 -0
  593. package/dist/runtime/query/session-storage.js.map +1 -0
  594. package/dist/runtime/query/steering.d.ts +9 -3
  595. package/dist/runtime/query/steering.d.ts.map +1 -1
  596. package/dist/runtime/query/steering.js +12 -2
  597. package/dist/runtime/query/steering.js.map +1 -1
  598. package/dist/runtime/query/token-budget.d.ts +19 -5
  599. package/dist/runtime/query/token-budget.d.ts.map +1 -1
  600. package/dist/runtime/query/token-budget.js +43 -74
  601. package/dist/runtime/query/token-budget.js.map +1 -1
  602. package/dist/runtime/query/tool-call-budget.d.ts +6 -5
  603. package/dist/runtime/query/tool-call-budget.d.ts.map +1 -1
  604. package/dist/runtime/query/tool-call-budget.js +10 -12
  605. package/dist/runtime/query/tool-call-budget.js.map +1 -1
  606. package/dist/runtime/query/tool-executions.d.ts +26 -0
  607. package/dist/runtime/query/tool-executions.d.ts.map +1 -0
  608. package/dist/runtime/query/tool-executions.js +66 -0
  609. package/dist/runtime/query/tool-executions.js.map +1 -0
  610. package/dist/runtime/query/tool-grants.d.ts +3 -3
  611. package/dist/runtime/query/tool-grants.js +3 -3
  612. package/dist/runtime/query/tool-output-budget.d.ts +2 -2
  613. package/dist/runtime/query/tool-output-budget.js +4 -4
  614. package/dist/runtime/query/tool-output-budget.js.map +1 -1
  615. package/dist/runtime/query/tool-pause.d.ts +4 -3
  616. package/dist/runtime/query/tool-pause.d.ts.map +1 -1
  617. package/dist/runtime/query/tool-pause.js +5 -4
  618. package/dist/runtime/query/tool-pause.js.map +1 -1
  619. package/dist/runtime/query/tooling.d.ts +15 -10
  620. package/dist/runtime/query/tooling.d.ts.map +1 -1
  621. package/dist/runtime/query/tooling.js +7 -4
  622. package/dist/runtime/query/tooling.js.map +1 -1
  623. package/dist/runtime/query/turn-state.d.ts +56 -0
  624. package/dist/runtime/query/turn-state.d.ts.map +1 -0
  625. package/dist/runtime/query/turn-state.js +99 -0
  626. package/dist/runtime/query/turn-state.js.map +1 -0
  627. package/dist/sandbox/isolation.d.ts +1 -1
  628. package/dist/sandbox/isolation.js +2 -2
  629. package/dist/sandbox/isolation.js.map +1 -1
  630. package/dist/sandbox/provider/local.d.ts +2 -2
  631. package/dist/sandbox/provider/local.js +7 -7
  632. package/dist/sandbox/provider/local.js.map +1 -1
  633. package/dist/scheduler/completion-inbox.d.ts +21 -21
  634. package/dist/scheduler/completion-inbox.js +36 -36
  635. package/dist/scheduler/completion-inbox.js.map +1 -1
  636. package/dist/scheduler/delegating.d.ts +6 -3
  637. package/dist/scheduler/delegating.d.ts.map +1 -1
  638. package/dist/scheduler/delegating.js +15 -8
  639. package/dist/scheduler/delegating.js.map +1 -1
  640. package/dist/scheduler/local.d.ts +10 -8
  641. package/dist/scheduler/local.d.ts.map +1 -1
  642. package/dist/scheduler/local.js +37 -11
  643. package/dist/scheduler/local.js.map +1 -1
  644. package/dist/session/events/index.d.ts +3 -3
  645. package/dist/session/events/index.d.ts.map +1 -1
  646. package/dist/session/events/index.js +4 -8
  647. package/dist/session/events/index.js.map +1 -1
  648. package/dist/session/handoff/broadcast.d.ts +3 -3
  649. package/dist/session/handoff/broadcast.d.ts.map +1 -1
  650. package/dist/session/handoff/broadcast.js +4 -4
  651. package/dist/session/handoff/broadcast.js.map +1 -1
  652. package/dist/session/handoff/events.d.ts +1 -1
  653. package/dist/session/handoff/events.js +1 -1
  654. package/dist/session/handoff/index.d.ts +1 -1
  655. package/dist/session/handoff/index.d.ts.map +1 -1
  656. package/dist/session/handoff/single.d.ts +12 -12
  657. package/dist/session/handoff/single.d.ts.map +1 -1
  658. package/dist/session/handoff/single.js +9 -9
  659. package/dist/session/handoff/single.js.map +1 -1
  660. package/dist/session/handoff/version.d.ts +7 -7
  661. package/dist/session/handoff/version.d.ts.map +1 -1
  662. package/dist/session/handoff/version.js +2 -2
  663. package/dist/session/handoff/version.js.map +1 -1
  664. package/dist/session/home.d.ts +23 -0
  665. package/dist/session/home.d.ts.map +1 -0
  666. package/dist/session/home.js +45 -0
  667. package/dist/session/home.js.map +1 -0
  668. package/dist/session/index.d.ts +1 -0
  669. package/dist/session/index.d.ts.map +1 -1
  670. package/dist/session/index.js +1 -0
  671. package/dist/session/index.js.map +1 -1
  672. package/dist/session/log-hash.d.ts +25 -0
  673. package/dist/session/log-hash.d.ts.map +1 -0
  674. package/dist/session/log-hash.js +82 -0
  675. package/dist/session/log-hash.js.map +1 -0
  676. package/dist/session/messages.d.ts +11 -0
  677. package/dist/session/messages.d.ts.map +1 -0
  678. package/dist/session/messages.js +32 -0
  679. package/dist/session/messages.js.map +1 -0
  680. package/dist/session/paths.d.ts +168 -0
  681. package/dist/session/paths.d.ts.map +1 -0
  682. package/dist/session/paths.js +338 -0
  683. package/dist/session/paths.js.map +1 -0
  684. package/dist/session/retention/archive.d.ts +8 -1
  685. package/dist/session/retention/archive.d.ts.map +1 -1
  686. package/dist/session/retention/archive.js +3 -5
  687. package/dist/session/retention/archive.js.map +1 -1
  688. package/dist/session/status/derive.d.ts +13 -13
  689. package/dist/session/status/derive.d.ts.map +1 -1
  690. package/dist/session/status/derive.js +20 -20
  691. package/dist/session/status/derive.js.map +1 -1
  692. package/dist/session/workspace/git-worktree.d.ts +8 -1
  693. package/dist/session/workspace/git-worktree.d.ts.map +1 -1
  694. package/dist/session/workspace/git-worktree.js +29 -1
  695. package/dist/session/workspace/git-worktree.js.map +1 -1
  696. package/dist/session/workspace/index.d.ts +2 -4
  697. package/dist/session/workspace/index.d.ts.map +1 -1
  698. package/dist/session/workspace/index.js +2 -3
  699. package/dist/session/workspace/index.js.map +1 -1
  700. package/dist/session/workspace/shared-session.d.ts +112 -0
  701. package/dist/session/workspace/shared-session.d.ts.map +1 -0
  702. package/dist/session/workspace/shared-session.js +290 -0
  703. package/dist/session/workspace/shared-session.js.map +1 -0
  704. package/dist/session-query/index.d.ts +67 -0
  705. package/dist/session-query/index.d.ts.map +1 -0
  706. package/dist/session-query/index.js +100 -0
  707. package/dist/session-query/index.js.map +1 -0
  708. package/dist/skills/registry.d.ts +1 -1
  709. package/dist/skills/registry.js +1 -1
  710. package/dist/store/activity/memory.d.ts +3 -3
  711. package/dist/store/activity/memory.d.ts.map +1 -1
  712. package/dist/store/activity/memory.js +4 -4
  713. package/dist/store/activity/memory.js.map +1 -1
  714. package/dist/store/attachment/index.d.ts +4 -4
  715. package/dist/store/attachment/index.d.ts.map +1 -1
  716. package/dist/store/attachment/index.js +3 -3
  717. package/dist/store/attachment/index.js.map +1 -1
  718. package/dist/store/budget/disk.d.ts +59 -0
  719. package/dist/store/budget/disk.d.ts.map +1 -0
  720. package/dist/store/budget/disk.js +179 -0
  721. package/dist/store/budget/disk.js.map +1 -0
  722. package/dist/store/budget/index.d.ts +6 -0
  723. package/dist/store/budget/index.d.ts.map +1 -0
  724. package/dist/store/budget/index.js +6 -0
  725. package/dist/store/budget/index.js.map +1 -0
  726. package/dist/store/budget/ledger.d.ts +156 -0
  727. package/dist/store/budget/ledger.d.ts.map +1 -0
  728. package/dist/store/budget/ledger.js +683 -0
  729. package/dist/store/budget/ledger.js.map +1 -0
  730. package/dist/store/budget/memory.d.ts +18 -0
  731. package/dist/store/budget/memory.d.ts.map +1 -0
  732. package/dist/store/budget/memory.js +31 -0
  733. package/dist/store/budget/memory.js.map +1 -0
  734. package/dist/store/checkpoint/contract.d.ts +140 -0
  735. package/dist/store/checkpoint/contract.d.ts.map +1 -0
  736. package/dist/store/checkpoint/contract.js +91 -0
  737. package/dist/store/checkpoint/contract.js.map +1 -0
  738. package/dist/store/checkpoint/disk.d.ts +44 -0
  739. package/dist/store/checkpoint/disk.d.ts.map +1 -0
  740. package/dist/store/checkpoint/disk.js +168 -0
  741. package/dist/store/checkpoint/disk.js.map +1 -0
  742. package/dist/store/checkpoint/index.d.ts +9 -0
  743. package/dist/store/checkpoint/index.d.ts.map +1 -0
  744. package/dist/store/checkpoint/index.js +7 -0
  745. package/dist/store/checkpoint/index.js.map +1 -0
  746. package/dist/store/checkpoint/memory.d.ts +27 -0
  747. package/dist/store/checkpoint/memory.d.ts.map +1 -0
  748. package/dist/store/checkpoint/memory.js +80 -0
  749. package/dist/store/checkpoint/memory.js.map +1 -0
  750. package/dist/store/checkpoint/prune.d.ts +45 -0
  751. package/dist/store/checkpoint/prune.d.ts.map +1 -0
  752. package/dist/store/checkpoint/prune.js +71 -0
  753. package/dist/store/checkpoint/prune.js.map +1 -0
  754. package/dist/store/config/index.d.ts +1 -1
  755. package/dist/store/config/index.js +1 -1
  756. package/dist/store/evidence/disk.d.ts +25 -8
  757. package/dist/store/evidence/disk.d.ts.map +1 -1
  758. package/dist/store/evidence/disk.js +148 -47
  759. package/dist/store/evidence/disk.js.map +1 -1
  760. package/dist/store/evidence/index-page.d.ts +31 -140
  761. package/dist/store/evidence/index-page.d.ts.map +1 -1
  762. package/dist/store/evidence/index-page.js +59 -129
  763. package/dist/store/evidence/index-page.js.map +1 -1
  764. package/dist/store/evidence/source-text.d.ts +7 -6
  765. package/dist/store/evidence/source-text.d.ts.map +1 -1
  766. package/dist/store/evidence/source-text.js +16 -23
  767. package/dist/store/evidence/source-text.js.map +1 -1
  768. package/dist/store/evidence/types.d.ts +38 -39
  769. package/dist/store/evidence/types.d.ts.map +1 -1
  770. package/dist/store/feedback/conformance.d.ts +6 -6
  771. package/dist/store/feedback/conformance.d.ts.map +1 -1
  772. package/dist/store/feedback/conformance.js +30 -29
  773. package/dist/store/feedback/conformance.js.map +1 -1
  774. package/dist/store/feedback/disk.d.ts +20 -19
  775. package/dist/store/feedback/disk.d.ts.map +1 -1
  776. package/dist/store/feedback/disk.js +53 -53
  777. package/dist/store/feedback/disk.js.map +1 -1
  778. package/dist/store/feedback/index.d.ts +1 -1
  779. package/dist/store/feedback/index.d.ts.map +1 -1
  780. package/dist/store/feedback/index.js +1 -1
  781. package/dist/store/feedback/index.js.map +1 -1
  782. package/dist/store/feedback/memory.d.ts +8 -5
  783. package/dist/store/feedback/memory.d.ts.map +1 -1
  784. package/dist/store/feedback/memory.js +0 -0
  785. package/dist/store/feedback/memory.js.map +1 -1
  786. package/dist/store/feedback/types.d.ts +12 -11
  787. package/dist/store/feedback/types.d.ts.map +1 -1
  788. package/dist/store/feedback/types.js +3 -3
  789. package/dist/store/feedback/types.js.map +1 -1
  790. package/dist/store/index.d.ts +7 -8
  791. package/dist/store/index.d.ts.map +1 -1
  792. package/dist/store/index.js +4 -16
  793. package/dist/store/index.js.map +1 -1
  794. package/dist/store/memory/digest.d.ts +15 -0
  795. package/dist/store/memory/digest.d.ts.map +1 -0
  796. package/dist/store/memory/digest.js +27 -0
  797. package/dist/store/memory/digest.js.map +1 -0
  798. package/dist/store/memory/disk.d.ts.map +1 -1
  799. package/dist/store/memory/disk.js +42 -7
  800. package/dist/store/memory/disk.js.map +1 -1
  801. package/dist/store/memory/index-file.d.ts +56 -0
  802. package/dist/store/memory/index-file.d.ts.map +1 -0
  803. package/dist/store/memory/index-file.js +92 -0
  804. package/dist/store/memory/index-file.js.map +1 -0
  805. package/dist/store/memory/index.d.ts.map +1 -1
  806. package/dist/store/memory/index.js +4 -2
  807. package/dist/store/memory/index.js.map +1 -1
  808. package/dist/store/memory/links.d.ts +15 -0
  809. package/dist/store/memory/links.d.ts.map +1 -0
  810. package/dist/store/memory/links.js +35 -0
  811. package/dist/store/memory/links.js.map +1 -0
  812. package/dist/store/memory/markdown-format.d.ts +88 -0
  813. package/dist/store/memory/markdown-format.d.ts.map +1 -0
  814. package/dist/store/memory/markdown-format.js +222 -0
  815. package/dist/store/memory/markdown-format.js.map +1 -0
  816. package/dist/store/memory/markdown.d.ts +109 -0
  817. package/dist/store/memory/markdown.d.ts.map +1 -0
  818. package/dist/store/memory/markdown.js +606 -0
  819. package/dist/store/memory/markdown.js.map +1 -0
  820. package/dist/store/memory/memory.d.ts.map +1 -1
  821. package/dist/store/memory/memory.js +17 -4
  822. package/dist/store/memory/memory.js.map +1 -1
  823. package/dist/store/memory/naming.d.ts +66 -0
  824. package/dist/store/memory/naming.d.ts.map +1 -0
  825. package/dist/store/memory/naming.js +162 -0
  826. package/dist/store/memory/naming.js.map +1 -0
  827. package/dist/store/memory/origin.d.ts +25 -0
  828. package/dist/store/memory/origin.d.ts.map +1 -0
  829. package/dist/store/memory/origin.js +26 -0
  830. package/dist/store/memory/origin.js.map +1 -0
  831. package/dist/store/session/disk.d.ts +21 -24
  832. package/dist/store/session/disk.d.ts.map +1 -1
  833. package/dist/store/session/disk.js +27 -132
  834. package/dist/store/session/disk.js.map +1 -1
  835. package/dist/store/session/index.d.ts +0 -3
  836. package/dist/store/session/index.d.ts.map +1 -1
  837. package/dist/store/session/index.js +5 -7
  838. package/dist/store/session/index.js.map +1 -1
  839. package/dist/store/session/memory.d.ts +1 -8
  840. package/dist/store/session/memory.d.ts.map +1 -1
  841. package/dist/store/session/memory.js +1 -58
  842. package/dist/store/session/memory.js.map +1 -1
  843. package/dist/store/session-claim.d.ts +30 -0
  844. package/dist/store/session-claim.d.ts.map +1 -0
  845. package/dist/store/session-claim.js +71 -0
  846. package/dist/store/session-claim.js.map +1 -0
  847. package/dist/store/session-index/fts.d.ts +60 -0
  848. package/dist/store/session-index/fts.d.ts.map +1 -0
  849. package/dist/store/session-index/fts.js +160 -0
  850. package/dist/store/session-index/fts.js.map +1 -0
  851. package/dist/store/session-index/index.d.ts +206 -0
  852. package/dist/store/session-index/index.d.ts.map +1 -0
  853. package/dist/store/session-index/index.js +22 -0
  854. package/dist/store/session-index/index.js.map +1 -0
  855. package/dist/store/session-index/rebuild.d.ts +180 -0
  856. package/dist/store/session-index/rebuild.d.ts.map +1 -0
  857. package/dist/store/session-index/rebuild.js +669 -0
  858. package/dist/store/session-index/rebuild.js.map +1 -0
  859. package/dist/store/session-index/refs.d.ts +66 -0
  860. package/dist/store/session-index/refs.d.ts.map +1 -0
  861. package/dist/store/session-index/refs.js +107 -0
  862. package/dist/store/session-index/refs.js.map +1 -0
  863. package/dist/store/session-index/scan.d.ts +42 -0
  864. package/dist/store/session-index/scan.d.ts.map +1 -0
  865. package/dist/store/session-index/scan.js +188 -0
  866. package/dist/store/session-index/scan.js.map +1 -0
  867. package/dist/store/session-index/sqlite.d.ts +76 -0
  868. package/dist/store/session-index/sqlite.d.ts.map +1 -0
  869. package/dist/store/session-index/sqlite.js +547 -0
  870. package/dist/store/session-index/sqlite.js.map +1 -0
  871. package/dist/store/session-log/chain.d.ts +111 -0
  872. package/dist/store/session-log/chain.d.ts.map +1 -0
  873. package/dist/store/session-log/chain.js +212 -0
  874. package/dist/store/session-log/chain.js.map +1 -0
  875. package/dist/store/session-log/conformance.d.ts +61 -0
  876. package/dist/store/session-log/conformance.d.ts.map +1 -0
  877. package/dist/store/session-log/conformance.js +392 -0
  878. package/dist/store/session-log/conformance.js.map +1 -0
  879. package/dist/store/session-log/core.d.ts +203 -0
  880. package/dist/store/session-log/core.d.ts.map +1 -0
  881. package/dist/store/session-log/core.js +516 -0
  882. package/dist/store/session-log/core.js.map +1 -0
  883. package/dist/store/session-log/disk.d.ts +56 -0
  884. package/dist/store/session-log/disk.d.ts.map +1 -0
  885. package/dist/store/session-log/disk.js +169 -0
  886. package/dist/store/session-log/disk.js.map +1 -0
  887. package/dist/store/session-log/fold.d.ts +115 -0
  888. package/dist/store/session-log/fold.d.ts.map +1 -0
  889. package/dist/store/session-log/fold.js +265 -0
  890. package/dist/store/session-log/fold.js.map +1 -0
  891. package/dist/store/session-log/heal.d.ts +34 -0
  892. package/dist/store/session-log/heal.d.ts.map +1 -0
  893. package/dist/store/session-log/heal.js +12 -0
  894. package/dist/store/session-log/heal.js.map +1 -0
  895. package/dist/store/session-log/held-leases.d.ts +56 -0
  896. package/dist/store/session-log/held-leases.d.ts.map +1 -0
  897. package/dist/store/session-log/held-leases.js +67 -0
  898. package/dist/store/session-log/held-leases.js.map +1 -0
  899. package/dist/store/session-log/index.d.ts +10 -0
  900. package/dist/store/session-log/index.d.ts.map +1 -0
  901. package/dist/store/session-log/index.js +16 -0
  902. package/dist/store/session-log/index.js.map +1 -0
  903. package/dist/store/session-log/lease.d.ts +126 -0
  904. package/dist/store/session-log/lease.d.ts.map +1 -0
  905. package/dist/store/session-log/lease.js +226 -0
  906. package/dist/store/session-log/lease.js.map +1 -0
  907. package/dist/store/session-log/memory.d.ts +43 -0
  908. package/dist/store/session-log/memory.d.ts.map +1 -0
  909. package/dist/store/session-log/memory.js +78 -0
  910. package/dist/store/session-log/memory.js.map +1 -0
  911. package/dist/store/session-log/spill.d.ts +109 -0
  912. package/dist/store/session-log/spill.d.ts.map +1 -0
  913. package/dist/store/session-log/spill.js +223 -0
  914. package/dist/store/session-log/spill.js.map +1 -0
  915. package/dist/store/task/context.d.ts +25 -0
  916. package/dist/store/task/context.d.ts.map +1 -0
  917. package/dist/store/task/context.js +18 -0
  918. package/dist/store/task/context.js.map +1 -0
  919. package/dist/store/task/disk.d.ts +29 -26
  920. package/dist/store/task/disk.d.ts.map +1 -1
  921. package/dist/store/task/disk.js +102 -137
  922. package/dist/store/task/disk.js.map +1 -1
  923. package/dist/store/task/memory.d.ts +2 -2
  924. package/dist/store/task/memory.d.ts.map +1 -1
  925. package/dist/store/task/memory.js +10 -6
  926. package/dist/store/task/memory.js.map +1 -1
  927. package/dist/store/topic/index.js +2 -2
  928. package/dist/store/topic/index.js.map +1 -1
  929. package/dist/store/topic/objective.d.ts.map +1 -1
  930. package/dist/store/topic/objective.js +10 -3
  931. package/dist/store/topic/objective.js.map +1 -1
  932. package/dist/store/topic/state.js +1 -1
  933. package/dist/streaming/coalesce.d.ts +3 -3
  934. package/dist/streaming/coalesce.d.ts.map +1 -1
  935. package/dist/streaming/coalesce.js +1 -1
  936. package/dist/streaming/coalesce.js.map +1 -1
  937. package/dist/telemetry/attributes.d.ts +9 -8
  938. package/dist/telemetry/attributes.d.ts.map +1 -1
  939. package/dist/telemetry/attributes.js +6 -5
  940. package/dist/telemetry/attributes.js.map +1 -1
  941. package/dist/telemetry/metrics.d.ts +2 -2
  942. package/dist/telemetry/metrics.d.ts.map +1 -1
  943. package/dist/telemetry/metrics.js +5 -5
  944. package/dist/telemetry/metrics.js.map +1 -1
  945. package/dist/telemetry/runtime-accessors.js +1 -1
  946. package/dist/telemetry/runtime-accessors.js.map +1 -1
  947. package/dist/test-support/ids.d.ts +4 -4
  948. package/dist/test-support/ids.d.ts.map +1 -1
  949. package/dist/test-support/ids.js +3 -3
  950. package/dist/test-support/ids.js.map +1 -1
  951. package/dist/testing.d.ts +4 -6
  952. package/dist/testing.d.ts.map +1 -1
  953. package/dist/testing.js +3 -5
  954. package/dist/testing.js.map +1 -1
  955. package/dist/tools/advisory/index.js +1 -1
  956. package/dist/tools/advisory/index.js.map +1 -1
  957. package/dist/tools/builtins/bash.d.ts +6 -0
  958. package/dist/tools/builtins/bash.d.ts.map +1 -1
  959. package/dist/tools/builtins/bash.js +37 -5
  960. package/dist/tools/builtins/bash.js.map +1 -1
  961. package/dist/tools/builtins/content-fingerprint.d.ts +2 -2
  962. package/dist/tools/builtins/content-fingerprint.js +2 -2
  963. package/dist/tools/builtins/edit-apply.js +1 -1
  964. package/dist/tools/builtins/edit-apply.js.map +1 -1
  965. package/dist/tools/builtins/edit.d.ts.map +1 -1
  966. package/dist/tools/builtins/edit.js +3 -0
  967. package/dist/tools/builtins/edit.js.map +1 -1
  968. package/dist/tools/builtins/glob.d.ts.map +1 -1
  969. package/dist/tools/builtins/glob.js +3 -0
  970. package/dist/tools/builtins/glob.js.map +1 -1
  971. package/dist/tools/builtins/grep.d.ts.map +1 -1
  972. package/dist/tools/builtins/grep.js +3 -0
  973. package/dist/tools/builtins/grep.js.map +1 -1
  974. package/dist/tools/builtins/job.js +5 -5
  975. package/dist/tools/builtins/job.js.map +1 -1
  976. package/dist/tools/builtins/ls.d.ts +1 -1
  977. package/dist/tools/builtins/ls.d.ts.map +1 -1
  978. package/dist/tools/builtins/ls.js +3 -0
  979. package/dist/tools/builtins/ls.js.map +1 -1
  980. package/dist/tools/builtins/lsp.d.ts +1 -1
  981. package/dist/tools/builtins/lsp.d.ts.map +1 -1
  982. package/dist/tools/builtins/lsp.js +5 -2
  983. package/dist/tools/builtins/lsp.js.map +1 -1
  984. package/dist/tools/builtins/read-file.d.ts.map +1 -1
  985. package/dist/tools/builtins/read-file.js +3 -0
  986. package/dist/tools/builtins/read-file.js.map +1 -1
  987. package/dist/tools/builtins/run-code.js +9 -9
  988. package/dist/tools/builtins/run-code.js.map +1 -1
  989. package/dist/tools/builtins/skill.js +3 -3
  990. package/dist/tools/builtins/skill.js.map +1 -1
  991. package/dist/tools/builtins/wait-for-job-bounds.d.ts +4 -4
  992. package/dist/tools/builtins/wait-for-job-bounds.d.ts.map +1 -1
  993. package/dist/tools/builtins/wait-for-job-bounds.js +2 -2
  994. package/dist/tools/builtins/wait-for-job-bounds.js.map +1 -1
  995. package/dist/tools/builtins/wait-for-job.js +3 -3
  996. package/dist/tools/builtins/wait-for-job.js.map +1 -1
  997. package/dist/tools/builtins/web-guidance.d.ts +2 -2
  998. package/dist/tools/builtins/web-guidance.js +2 -2
  999. package/dist/tools/builtins/web.js +3 -3
  1000. package/dist/tools/builtins/web.js.map +1 -1
  1001. package/dist/tools/builtins/write-file.d.ts.map +1 -1
  1002. package/dist/tools/builtins/write-file.js +3 -0
  1003. package/dist/tools/builtins/write-file.js.map +1 -1
  1004. package/dist/tools/coordinator/agent.d.ts +1 -1
  1005. package/dist/tools/coordinator/agent.js +7 -7
  1006. package/dist/tools/coordinator/agent.js.map +1 -1
  1007. package/dist/tools/coordinator/ask-user-question.d.ts +10 -9
  1008. package/dist/tools/coordinator/ask-user-question.d.ts.map +1 -1
  1009. package/dist/tools/coordinator/ask-user-question.js +9 -8
  1010. package/dist/tools/coordinator/ask-user-question.js.map +1 -1
  1011. package/dist/tools/coordinator/index.d.ts +17 -11
  1012. package/dist/tools/coordinator/index.d.ts.map +1 -1
  1013. package/dist/tools/coordinator/index.js +45 -44
  1014. package/dist/tools/coordinator/index.js.map +1 -1
  1015. package/dist/tools/coordinator/outcome.d.ts +5 -5
  1016. package/dist/tools/coordinator/outcome.js +7 -7
  1017. package/dist/tools/coordinator/outcome.js.map +1 -1
  1018. package/dist/tools/coordinator/plan-dependencies.js +1 -1
  1019. package/dist/tools/coordinator/plan-dependencies.js.map +1 -1
  1020. package/dist/tools/coordinator/wait-with-idle-bound.d.ts +4 -4
  1021. package/dist/tools/coordinator/wait-with-idle-bound.d.ts.map +1 -1
  1022. package/dist/tools/coordinator/wait-with-idle-bound.js +2 -2
  1023. package/dist/tools/coordinator/wait-with-idle-bound.js.map +1 -1
  1024. package/dist/tools/defineTool.d.ts +5 -1
  1025. package/dist/tools/defineTool.d.ts.map +1 -1
  1026. package/dist/tools/defineTool.js +4 -0
  1027. package/dist/tools/defineTool.js.map +1 -1
  1028. package/dist/tools/env-scrub.d.ts +1 -1
  1029. package/dist/tools/env-scrub.js +1 -1
  1030. package/dist/tools/goal/index.d.ts +10 -6
  1031. package/dist/tools/goal/index.d.ts.map +1 -1
  1032. package/dist/tools/goal/index.js +9 -9
  1033. package/dist/tools/goal/index.js.map +1 -1
  1034. package/dist/tools/memory/fields.d.ts +8 -0
  1035. package/dist/tools/memory/fields.d.ts.map +1 -0
  1036. package/dist/tools/memory/fields.js +22 -0
  1037. package/dist/tools/memory/fields.js.map +1 -0
  1038. package/dist/tools/memory/read.d.ts.map +1 -1
  1039. package/dist/tools/memory/read.js +60 -7
  1040. package/dist/tools/memory/read.js.map +1 -1
  1041. package/dist/tools/memory/resolve.d.ts +21 -0
  1042. package/dist/tools/memory/resolve.d.ts.map +1 -0
  1043. package/dist/tools/memory/resolve.js +23 -0
  1044. package/dist/tools/memory/resolve.js.map +1 -0
  1045. package/dist/tools/memory/save.d.ts.map +1 -1
  1046. package/dist/tools/memory/save.js +57 -18
  1047. package/dist/tools/memory/save.js.map +1 -1
  1048. package/dist/tools/memory/search.d.ts.map +1 -1
  1049. package/dist/tools/memory/search.js +9 -2
  1050. package/dist/tools/memory/search.js.map +1 -1
  1051. package/dist/tools/memory/update.d.ts.map +1 -1
  1052. package/dist/tools/memory/update.js +45 -7
  1053. package/dist/tools/memory/update.js.map +1 -1
  1054. package/dist/tools/paths.d.ts +29 -3
  1055. package/dist/tools/paths.d.ts.map +1 -1
  1056. package/dist/tools/paths.js +81 -23
  1057. package/dist/tools/paths.js.map +1 -1
  1058. package/dist/tools/posix-path.js +1 -1
  1059. package/dist/tools/posix-path.js.map +1 -1
  1060. package/dist/tools/resident-history.d.ts +1 -1
  1061. package/dist/tools/resident-history.js +1 -1
  1062. package/dist/tools/resident-tool-evidence.d.ts +1 -1
  1063. package/dist/tools/resident-tool-evidence.d.ts.map +1 -1
  1064. package/dist/tools/resident-tool-evidence.js +1 -1
  1065. package/dist/tools/resident-tool-evidence.js.map +1 -1
  1066. package/dist/tools/task/create.d.ts +2 -2
  1067. package/dist/tools/task/create.d.ts.map +1 -1
  1068. package/dist/tools/task/create.js +3 -2
  1069. package/dist/tools/task/create.js.map +1 -1
  1070. package/dist/tools/task/index.d.ts +16 -2
  1071. package/dist/tools/task/index.d.ts.map +1 -1
  1072. package/dist/tools/task/index.js +4 -3
  1073. package/dist/tools/task/index.js.map +1 -1
  1074. package/dist/tools/task/list.d.ts +4 -2
  1075. package/dist/tools/task/list.d.ts.map +1 -1
  1076. package/dist/tools/task/list.js +8 -4
  1077. package/dist/tools/task/list.js.map +1 -1
  1078. package/dist/turn/LimitChecker.d.ts +30 -0
  1079. package/dist/turn/LimitChecker.d.ts.map +1 -0
  1080. package/dist/turn/LimitChecker.js +57 -0
  1081. package/dist/turn/LimitChecker.js.map +1 -0
  1082. package/dist/turn/command-gate.d.ts +107 -0
  1083. package/dist/turn/command-gate.d.ts.map +1 -0
  1084. package/dist/turn/command-gate.js +221 -0
  1085. package/dist/turn/command-gate.js.map +1 -0
  1086. package/dist/turn/drain.d.ts +138 -0
  1087. package/dist/turn/drain.d.ts.map +1 -0
  1088. package/dist/turn/drain.js +209 -0
  1089. package/dist/turn/drain.js.map +1 -0
  1090. package/dist/turn/evidence-query.d.ts +41 -0
  1091. package/dist/turn/evidence-query.d.ts.map +1 -0
  1092. package/dist/turn/evidence-query.js +270 -0
  1093. package/dist/turn/evidence-query.js.map +1 -0
  1094. package/dist/turn/evidence-recall.d.ts +102 -0
  1095. package/dist/turn/evidence-recall.d.ts.map +1 -0
  1096. package/dist/turn/evidence-recall.js +635 -0
  1097. package/dist/turn/evidence-recall.js.map +1 -0
  1098. package/dist/turn/index.d.ts +17 -0
  1099. package/dist/turn/index.d.ts.map +1 -0
  1100. package/dist/turn/index.js +9 -0
  1101. package/dist/turn/index.js.map +1 -0
  1102. package/dist/turn/json-claim-verifier.d.ts +83 -0
  1103. package/dist/turn/json-claim-verifier.d.ts.map +1 -0
  1104. package/dist/turn/json-claim-verifier.js +200 -0
  1105. package/dist/turn/json-claim-verifier.js.map +1 -0
  1106. package/dist/turn/memory-promoter.d.ts +43 -0
  1107. package/dist/turn/memory-promoter.d.ts.map +1 -0
  1108. package/dist/turn/memory-promoter.js +111 -0
  1109. package/dist/turn/memory-promoter.js.map +1 -0
  1110. package/dist/turn/memory-recall.d.ts +33 -0
  1111. package/dist/turn/memory-recall.d.ts.map +1 -0
  1112. package/dist/turn/memory-recall.js +248 -0
  1113. package/dist/turn/memory-recall.js.map +1 -0
  1114. package/dist/turn/preparation-context-error.d.ts.map +1 -0
  1115. package/dist/turn/preparation-context-error.js.map +1 -0
  1116. package/dist/turn/reporter.d.ts +8 -0
  1117. package/dist/turn/reporter.d.ts.map +1 -0
  1118. package/dist/turn/reporter.js +420 -0
  1119. package/dist/turn/reporter.js.map +1 -0
  1120. package/dist/turn/workspace-fingerprint.d.ts.map +1 -0
  1121. package/dist/turn/workspace-fingerprint.js.map +1 -0
  1122. package/dist/types/activity/index.d.ts +2 -2
  1123. package/dist/types/activity/index.d.ts.map +1 -1
  1124. package/dist/types/advisory/config.d.ts +7 -7
  1125. package/dist/types/advisory/config.d.ts.map +1 -1
  1126. package/dist/types/agent/base.d.ts +71 -44
  1127. package/dist/types/agent/base.d.ts.map +1 -1
  1128. package/dist/types/agent/core.d.ts +10 -10
  1129. package/dist/types/agent/core.d.ts.map +1 -1
  1130. package/dist/types/agent/delegate.d.ts +2 -2
  1131. package/dist/types/agent/factory.d.ts +6 -4
  1132. package/dist/types/agent/factory.d.ts.map +1 -1
  1133. package/dist/types/agent/manager.d.ts +6 -6
  1134. package/dist/types/agent/manager.d.ts.map +1 -1
  1135. package/dist/types/agent/pipeline.d.ts +5 -4
  1136. package/dist/types/agent/pipeline.d.ts.map +1 -1
  1137. package/dist/types/agent/reactive.d.ts +11 -10
  1138. package/dist/types/agent/reactive.d.ts.map +1 -1
  1139. package/dist/types/agent/router.d.ts +1 -1
  1140. package/dist/types/agent/scheduler.d.ts +27 -11
  1141. package/dist/types/agent/scheduler.d.ts.map +1 -1
  1142. package/dist/types/agent/supervisor.d.ts +13 -13
  1143. package/dist/types/agent/task.d.ts +48 -12
  1144. package/dist/types/agent/task.d.ts.map +1 -1
  1145. package/dist/types/agent/working-memory.d.ts +5 -4
  1146. package/dist/types/agent/working-memory.d.ts.map +1 -1
  1147. package/dist/types/authorization/index.d.ts +6 -6
  1148. package/dist/types/bidi/index.d.ts +21 -12
  1149. package/dist/types/bidi/index.d.ts.map +1 -1
  1150. package/dist/types/bus/index.d.ts +34 -28
  1151. package/dist/types/bus/index.d.ts.map +1 -1
  1152. package/dist/types/code-navigation/index.d.ts +1 -1
  1153. package/dist/types/common/index.d.ts +10 -18
  1154. package/dist/types/common/index.d.ts.map +1 -1
  1155. package/dist/types/common/index.js +3 -2
  1156. package/dist/types/common/index.js.map +1 -1
  1157. package/dist/types/connector/core.d.ts +2 -2
  1158. package/dist/types/connector/definition.d.ts +1 -1
  1159. package/dist/types/connector/mcp.d.ts +1 -1
  1160. package/dist/types/errors/catalog.js +4 -4
  1161. package/dist/types/errors/catalog.js.map +1 -1
  1162. package/dist/types/errors/index.d.ts +5 -5
  1163. package/dist/types/errors/index.d.ts.map +1 -1
  1164. package/dist/types/guardrail/index.d.ts +12 -10
  1165. package/dist/types/guardrail/index.d.ts.map +1 -1
  1166. package/dist/types/hitl/index.d.ts +60 -117
  1167. package/dist/types/hitl/index.d.ts.map +1 -1
  1168. package/dist/types/hitl/index.js +1 -1
  1169. package/dist/types/hitl/index.js.map +1 -1
  1170. package/dist/types/hitl/policy.d.ts +8 -6
  1171. package/dist/types/hitl/policy.d.ts.map +1 -1
  1172. package/dist/types/ids/brand.d.ts +10 -3
  1173. package/dist/types/ids/brand.d.ts.map +1 -1
  1174. package/dist/types/ids/brand.js.map +1 -1
  1175. package/dist/types/ids/index.d.ts +10 -4
  1176. package/dist/types/ids/index.d.ts.map +1 -1
  1177. package/dist/types/ids/index.js.map +1 -1
  1178. package/dist/types/memory/index.d.ts +35 -0
  1179. package/dist/types/memory/index.d.ts.map +1 -1
  1180. package/dist/types/memory/index.js +17 -0
  1181. package/dist/types/memory/index.js.map +1 -1
  1182. package/dist/types/message/index.d.ts +4 -4
  1183. package/dist/types/plan/index.d.ts +5 -3
  1184. package/dist/types/plan/index.d.ts.map +1 -1
  1185. package/dist/types/plugin/index.d.ts +27 -19
  1186. package/dist/types/plugin/index.d.ts.map +1 -1
  1187. package/dist/types/plugin/index.js +16 -3
  1188. package/dist/types/plugin/index.js.map +1 -1
  1189. package/dist/types/probe/event-kind.d.ts +3 -3
  1190. package/dist/types/probe/event-kind.d.ts.map +1 -1
  1191. package/dist/types/probe/registry.d.ts +3 -2
  1192. package/dist/types/probe/registry.d.ts.map +1 -1
  1193. package/dist/types/project/entity.d.ts +3 -3
  1194. package/dist/types/provider/config.d.ts +3 -3
  1195. package/dist/types/provider/error.d.ts +1 -1
  1196. package/dist/types/provider/errors.d.ts +2 -2
  1197. package/dist/types/provider/errors.js +2 -2
  1198. package/dist/types/provider/errors.js.map +1 -1
  1199. package/dist/types/provider/interface.d.ts +5 -5
  1200. package/dist/types/router/task-router.d.ts +1 -1
  1201. package/dist/types/sandbox/index.d.ts +14 -14
  1202. package/dist/types/sandbox/index.d.ts.map +1 -1
  1203. package/dist/types/sandbox/index.js +4 -4
  1204. package/dist/types/session/answer-review.d.ts +80 -0
  1205. package/dist/types/session/answer-review.d.ts.map +1 -0
  1206. package/dist/types/session/answer-review.js.map +1 -0
  1207. package/dist/types/session/audit.d.ts +153 -0
  1208. package/dist/types/session/audit.d.ts.map +1 -0
  1209. package/dist/types/session/audit.js +35 -0
  1210. package/dist/types/session/audit.js.map +1 -0
  1211. package/dist/types/session/cancel-cause.d.ts +49 -0
  1212. package/dist/types/session/cancel-cause.d.ts.map +1 -0
  1213. package/dist/types/session/cancel-cause.js +39 -0
  1214. package/dist/types/session/cancel-cause.js.map +1 -0
  1215. package/dist/types/session/checkpoint.d.ts +325 -0
  1216. package/dist/types/session/checkpoint.d.ts.map +1 -0
  1217. package/dist/types/session/checkpoint.js +100 -0
  1218. package/dist/types/session/checkpoint.js.map +1 -0
  1219. package/dist/types/session/config.d.ts +199 -0
  1220. package/dist/types/session/config.d.ts.map +1 -0
  1221. package/dist/types/session/config.js.map +1 -0
  1222. package/dist/types/session/derive-status.d.ts +28 -0
  1223. package/dist/types/session/derive-status.d.ts.map +1 -0
  1224. package/dist/types/session/derive-status.js +49 -0
  1225. package/dist/types/session/derive-status.js.map +1 -0
  1226. package/dist/types/session/durable.d.ts +142 -0
  1227. package/dist/types/session/durable.d.ts.map +1 -0
  1228. package/dist/types/session/durable.js +11 -0
  1229. package/dist/types/session/durable.js.map +1 -0
  1230. package/dist/types/session/entity.d.ts +1 -1
  1231. package/dist/types/session/events.d.ts +1139 -0
  1232. package/dist/types/session/events.d.ts.map +1 -0
  1233. package/dist/types/session/events.js +15 -0
  1234. package/dist/types/session/events.js.map +1 -0
  1235. package/dist/types/session/fork.d.ts +45 -0
  1236. package/dist/types/session/fork.d.ts.map +1 -0
  1237. package/dist/types/session/fork.js +15 -0
  1238. package/dist/types/session/fork.js.map +1 -0
  1239. package/dist/types/session/ids.d.ts +1 -1
  1240. package/dist/types/session/ids.d.ts.map +1 -1
  1241. package/dist/types/session/index.d.ts +20 -1
  1242. package/dist/types/session/index.d.ts.map +1 -1
  1243. package/dist/types/session/index.js +22 -4
  1244. package/dist/types/session/index.js.map +1 -1
  1245. package/dist/types/session/lineage.d.ts +15 -0
  1246. package/dist/types/session/lineage.d.ts.map +1 -0
  1247. package/dist/types/session/lineage.js.map +1 -0
  1248. package/dist/types/session/log-cursor.d.ts +57 -0
  1249. package/dist/types/session/log-cursor.d.ts.map +1 -0
  1250. package/dist/types/session/log-cursor.js +34 -0
  1251. package/dist/types/session/log-cursor.js.map +1 -0
  1252. package/dist/types/session/memory-promotion.d.ts +91 -0
  1253. package/dist/types/session/memory-promotion.d.ts.map +1 -0
  1254. package/dist/types/session/memory-promotion.js +39 -0
  1255. package/dist/types/session/memory-promotion.js.map +1 -0
  1256. package/dist/types/session/messages.d.ts +1 -1
  1257. package/dist/types/session/messages.js +1 -1
  1258. package/dist/types/session/prepare-step.d.ts +278 -0
  1259. package/dist/types/session/prepare-step.d.ts.map +1 -0
  1260. package/dist/types/session/prepare-step.js.map +1 -0
  1261. package/dist/types/session/records.d.ts +5597 -0
  1262. package/dist/types/session/records.d.ts.map +1 -0
  1263. package/dist/types/session/records.js +721 -0
  1264. package/dist/types/session/records.js.map +1 -0
  1265. package/dist/types/session/step.d.ts +195 -0
  1266. package/dist/types/session/step.d.ts.map +1 -0
  1267. package/dist/types/session/step.js +26 -0
  1268. package/dist/types/session/step.js.map +1 -0
  1269. package/dist/types/session/stop-reason.d.ts +67 -0
  1270. package/dist/types/session/stop-reason.d.ts.map +1 -0
  1271. package/dist/types/session/stop-reason.js.map +1 -0
  1272. package/dist/types/session/store.d.ts +2 -43
  1273. package/dist/types/session/store.d.ts.map +1 -1
  1274. package/dist/types/session/tool-execution.d.ts +34 -0
  1275. package/dist/types/session/tool-execution.d.ts.map +1 -0
  1276. package/dist/types/session/tool-execution.js +11 -0
  1277. package/dist/types/session/tool-execution.js.map +1 -0
  1278. package/dist/types/session/turn-state.d.ts +74 -0
  1279. package/dist/types/session/turn-state.d.ts.map +1 -0
  1280. package/dist/types/session/turn-state.js +59 -0
  1281. package/dist/types/session/turn-state.js.map +1 -0
  1282. package/dist/types/session/turn.d.ts +215 -0
  1283. package/dist/types/session/turn.d.ts.map +1 -0
  1284. package/dist/types/session/turn.js +44 -0
  1285. package/dist/types/session/turn.js.map +1 -0
  1286. package/dist/types/structured-output/index.d.ts +2 -2
  1287. package/dist/types/structured-output/index.d.ts.map +1 -1
  1288. package/dist/types/summary/deliverable.d.ts +4 -4
  1289. package/dist/types/summary/deliverable.d.ts.map +1 -1
  1290. package/dist/types/task/index.d.ts +8 -4
  1291. package/dist/types/task/index.d.ts.map +1 -1
  1292. package/dist/types/tool/index.d.ts +73 -26
  1293. package/dist/types/tool/index.d.ts.map +1 -1
  1294. package/dist/types/tool/index.js.map +1 -1
  1295. package/dist/types/topic/entity.d.ts +6 -6
  1296. package/dist/types/topic/objective.d.ts +10 -5
  1297. package/dist/types/topic/objective.d.ts.map +1 -1
  1298. package/dist/types/topic/objective.js.map +1 -1
  1299. package/dist/types/topic/state.d.ts +4 -4
  1300. package/dist/types/topic/store.d.ts +1 -1
  1301. package/dist/types/topic/store.js +1 -1
  1302. package/dist/types/workspace/index.d.ts +1 -1
  1303. package/dist/types/workspace/index.d.ts.map +1 -1
  1304. package/dist/types/workspace/index.js +1 -1
  1305. package/dist/types/workspace/index.js.map +1 -1
  1306. package/dist/types/workspace/ref.d.ts +3 -3
  1307. package/dist/types/workspace/shared-session.d.ts +61 -0
  1308. package/dist/types/workspace/shared-session.d.ts.map +1 -0
  1309. package/dist/types/workspace/shared-session.js +2 -0
  1310. package/dist/types/workspace/shared-session.js.map +1 -0
  1311. package/dist/utils/abort.js +4 -4
  1312. package/dist/utils/abort.js.map +1 -1
  1313. package/dist/utils/atomic-write.d.ts +29 -1
  1314. package/dist/utils/atomic-write.d.ts.map +1 -1
  1315. package/dist/utils/atomic-write.js +60 -4
  1316. package/dist/utils/atomic-write.js.map +1 -1
  1317. package/dist/utils/cost.d.ts +3 -3
  1318. package/dist/utils/cost.d.ts.map +1 -1
  1319. package/dist/utils/cost.js +11 -12
  1320. package/dist/utils/cost.js.map +1 -1
  1321. package/dist/utils/env.d.ts +1 -1
  1322. package/dist/utils/env.js +1 -1
  1323. package/dist/utils/id.d.ts +9 -8
  1324. package/dist/utils/id.d.ts.map +1 -1
  1325. package/dist/utils/id.js +20 -13
  1326. package/dist/utils/id.js.map +1 -1
  1327. package/dist/utils/log/create-logger.js +1 -1
  1328. package/dist/utils/log/create-logger.js.map +1 -1
  1329. package/dist/utils/log/types.js +1 -1
  1330. package/dist/utils/log/types.js.map +1 -1
  1331. package/dist/utils/shell-compress.js +2 -2
  1332. package/dist/utils/shell-compress.js.map +1 -1
  1333. package/dist/utils/uuidv7.d.ts +33 -0
  1334. package/dist/utils/uuidv7.d.ts.map +1 -0
  1335. package/dist/utils/uuidv7.js +70 -0
  1336. package/dist/utils/uuidv7.js.map +1 -0
  1337. package/dist/vault/instrumentation.d.ts +5 -2
  1338. package/dist/vault/instrumentation.d.ts.map +1 -1
  1339. package/dist/vault/instrumentation.js +12 -6
  1340. package/dist/vault/instrumentation.js.map +1 -1
  1341. package/package.json +1 -1
  1342. package/src/advisory/budget.ts +3 -3
  1343. package/src/advisory/context.ts +9 -9
  1344. package/src/advisory/evaluator.ts +2 -2
  1345. package/src/advisory/parse.ts +1 -1
  1346. package/src/agents/AbstractAgent.ts +74 -50
  1347. package/src/agents/PipelineAgent.ts +91 -26
  1348. package/src/agents/ReactiveAgent.ts +35 -29
  1349. package/src/agents/RouterAgent.ts +32 -44
  1350. package/src/agents/SupervisorAgent.ts +55 -41
  1351. package/src/agents/budget.ts +73 -16
  1352. package/src/agents/defineAgent.ts +7 -3
  1353. package/src/agents/handle.ts +17 -19
  1354. package/src/agents/lock.ts +4 -4
  1355. package/src/agents/runAgent.ts +96 -38
  1356. package/src/agents/storage.ts +36 -0
  1357. package/src/authorization/command-line.ts +1 -1
  1358. package/src/authorization/gate.ts +1 -1
  1359. package/src/authorization/permission-presets.ts +4 -4
  1360. package/src/bridge/a2a/client.ts +2 -2
  1361. package/src/bridge/a2a/context.ts +46 -0
  1362. package/src/bridge/a2a/index.ts +12 -5
  1363. package/src/bridge/a2a/mapper.ts +48 -38
  1364. package/src/bridge/a2a/task.ts +91 -37
  1365. package/src/bridge/acp/permission.ts +2 -2
  1366. package/src/bridge/acp/server.ts +45 -11
  1367. package/src/bridge/acp/update.ts +9 -9
  1368. package/src/bridge/external-session.ts +82 -0
  1369. package/src/bridge/sse/index.ts +1 -1
  1370. package/src/bridge/sse/mapper.ts +116 -145
  1371. package/src/bus/breaker.ts +30 -29
  1372. package/src/bus/index.ts +7 -7
  1373. package/src/bus/lock.ts +7 -7
  1374. package/src/bus/ownership.ts +8 -8
  1375. package/src/compaction/consolidation.ts +61 -15
  1376. package/src/compaction/context-window.ts +4 -4
  1377. package/src/compaction/index.ts +2 -2
  1378. package/src/compaction/manager.ts +4 -4
  1379. package/src/compaction/manual.ts +5 -5
  1380. package/src/compaction/plan.ts +8 -8
  1381. package/src/compaction/reducer.ts +8 -8
  1382. package/src/compaction/retention.ts +2 -2
  1383. package/src/compaction/salience/bm25.ts +2 -2
  1384. package/src/compaction/salience/goal.ts +3 -3
  1385. package/src/compaction/salience/minhash.ts +1 -1
  1386. package/src/compaction/salience/score.ts +3 -3
  1387. package/src/compaction/salience/tokenize.ts +1 -1
  1388. package/src/compaction/verifier.ts +7 -7
  1389. package/src/compaction/wire.ts +1 -1
  1390. package/src/config/registry.ts +4 -4
  1391. package/src/config/runtime.ts +3 -3
  1392. package/src/connector/http-operation.ts +1 -1
  1393. package/src/connector/mcp/adapter.ts +1 -1
  1394. package/src/connector/mcp/client.ts +1 -1
  1395. package/src/connector/mcp/discovery.ts +2 -2
  1396. package/src/connector/mcp/policy.ts +1 -1
  1397. package/src/connector/mcp/prompt-adapter.ts +3 -3
  1398. package/src/constants/a2a/index.ts +10 -3
  1399. package/src/constants/continuation.ts +1 -1
  1400. package/src/constants/index.ts +0 -1
  1401. package/src/constants/limits.ts +2 -2
  1402. package/src/constants/telemetry/index.ts +15 -12
  1403. package/src/constants/tools/index.ts +2 -2
  1404. package/src/contracts/api.ts +11 -202
  1405. package/src/contracts/index.ts +8 -15
  1406. package/src/contracts/schemas.ts +6 -39
  1407. package/src/contracts/session/api.ts +150 -0
  1408. package/src/contracts/session/index.ts +29 -0
  1409. package/src/contracts/session/schemas.ts +60 -0
  1410. package/src/contracts/session/turn-status.ts +83 -0
  1411. package/src/contracts/session/turn.ts +67 -0
  1412. package/src/directory/derive-supervisor.ts +2 -2
  1413. package/src/directory/derive.ts +4 -4
  1414. package/src/directory/index.ts +2 -2
  1415. package/src/directory/load.ts +2 -2
  1416. package/src/directory/types.ts +2 -2
  1417. package/src/eval/experiment.ts +23 -23
  1418. package/src/eval/from-turn.ts +50 -0
  1419. package/src/eval/harness-verification.ts +7 -7
  1420. package/src/eval/index.ts +2 -2
  1421. package/src/eval/judge.ts +10 -10
  1422. package/src/eval/scorers.ts +23 -23
  1423. package/src/eval/types.ts +12 -12
  1424. package/src/eval/uncertainty.ts +2 -2
  1425. package/src/execution/code-runtime/types.ts +4 -4
  1426. package/src/execution/code-runtime/worker.ts +1 -1
  1427. package/src/invariants/index.ts +2 -2
  1428. package/src/manager/agent/child-session.ts +120 -0
  1429. package/src/manager/agent/lifecycle.ts +422 -102
  1430. package/src/manager/index.ts +1 -2
  1431. package/src/manager/plan/lifecycle.ts +16 -10
  1432. package/src/manager/resident/consumption.ts +8 -6
  1433. package/src/manager/resident/evidence-recall.ts +14 -14
  1434. package/src/manager/resident/host.ts +2 -2
  1435. package/src/manager/resident/learning-cycle.ts +5 -3
  1436. package/src/manager/resident/learning-observation.ts +9 -4
  1437. package/src/manager/resident/learning-store.ts +46 -16
  1438. package/src/manager/resident/tool-evidence.ts +38 -31
  1439. package/src/manager/session/turn-recorder.ts +1291 -0
  1440. package/src/plugin/lifecycle.ts +20 -13
  1441. package/src/plugin/shell-hook.ts +64 -25
  1442. package/src/pricing/index.ts +5 -5
  1443. package/src/pricing/rates.source.json +5 -5
  1444. package/src/probe/context.ts +5 -3
  1445. package/src/probe/registry.ts +1 -1
  1446. package/src/prompt/coding-agent-doctrine.ts +1 -1
  1447. package/src/prompt/contributions.ts +28 -6
  1448. package/src/prompt/resident-learning.ts +2 -2
  1449. package/src/provider/collect-chat-completion.ts +3 -3
  1450. package/src/provider/conformance.ts +8 -5
  1451. package/src/provider/errors.ts +2 -2
  1452. package/src/provider/fallback.ts +8 -8
  1453. package/src/provider/idle-timeout.ts +4 -4
  1454. package/src/provider/instrumentation.ts +14 -7
  1455. package/src/provider/mock.ts +1 -1
  1456. package/src/provider/retry.ts +7 -7
  1457. package/src/provider/stream-text.ts +1 -1
  1458. package/src/provider/thinking-support.ts +2 -2
  1459. package/src/provider/token-budget.ts +2 -2
  1460. package/src/public-runtime.ts +213 -141
  1461. package/src/public-tools.ts +14 -7
  1462. package/src/public-types.ts +71 -59
  1463. package/src/rag/embedding.ts +1 -1
  1464. package/src/read-model/index.ts +2 -2
  1465. package/src/read-model/registry.ts +11 -11
  1466. package/src/read-model/session-status.ts +87 -0
  1467. package/src/registry/command/kernel-commands.ts +10 -10
  1468. package/src/registry/tool/dialect.ts +1 -1
  1469. package/src/registry/tool/execute.ts +20 -7
  1470. package/src/registry/tool/portable.ts +1 -1
  1471. package/src/registry/tool/presentation.ts +1 -1
  1472. package/src/registry/tool/schema.ts +1 -1
  1473. package/src/registry/tool/screen.ts +3 -3
  1474. package/src/runtime/bidi/index.ts +2 -2
  1475. package/src/runtime/bidi/session.ts +45 -34
  1476. package/src/runtime/jobs/awaited-jobs.ts +13 -13
  1477. package/src/runtime/jobs/registry.ts +11 -11
  1478. package/src/runtime/query/abandon-turn.ts +110 -0
  1479. package/src/runtime/query/approval-policy.ts +13 -13
  1480. package/src/runtime/query/callback-inference.ts +8 -5
  1481. package/src/runtime/query/cancelled-before-start.ts +96 -79
  1482. package/src/runtime/query/checkpoint.ts +519 -420
  1483. package/src/runtime/query/compact-session.ts +92 -0
  1484. package/src/runtime/query/context.ts +80 -136
  1485. package/src/runtime/query/events.ts +159 -126
  1486. package/src/runtime/query/executor/tool-call-admission.ts +6 -5
  1487. package/src/runtime/query/executor.ts +206 -111
  1488. package/src/runtime/query/file-evidence-seed.ts +2 -2
  1489. package/src/runtime/query/finalize-turn.ts +209 -0
  1490. package/src/runtime/query/fork/list.ts +20 -0
  1491. package/src/runtime/query/fork/mutate.ts +82 -0
  1492. package/src/runtime/query/fork/prepare.ts +92 -0
  1493. package/src/runtime/query/guard.ts +22 -22
  1494. package/src/runtime/query/guardrail-presets.ts +12 -12
  1495. package/src/runtime/query/guardrails.ts +11 -11
  1496. package/src/runtime/query/index.ts +1607 -1533
  1497. package/src/runtime/query/iteration/index.ts +304 -253
  1498. package/src/runtime/query/iteration/outstanding-work.ts +65 -65
  1499. package/src/runtime/query/iteration/phases/advisory.ts +16 -16
  1500. package/src/runtime/query/iteration/phases/checkpoint.ts +26 -10
  1501. package/src/runtime/query/iteration/phases/compaction.ts +74 -72
  1502. package/src/runtime/query/iteration/phases/context.ts +57 -60
  1503. package/src/runtime/query/iteration/phases/plan.ts +9 -6
  1504. package/src/runtime/query/iteration/phases/tool-review.ts +141 -27
  1505. package/src/runtime/query/iteration/phases/working-memory.ts +57 -22
  1506. package/src/runtime/query/iteration/step-context.ts +17 -0
  1507. package/src/runtime/query/iteration/step-shaping.ts +21 -24
  1508. package/src/runtime/query/iteration/stream-turn.ts +36 -32
  1509. package/src/runtime/query/plugin-hooks.ts +1 -1
  1510. package/src/runtime/query/prepare-turn.ts +932 -0
  1511. package/src/runtime/query/project-instructions.ts +5 -4
  1512. package/src/runtime/query/prompt-cache.ts +1 -1
  1513. package/src/runtime/query/prompt.ts +5 -5
  1514. package/src/runtime/query/question-park.ts +7 -7
  1515. package/src/runtime/query/release-turn.ts +157 -0
  1516. package/src/runtime/query/repeat-call.ts +7 -7
  1517. package/src/runtime/query/result.ts +123 -131
  1518. package/src/runtime/query/resume-pending.ts +101 -44
  1519. package/src/runtime/query/resume-session.ts +153 -0
  1520. package/src/runtime/query/review-policy.ts +147 -19
  1521. package/src/runtime/query/sandbox-lifecycle.ts +5 -5
  1522. package/src/runtime/query/session-storage.ts +302 -0
  1523. package/src/runtime/query/steering.ts +17 -4
  1524. package/src/runtime/query/token-budget.ts +59 -93
  1525. package/src/runtime/query/tool-call-budget.ts +14 -14
  1526. package/src/runtime/query/tool-executions.ts +77 -0
  1527. package/src/runtime/query/tool-grants.ts +3 -3
  1528. package/src/runtime/query/tool-output-budget.ts +4 -4
  1529. package/src/runtime/query/tool-pause.ts +8 -6
  1530. package/src/runtime/query/tooling.ts +22 -14
  1531. package/src/runtime/query/turn-state.ts +153 -0
  1532. package/src/sandbox/isolation.ts +2 -2
  1533. package/src/sandbox/provider/local.ts +8 -8
  1534. package/src/scheduler/completion-inbox.ts +36 -36
  1535. package/src/scheduler/delegating.ts +27 -13
  1536. package/src/scheduler/local.ts +49 -21
  1537. package/src/session/events/index.ts +10 -14
  1538. package/src/session/handoff/broadcast.ts +7 -7
  1539. package/src/session/handoff/events.ts +1 -1
  1540. package/src/session/handoff/index.ts +1 -1
  1541. package/src/session/handoff/single.ts +21 -21
  1542. package/src/session/handoff/version.ts +11 -7
  1543. package/src/session/home.ts +66 -0
  1544. package/src/session/index.ts +1 -0
  1545. package/src/session/log-hash.ts +115 -0
  1546. package/src/session/messages.ts +39 -0
  1547. package/src/session/paths.ts +449 -0
  1548. package/src/session/retention/archive.ts +13 -5
  1549. package/src/session/status/derive.ts +21 -21
  1550. package/src/session/workspace/git-worktree.ts +31 -2
  1551. package/src/session/workspace/index.ts +5 -8
  1552. package/src/session/workspace/shared-session.ts +354 -0
  1553. package/src/session-query/index.ts +152 -0
  1554. package/src/skills/registry.ts +1 -1
  1555. package/src/store/activity/memory.ts +5 -5
  1556. package/src/store/attachment/index.ts +5 -5
  1557. package/src/store/budget/disk.ts +243 -0
  1558. package/src/store/budget/index.ts +24 -0
  1559. package/src/store/budget/ledger.ts +836 -0
  1560. package/src/store/budget/memory.ts +39 -0
  1561. package/src/store/checkpoint/contract.ts +225 -0
  1562. package/src/store/checkpoint/disk.ts +209 -0
  1563. package/src/store/checkpoint/index.ts +22 -0
  1564. package/src/store/checkpoint/memory.ts +112 -0
  1565. package/src/store/checkpoint/prune.ts +93 -0
  1566. package/src/store/config/index.ts +1 -1
  1567. package/src/store/evidence/disk.ts +185 -81
  1568. package/src/store/evidence/index-page.ts +67 -140
  1569. package/src/store/evidence/source-text.ts +23 -28
  1570. package/src/store/evidence/types.ts +51 -41
  1571. package/src/store/feedback/conformance.ts +37 -35
  1572. package/src/store/feedback/disk.ts +61 -63
  1573. package/src/store/feedback/index.ts +1 -1
  1574. package/src/store/feedback/memory.ts +0 -0
  1575. package/src/store/feedback/types.ts +14 -13
  1576. package/src/store/index.ts +24 -28
  1577. package/src/store/memory/digest.ts +35 -0
  1578. package/src/store/memory/disk.ts +66 -20
  1579. package/src/store/memory/index-file.ts +121 -0
  1580. package/src/store/memory/index.ts +4 -2
  1581. package/src/store/memory/links.ts +37 -0
  1582. package/src/store/memory/markdown-format.ts +276 -0
  1583. package/src/store/memory/markdown.ts +741 -0
  1584. package/src/store/memory/memory.ts +39 -17
  1585. package/src/store/memory/naming.ts +195 -0
  1586. package/src/store/memory/origin.ts +35 -0
  1587. package/src/store/session/disk.ts +27 -200
  1588. package/src/store/session/index.ts +5 -9
  1589. package/src/store/session/memory.ts +1 -78
  1590. package/src/store/session-claim.ts +101 -0
  1591. package/src/store/session-index/fts.ts +215 -0
  1592. package/src/store/session-index/index.ts +253 -0
  1593. package/src/store/session-index/rebuild.ts +869 -0
  1594. package/src/store/session-index/refs.ts +164 -0
  1595. package/src/store/session-index/scan.ts +273 -0
  1596. package/src/store/session-index/sqlite.ts +772 -0
  1597. package/src/store/session-log/chain.ts +314 -0
  1598. package/src/store/session-log/conformance.ts +487 -0
  1599. package/src/store/session-log/core.ts +809 -0
  1600. package/src/store/session-log/disk.ts +217 -0
  1601. package/src/store/session-log/fold.ts +368 -0
  1602. package/src/store/session-log/heal.ts +44 -0
  1603. package/src/store/session-log/held-leases.ts +103 -0
  1604. package/src/store/session-log/index.ts +87 -0
  1605. package/src/store/session-log/lease.ts +354 -0
  1606. package/src/store/session-log/memory.ts +111 -0
  1607. package/src/store/session-log/spill.ts +311 -0
  1608. package/src/store/task/context.ts +33 -0
  1609. package/src/store/task/disk.ts +122 -141
  1610. package/src/store/task/memory.ts +14 -8
  1611. package/src/store/topic/index.ts +2 -2
  1612. package/src/store/topic/objective.ts +12 -3
  1613. package/src/store/topic/state.ts +1 -1
  1614. package/src/streaming/coalesce.ts +8 -7
  1615. package/src/telemetry/attributes.ts +10 -9
  1616. package/src/telemetry/metrics.ts +6 -6
  1617. package/src/telemetry/runtime-accessors.ts +1 -1
  1618. package/src/test-support/ids.ts +5 -6
  1619. package/src/testing.ts +11 -16
  1620. package/src/tools/advisory/index.ts +1 -1
  1621. package/src/tools/builtins/bash.ts +43 -5
  1622. package/src/tools/builtins/content-fingerprint.ts +2 -2
  1623. package/src/tools/builtins/edit-apply.ts +1 -1
  1624. package/src/tools/builtins/edit.ts +3 -0
  1625. package/src/tools/builtins/glob.ts +3 -0
  1626. package/src/tools/builtins/grep.ts +3 -0
  1627. package/src/tools/builtins/job.ts +5 -5
  1628. package/src/tools/builtins/ls.ts +3 -0
  1629. package/src/tools/builtins/lsp.ts +5 -2
  1630. package/src/tools/builtins/read-file.ts +3 -0
  1631. package/src/tools/builtins/run-code.ts +11 -11
  1632. package/src/tools/builtins/skill.ts +3 -3
  1633. package/src/tools/builtins/wait-for-job-bounds.ts +6 -6
  1634. package/src/tools/builtins/wait-for-job.ts +3 -3
  1635. package/src/tools/builtins/web-guidance.ts +2 -2
  1636. package/src/tools/builtins/web.ts +3 -3
  1637. package/src/tools/builtins/write-file.ts +3 -0
  1638. package/src/tools/coordinator/agent.ts +8 -8
  1639. package/src/tools/coordinator/ask-user-question.ts +16 -14
  1640. package/src/tools/coordinator/index.ts +64 -54
  1641. package/src/tools/coordinator/outcome.ts +7 -7
  1642. package/src/tools/coordinator/plan-dependencies.ts +1 -1
  1643. package/src/tools/coordinator/wait-with-idle-bound.ts +6 -6
  1644. package/src/tools/defineTool.ts +9 -1
  1645. package/src/tools/env-scrub.ts +1 -1
  1646. package/src/tools/goal/index.ts +16 -12
  1647. package/src/tools/memory/fields.ts +26 -0
  1648. package/src/tools/memory/read.ts +75 -8
  1649. package/src/tools/memory/resolve.ts +37 -0
  1650. package/src/tools/memory/save.ts +54 -18
  1651. package/src/tools/memory/search.ts +9 -5
  1652. package/src/tools/memory/update.ts +43 -7
  1653. package/src/tools/paths.ts +87 -27
  1654. package/src/tools/posix-path.ts +1 -1
  1655. package/src/tools/resident-history.ts +1 -1
  1656. package/src/tools/resident-tool-evidence.ts +1 -1
  1657. package/src/tools/task/create.ts +7 -3
  1658. package/src/tools/task/index.ts +20 -4
  1659. package/src/tools/task/list.ts +12 -6
  1660. package/src/turn/LimitChecker.ts +99 -0
  1661. package/src/turn/command-gate.ts +294 -0
  1662. package/src/turn/drain.ts +324 -0
  1663. package/src/turn/evidence-query.ts +333 -0
  1664. package/src/turn/evidence-recall.ts +860 -0
  1665. package/src/turn/index.ts +38 -0
  1666. package/src/turn/json-claim-verifier.ts +298 -0
  1667. package/src/turn/memory-promoter.ts +160 -0
  1668. package/src/turn/memory-recall.ts +285 -0
  1669. package/src/turn/reporter.ts +469 -0
  1670. package/src/types/activity/index.ts +2 -2
  1671. package/src/types/advisory/config.ts +7 -7
  1672. package/src/types/agent/base.ts +74 -44
  1673. package/src/types/agent/core.ts +10 -10
  1674. package/src/types/agent/delegate.ts +2 -2
  1675. package/src/types/agent/factory.ts +8 -4
  1676. package/src/types/agent/manager.ts +6 -6
  1677. package/src/types/agent/pipeline.ts +5 -4
  1678. package/src/types/agent/reactive.ts +11 -10
  1679. package/src/types/agent/router.ts +1 -1
  1680. package/src/types/agent/scheduler.ts +28 -11
  1681. package/src/types/agent/supervisor.ts +13 -13
  1682. package/src/types/agent/task.ts +53 -12
  1683. package/src/types/agent/working-memory.ts +6 -4
  1684. package/src/types/bidi/index.ts +31 -12
  1685. package/src/types/bus/index.ts +32 -26
  1686. package/src/types/code-navigation/index.ts +1 -1
  1687. package/src/types/common/index.ts +12 -26
  1688. package/src/types/connector/core.ts +2 -2
  1689. package/src/types/connector/definition.ts +1 -1
  1690. package/src/types/connector/mcp.ts +1 -1
  1691. package/src/types/errors/catalog.ts +4 -4
  1692. package/src/types/errors/index.ts +5 -5
  1693. package/src/types/guardrail/index.ts +12 -10
  1694. package/src/types/hitl/index.ts +81 -125
  1695. package/src/types/hitl/policy.ts +8 -6
  1696. package/src/types/ids/brand.ts +10 -2
  1697. package/src/types/ids/index.ts +10 -4
  1698. package/src/types/memory/index.ts +53 -0
  1699. package/src/types/message/index.ts +4 -4
  1700. package/src/types/plan/index.ts +5 -3
  1701. package/src/types/plugin/index.ts +41 -24
  1702. package/src/types/probe/event-kind.ts +3 -3
  1703. package/src/types/probe/registry.ts +3 -2
  1704. package/src/types/project/entity.ts +3 -3
  1705. package/src/types/provider/config.ts +3 -3
  1706. package/src/types/provider/error.ts +1 -1
  1707. package/src/types/provider/errors.ts +3 -3
  1708. package/src/types/provider/interface.ts +5 -5
  1709. package/src/types/router/task-router.ts +1 -1
  1710. package/src/types/sandbox/index.ts +12 -12
  1711. package/src/types/session/answer-review.ts +85 -0
  1712. package/src/types/session/audit.ts +167 -0
  1713. package/src/types/session/cancel-cause.ts +60 -0
  1714. package/src/types/session/checkpoint.ts +167 -0
  1715. package/src/types/session/config.ts +212 -0
  1716. package/src/types/session/derive-status.ts +61 -0
  1717. package/src/types/session/durable.ts +150 -0
  1718. package/src/types/session/entity.ts +1 -1
  1719. package/src/types/session/events.ts +1187 -0
  1720. package/src/types/session/fork.ts +52 -0
  1721. package/src/types/session/ids.ts +1 -1
  1722. package/src/types/session/index.ts +24 -4
  1723. package/src/types/session/lineage.ts +15 -0
  1724. package/src/types/session/log-cursor.ts +69 -0
  1725. package/src/types/session/memory-promotion.ts +116 -0
  1726. package/src/types/session/messages.ts +1 -1
  1727. package/src/types/session/prepare-step.ts +299 -0
  1728. package/src/types/session/records.ts +931 -0
  1729. package/src/types/session/step.ts +214 -0
  1730. package/src/types/session/stop-reason.ts +83 -0
  1731. package/src/types/session/store.ts +5 -52
  1732. package/src/types/session/tool-execution.ts +32 -0
  1733. package/src/types/session/turn-state.ts +136 -0
  1734. package/src/types/session/turn.ts +289 -0
  1735. package/src/types/structured-output/index.ts +4 -4
  1736. package/src/types/summary/deliverable.ts +4 -4
  1737. package/src/types/task/index.ts +8 -4
  1738. package/src/types/tool/index.ts +74 -27
  1739. package/src/types/topic/entity.ts +6 -6
  1740. package/src/types/topic/objective.ts +7 -5
  1741. package/src/types/topic/state.ts +4 -4
  1742. package/src/types/topic/store.ts +1 -1
  1743. package/src/types/workspace/index.ts +8 -8
  1744. package/src/types/workspace/ref.ts +3 -3
  1745. package/src/types/workspace/shared-session.ts +65 -0
  1746. package/src/utils/abort.ts +4 -4
  1747. package/src/utils/atomic-write.ts +67 -4
  1748. package/src/utils/cost.ts +11 -12
  1749. package/src/utils/env.ts +1 -1
  1750. package/src/utils/id.ts +25 -18
  1751. package/src/utils/log/attributes.ts +2 -2
  1752. package/src/utils/log/create-logger.ts +1 -1
  1753. package/src/utils/log/types.ts +1 -1
  1754. package/src/utils/shell-compress.ts +2 -2
  1755. package/src/utils/uuidv7.ts +107 -0
  1756. package/src/vault/instrumentation.ts +21 -8
  1757. package/dist/constants/emergency.d.ts +0 -4
  1758. package/dist/constants/emergency.d.ts.map +0 -1
  1759. package/dist/constants/emergency.js +0 -4
  1760. package/dist/constants/emergency.js.map +0 -1
  1761. package/dist/contracts/run-status.d.ts +0 -17
  1762. package/dist/contracts/run-status.d.ts.map +0 -1
  1763. package/dist/contracts/run-status.js +0 -41
  1764. package/dist/contracts/run-status.js.map +0 -1
  1765. package/dist/eval/from-run.d.ts +0 -30
  1766. package/dist/eval/from-run.d.ts.map +0 -1
  1767. package/dist/eval/from-run.js +0 -46
  1768. package/dist/eval/from-run.js.map +0 -1
  1769. package/dist/manager/run/emergency.d.ts +0 -19
  1770. package/dist/manager/run/emergency.d.ts.map +0 -1
  1771. package/dist/manager/run/emergency.js +0 -122
  1772. package/dist/manager/run/emergency.js.map +0 -1
  1773. package/dist/manager/run/persistence.d.ts +0 -312
  1774. package/dist/manager/run/persistence.d.ts.map +0 -1
  1775. package/dist/manager/run/persistence.js +0 -656
  1776. package/dist/manager/run/persistence.js.map +0 -1
  1777. package/dist/read-model/run-status.d.ts +0 -43
  1778. package/dist/read-model/run-status.d.ts.map +0 -1
  1779. package/dist/read-model/run-status.js +0 -89
  1780. package/dist/read-model/run-status.js.map +0 -1
  1781. package/dist/run/LimitChecker.d.ts +0 -30
  1782. package/dist/run/LimitChecker.d.ts.map +0 -1
  1783. package/dist/run/LimitChecker.js +0 -57
  1784. package/dist/run/LimitChecker.js.map +0 -1
  1785. package/dist/run/command-gate.d.ts +0 -107
  1786. package/dist/run/command-gate.d.ts.map +0 -1
  1787. package/dist/run/command-gate.js +0 -221
  1788. package/dist/run/command-gate.js.map +0 -1
  1789. package/dist/run/drain.d.ts +0 -204
  1790. package/dist/run/drain.d.ts.map +0 -1
  1791. package/dist/run/drain.js +0 -238
  1792. package/dist/run/drain.js.map +0 -1
  1793. package/dist/run/evidence-query.d.ts +0 -41
  1794. package/dist/run/evidence-query.d.ts.map +0 -1
  1795. package/dist/run/evidence-query.js +0 -270
  1796. package/dist/run/evidence-query.js.map +0 -1
  1797. package/dist/run/evidence-recall.d.ts +0 -99
  1798. package/dist/run/evidence-recall.d.ts.map +0 -1
  1799. package/dist/run/evidence-recall.js +0 -633
  1800. package/dist/run/evidence-recall.js.map +0 -1
  1801. package/dist/run/index.d.ts +0 -19
  1802. package/dist/run/index.d.ts.map +0 -1
  1803. package/dist/run/index.js +0 -11
  1804. package/dist/run/index.js.map +0 -1
  1805. package/dist/run/json-claim-verifier.d.ts +0 -83
  1806. package/dist/run/json-claim-verifier.d.ts.map +0 -1
  1807. package/dist/run/json-claim-verifier.js +0 -200
  1808. package/dist/run/json-claim-verifier.js.map +0 -1
  1809. package/dist/run/memory-promoter.d.ts +0 -38
  1810. package/dist/run/memory-promoter.d.ts.map +0 -1
  1811. package/dist/run/memory-promoter.js +0 -109
  1812. package/dist/run/memory-promoter.js.map +0 -1
  1813. package/dist/run/memory-recall.d.ts +0 -25
  1814. package/dist/run/memory-recall.d.ts.map +0 -1
  1815. package/dist/run/memory-recall.js +0 -228
  1816. package/dist/run/memory-recall.js.map +0 -1
  1817. package/dist/run/preparation-context-error.d.ts.map +0 -1
  1818. package/dist/run/preparation-context-error.js.map +0 -1
  1819. package/dist/run/reporter.d.ts +0 -8
  1820. package/dist/run/reporter.d.ts.map +0 -1
  1821. package/dist/run/reporter.js +0 -420
  1822. package/dist/run/reporter.js.map +0 -1
  1823. package/dist/run/token-budget.d.ts +0 -116
  1824. package/dist/run/token-budget.d.ts.map +0 -1
  1825. package/dist/run/token-budget.js +0 -626
  1826. package/dist/run/token-budget.js.map +0 -1
  1827. package/dist/run/workspace-fingerprint.d.ts.map +0 -1
  1828. package/dist/run/workspace-fingerprint.js.map +0 -1
  1829. package/dist/run-query/index.d.ts +0 -90
  1830. package/dist/run-query/index.d.ts.map +0 -1
  1831. package/dist/run-query/index.js +0 -127
  1832. package/dist/run-query/index.js.map +0 -1
  1833. package/dist/runtime/query/finalize-run.d.ts +0 -55
  1834. package/dist/runtime/query/finalize-run.d.ts.map +0 -1
  1835. package/dist/runtime/query/finalize-run.js +0 -113
  1836. package/dist/runtime/query/finalize-run.js.map +0 -1
  1837. package/dist/runtime/query/prepare-run.d.ts +0 -94
  1838. package/dist/runtime/query/prepare-run.d.ts.map +0 -1
  1839. package/dist/runtime/query/prepare-run.js +0 -589
  1840. package/dist/runtime/query/prepare-run.js.map +0 -1
  1841. package/dist/runtime/query/release-run.d.ts +0 -56
  1842. package/dist/runtime/query/release-run.d.ts.map +0 -1
  1843. package/dist/runtime/query/release-run.js +0 -101
  1844. package/dist/runtime/query/release-run.js.map +0 -1
  1845. package/dist/runtime/query/replay/list.d.ts +0 -40
  1846. package/dist/runtime/query/replay/list.d.ts.map +0 -1
  1847. package/dist/runtime/query/replay/list.js +0 -38
  1848. package/dist/runtime/query/replay/list.js.map +0 -1
  1849. package/dist/runtime/query/replay/mutate.d.ts +0 -17
  1850. package/dist/runtime/query/replay/mutate.d.ts.map +0 -1
  1851. package/dist/runtime/query/replay/mutate.js +0 -69
  1852. package/dist/runtime/query/replay/mutate.js.map +0 -1
  1853. package/dist/runtime/query/replay/prepare.d.ts +0 -66
  1854. package/dist/runtime/query/replay/prepare.d.ts.map +0 -1
  1855. package/dist/runtime/query/replay/prepare.js +0 -81
  1856. package/dist/runtime/query/replay/prepare.js.map +0 -1
  1857. package/dist/runtime/query/resume-run.d.ts +0 -103
  1858. package/dist/runtime/query/resume-run.d.ts.map +0 -1
  1859. package/dist/runtime/query/resume-run.js +0 -105
  1860. package/dist/runtime/query/resume-run.js.map +0 -1
  1861. package/dist/runtime/query/run-state.d.ts +0 -57
  1862. package/dist/runtime/query/run-state.d.ts.map +0 -1
  1863. package/dist/runtime/query/run-state.js +0 -96
  1864. package/dist/runtime/query/run-state.js.map +0 -1
  1865. package/dist/session/workspace/path-builder.d.ts +0 -50
  1866. package/dist/session/workspace/path-builder.d.ts.map +0 -1
  1867. package/dist/session/workspace/path-builder.js +0 -51
  1868. package/dist/session/workspace/path-builder.js.map +0 -1
  1869. package/dist/session/workspace/shared-run.d.ts +0 -112
  1870. package/dist/session/workspace/shared-run.d.ts.map +0 -1
  1871. package/dist/session/workspace/shared-run.js +0 -290
  1872. package/dist/session/workspace/shared-run.js.map +0 -1
  1873. package/dist/store/evidence/compaction-archive.d.ts +0 -109
  1874. package/dist/store/evidence/compaction-archive.d.ts.map +0 -1
  1875. package/dist/store/evidence/compaction-archive.js +0 -125
  1876. package/dist/store/evidence/compaction-archive.js.map +0 -1
  1877. package/dist/store/evidence/linked.d.ts +0 -9
  1878. package/dist/store/evidence/linked.d.ts.map +0 -1
  1879. package/dist/store/evidence/linked.js +0 -314
  1880. package/dist/store/evidence/linked.js.map +0 -1
  1881. package/dist/store/evidence/record-chain.d.ts +0 -42
  1882. package/dist/store/evidence/record-chain.d.ts.map +0 -1
  1883. package/dist/store/evidence/record-chain.js +0 -111
  1884. package/dist/store/evidence/record-chain.js.map +0 -1
  1885. package/dist/store/run/checkpoint-disk.d.ts +0 -98
  1886. package/dist/store/run/checkpoint-disk.d.ts.map +0 -1
  1887. package/dist/store/run/checkpoint-disk.js +0 -190
  1888. package/dist/store/run/checkpoint-disk.js.map +0 -1
  1889. package/dist/store/run/checkpoint-memory.d.ts +0 -51
  1890. package/dist/store/run/checkpoint-memory.d.ts.map +0 -1
  1891. package/dist/store/run/checkpoint-memory.js +0 -178
  1892. package/dist/store/run/checkpoint-memory.js.map +0 -1
  1893. package/dist/store/run/claim-disk.d.ts +0 -130
  1894. package/dist/store/run/claim-disk.d.ts.map +0 -1
  1895. package/dist/store/run/claim-disk.js +0 -570
  1896. package/dist/store/run/claim-disk.js.map +0 -1
  1897. package/dist/store/run/conformance.d.ts +0 -159
  1898. package/dist/store/run/conformance.d.ts.map +0 -1
  1899. package/dist/store/run/conformance.js +0 -466
  1900. package/dist/store/run/conformance.js.map +0 -1
  1901. package/dist/store/run/disk.d.ts +0 -189
  1902. package/dist/store/run/disk.d.ts.map +0 -1
  1903. package/dist/store/run/disk.js +0 -804
  1904. package/dist/store/run/disk.js.map +0 -1
  1905. package/dist/store/run/listing.d.ts +0 -118
  1906. package/dist/store/run/listing.d.ts.map +0 -1
  1907. package/dist/store/run/listing.js +0 -333
  1908. package/dist/store/run/listing.js.map +0 -1
  1909. package/dist/store/run/memory.d.ts +0 -55
  1910. package/dist/store/run/memory.d.ts.map +0 -1
  1911. package/dist/store/run/memory.js +0 -176
  1912. package/dist/store/run/memory.js.map +0 -1
  1913. package/dist/store/run/token-budget-disk.d.ts +0 -37
  1914. package/dist/store/run/token-budget-disk.d.ts.map +0 -1
  1915. package/dist/store/run/token-budget-disk.js +0 -211
  1916. package/dist/store/run/token-budget-disk.js.map +0 -1
  1917. package/dist/store/run/tool-executions.d.ts +0 -13
  1918. package/dist/store/run/tool-executions.d.ts.map +0 -1
  1919. package/dist/store/run/tool-executions.js +0 -99
  1920. package/dist/store/run/tool-executions.js.map +0 -1
  1921. package/dist/store/session/sqlite.d.ts +0 -57
  1922. package/dist/store/session/sqlite.d.ts.map +0 -1
  1923. package/dist/store/session/sqlite.js +0 -430
  1924. package/dist/store/session/sqlite.js.map +0 -1
  1925. package/dist/types/run/answer-review.d.ts +0 -79
  1926. package/dist/types/run/answer-review.d.ts.map +0 -1
  1927. package/dist/types/run/answer-review.js.map +0 -1
  1928. package/dist/types/run/audit.d.ts +0 -150
  1929. package/dist/types/run/audit.d.ts.map +0 -1
  1930. package/dist/types/run/audit.js +0 -39
  1931. package/dist/types/run/audit.js.map +0 -1
  1932. package/dist/types/run/cancel-cause.d.ts +0 -49
  1933. package/dist/types/run/cancel-cause.d.ts.map +0 -1
  1934. package/dist/types/run/cancel-cause.js +0 -39
  1935. package/dist/types/run/cancel-cause.js.map +0 -1
  1936. package/dist/types/run/checkpoint-store.d.ts +0 -511
  1937. package/dist/types/run/checkpoint-store.d.ts.map +0 -1
  1938. package/dist/types/run/checkpoint-store.js +0 -12
  1939. package/dist/types/run/checkpoint-store.js.map +0 -1
  1940. package/dist/types/run/config.d.ts +0 -207
  1941. package/dist/types/run/config.d.ts.map +0 -1
  1942. package/dist/types/run/config.js.map +0 -1
  1943. package/dist/types/run/derive-status.d.ts +0 -29
  1944. package/dist/types/run/derive-status.d.ts.map +0 -1
  1945. package/dist/types/run/derive-status.js +0 -49
  1946. package/dist/types/run/derive-status.js.map +0 -1
  1947. package/dist/types/run/emergency.d.ts +0 -32
  1948. package/dist/types/run/emergency.d.ts.map +0 -1
  1949. package/dist/types/run/emergency.js +0 -6
  1950. package/dist/types/run/emergency.js.map +0 -1
  1951. package/dist/types/run/entity.d.ts +0 -151
  1952. package/dist/types/run/entity.d.ts.map +0 -1
  1953. package/dist/types/run/entity.js +0 -2
  1954. package/dist/types/run/entity.js.map +0 -1
  1955. package/dist/types/run/event-cursor.d.ts +0 -90
  1956. package/dist/types/run/event-cursor.d.ts.map +0 -1
  1957. package/dist/types/run/event-cursor.js +0 -47
  1958. package/dist/types/run/event-cursor.js.map +0 -1
  1959. package/dist/types/run/events.d.ts +0 -1064
  1960. package/dist/types/run/events.d.ts.map +0 -1
  1961. package/dist/types/run/events.js +0 -31
  1962. package/dist/types/run/events.js.map +0 -1
  1963. package/dist/types/run/index.d.ts +0 -24
  1964. package/dist/types/run/index.d.ts.map +0 -1
  1965. package/dist/types/run/index.js +0 -23
  1966. package/dist/types/run/index.js.map +0 -1
  1967. package/dist/types/run/lineage.d.ts +0 -15
  1968. package/dist/types/run/lineage.d.ts.map +0 -1
  1969. package/dist/types/run/lineage.js.map +0 -1
  1970. package/dist/types/run/memory-promotion.d.ts +0 -90
  1971. package/dist/types/run/memory-promotion.d.ts.map +0 -1
  1972. package/dist/types/run/memory-promotion.js +0 -38
  1973. package/dist/types/run/memory-promotion.js.map +0 -1
  1974. package/dist/types/run/metadata.d.ts +0 -47
  1975. package/dist/types/run/metadata.d.ts.map +0 -1
  1976. package/dist/types/run/metadata.js +0 -2
  1977. package/dist/types/run/metadata.js.map +0 -1
  1978. package/dist/types/run/prepare-step.d.ts +0 -271
  1979. package/dist/types/run/prepare-step.d.ts.map +0 -1
  1980. package/dist/types/run/prepare-step.js.map +0 -1
  1981. package/dist/types/run/replay.d.ts +0 -53
  1982. package/dist/types/run/replay.d.ts.map +0 -1
  1983. package/dist/types/run/replay.js +0 -15
  1984. package/dist/types/run/replay.js.map +0 -1
  1985. package/dist/types/run/schema-version.d.ts +0 -19
  1986. package/dist/types/run/schema-version.d.ts.map +0 -1
  1987. package/dist/types/run/schema-version.js +0 -18
  1988. package/dist/types/run/schema-version.js.map +0 -1
  1989. package/dist/types/run/state.d.ts +0 -109
  1990. package/dist/types/run/state.d.ts.map +0 -1
  1991. package/dist/types/run/state.js +0 -109
  1992. package/dist/types/run/state.js.map +0 -1
  1993. package/dist/types/run/status.d.ts +0 -26
  1994. package/dist/types/run/status.d.ts.map +0 -1
  1995. package/dist/types/run/status.js +0 -2
  1996. package/dist/types/run/status.js.map +0 -1
  1997. package/dist/types/run/step.d.ts +0 -198
  1998. package/dist/types/run/step.d.ts.map +0 -1
  1999. package/dist/types/run/step.js +0 -26
  2000. package/dist/types/run/step.js.map +0 -1
  2001. package/dist/types/run/stop-reason.d.ts +0 -67
  2002. package/dist/types/run/stop-reason.d.ts.map +0 -1
  2003. package/dist/types/run/stop-reason.js.map +0 -1
  2004. package/dist/types/run/store.d.ts +0 -300
  2005. package/dist/types/run/store.d.ts.map +0 -1
  2006. package/dist/types/run/store.js +0 -2
  2007. package/dist/types/run/store.js.map +0 -1
  2008. package/dist/types/run/subsession-events.d.ts +0 -64
  2009. package/dist/types/run/subsession-events.d.ts.map +0 -1
  2010. package/dist/types/run/subsession-events.js +0 -2
  2011. package/dist/types/run/subsession-events.js.map +0 -1
  2012. package/dist/types/run/token-budget-store.d.ts +0 -29
  2013. package/dist/types/run/token-budget-store.d.ts.map +0 -1
  2014. package/dist/types/run/token-budget-store.js +0 -25
  2015. package/dist/types/run/token-budget-store.js.map +0 -1
  2016. package/dist/types/workspace/shared-run.d.ts +0 -61
  2017. package/dist/types/workspace/shared-run.d.ts.map +0 -1
  2018. package/dist/types/workspace/shared-run.js +0 -2
  2019. package/dist/types/workspace/shared-run.js.map +0 -1
  2020. package/src/constants/emergency.ts +0 -3
  2021. package/src/contracts/run-status.ts +0 -43
  2022. package/src/eval/from-run.ts +0 -48
  2023. package/src/manager/run/emergency.ts +0 -148
  2024. package/src/manager/run/persistence.ts +0 -746
  2025. package/src/read-model/run-status.ts +0 -127
  2026. package/src/run/LimitChecker.ts +0 -99
  2027. package/src/run/command-gate.ts +0 -294
  2028. package/src/run/drain.ts +0 -403
  2029. package/src/run/evidence-query.ts +0 -333
  2030. package/src/run/evidence-recall.ts +0 -854
  2031. package/src/run/index.ts +0 -42
  2032. package/src/run/json-claim-verifier.ts +0 -298
  2033. package/src/run/memory-promoter.ts +0 -147
  2034. package/src/run/memory-recall.ts +0 -254
  2035. package/src/run/reporter.ts +0 -469
  2036. package/src/run/token-budget.ts +0 -733
  2037. package/src/run-query/index.ts +0 -177
  2038. package/src/runtime/query/finalize-run.ts +0 -192
  2039. package/src/runtime/query/prepare-run.ts +0 -718
  2040. package/src/runtime/query/release-run.ts +0 -168
  2041. package/src/runtime/query/replay/list.ts +0 -66
  2042. package/src/runtime/query/replay/mutate.ts +0 -82
  2043. package/src/runtime/query/replay/prepare.ts +0 -147
  2044. package/src/runtime/query/resume-run.ts +0 -202
  2045. package/src/runtime/query/run-state.ts +0 -138
  2046. package/src/session/workspace/path-builder.ts +0 -72
  2047. package/src/session/workspace/shared-run.ts +0 -354
  2048. package/src/store/evidence/compaction-archive.ts +0 -139
  2049. package/src/store/evidence/linked.ts +0 -365
  2050. package/src/store/evidence/record-chain.ts +0 -108
  2051. package/src/store/run/checkpoint-disk.ts +0 -264
  2052. package/src/store/run/checkpoint-memory.ts +0 -216
  2053. package/src/store/run/claim-disk.ts +0 -638
  2054. package/src/store/run/conformance.ts +0 -728
  2055. package/src/store/run/disk.ts +0 -911
  2056. package/src/store/run/listing.ts +0 -422
  2057. package/src/store/run/memory.ts +0 -204
  2058. package/src/store/run/token-budget-disk.ts +0 -250
  2059. package/src/store/run/tool-executions.ts +0 -112
  2060. package/src/store/session/sqlite.ts +0 -584
  2061. package/src/types/run/answer-review.ts +0 -84
  2062. package/src/types/run/audit.ts +0 -164
  2063. package/src/types/run/cancel-cause.ts +0 -60
  2064. package/src/types/run/checkpoint-store.ts +0 -545
  2065. package/src/types/run/config.ts +0 -221
  2066. package/src/types/run/derive-status.ts +0 -62
  2067. package/src/types/run/emergency.ts +0 -28
  2068. package/src/types/run/entity.ts +0 -161
  2069. package/src/types/run/event-cursor.ts +0 -118
  2070. package/src/types/run/events.ts +0 -1146
  2071. package/src/types/run/index.ts +0 -32
  2072. package/src/types/run/lineage.ts +0 -15
  2073. package/src/types/run/memory-promotion.ts +0 -112
  2074. package/src/types/run/metadata.ts +0 -51
  2075. package/src/types/run/prepare-step.ts +0 -292
  2076. package/src/types/run/replay.ts +0 -61
  2077. package/src/types/run/schema-version.ts +0 -19
  2078. package/src/types/run/state.ts +0 -206
  2079. package/src/types/run/status.ts +0 -33
  2080. package/src/types/run/step.ts +0 -217
  2081. package/src/types/run/stop-reason.ts +0 -83
  2082. package/src/types/run/store.ts +0 -325
  2083. package/src/types/run/subsession-events.ts +0 -71
  2084. package/src/types/run/token-budget-store.ts +0 -54
  2085. package/src/types/workspace/shared-run.ts +0 -65
  2086. /package/dist/{run → turn}/preparation-context-error.d.ts +0 -0
  2087. /package/dist/{run → turn}/preparation-context-error.js +0 -0
  2088. /package/dist/{run → turn}/workspace-fingerprint.d.ts +0 -0
  2089. /package/dist/{run → turn}/workspace-fingerprint.js +0 -0
  2090. /package/dist/types/{run → session}/answer-review.js +0 -0
  2091. /package/dist/types/{run → session}/config.js +0 -0
  2092. /package/dist/types/{run → session}/lineage.js +0 -0
  2093. /package/dist/types/{run → session}/prepare-step.js +0 -0
  2094. /package/dist/types/{run → session}/stop-reason.js +0 -0
  2095. /package/src/{run → turn}/preparation-context-error.ts +0 -0
  2096. /package/src/{run → turn}/workspace-fingerprint.ts +0 -0
@@ -1,4 +1,3 @@
1
- import { join } from 'node:path'
2
1
  import {
3
2
  AdvisorRegistry,
4
3
  AdvisoryContext,
@@ -14,21 +13,23 @@ import type { ContextReducer } from '../../compaction/reducer.js'
14
13
  import { serializeState as serializeWorkingState } from '../../compaction/serializer.js'
15
14
  import { restoreWorkingState, snapshotWorkingState } from '../../compaction/wire.js'
16
15
  import { type CompactionConfig, CompactionConfigSchema } from '../../config/runtime.js'
17
- import { TOOL_OUTPUT_DIR_NAME } from '../../constants/tools/index.js'
18
- import { EmergencySaveManager } from '../../manager/run/emergency.js'
19
- import type { RunPersistence } from '../../manager/run/persistence.js'
16
+ import { childSessionLog } from '../../manager/agent/child-session.js'
17
+ import { type TurnRecorder, recordedTurnStart } from '../../manager/session/turn-recorder.js'
20
18
  import { PromptContributionRegistry } from '../../prompt/contributions.js'
21
19
  import { resolveProviderCapabilities } from '../../provider/capabilities.js'
22
20
  import type { ProviderChainMember } from '../../provider/fallback.js'
23
21
  import { withStreamIdleTimeout } from '../../provider/idle-timeout.js'
24
22
  import type { ProviderRetryConfig } from '../../provider/retry.js'
25
23
  import { withTokenBudget } from '../../provider/token-budget.js'
26
- import type { TokenBudget } from '../../run/token-budget.js'
27
- import type { PathBuilder } from '../../session/workspace/path-builder.js'
24
+ // The session → turn surface QueryParams and query() are frozen against.
25
+ import type { SessionPaths } from '../../session/paths.js'
26
+ import type { SessionTokenBudget, SessionTokenBudgetStore } from '../../store/budget/index.js'
27
+ import type { SessionCheckpointStore } from '../../store/checkpoint/index.js'
28
+ import type { SessionLease, SessionLog } from '../../store/session-log/index.js'
28
29
  import {
29
30
  GENAI,
30
31
  NAMZU,
31
- agentRunSpanName,
32
+ agentTurnSpanName,
32
33
  parentContext,
33
34
  serializeSpan,
34
35
  } from '../../telemetry/attributes.js'
@@ -53,7 +54,7 @@ import {
53
54
  type ResumeHandler,
54
55
  autoApproveHandler,
55
56
  } from '../../types/hitl/index.js'
56
- import type { CheckpointId, RunId, SessionId, TenantId } from '../../types/ids/index.js'
57
+ import type { CheckpointId, MessageId, SessionId, TenantId } from '../../types/ids/index.js'
57
58
  import type { InvocationState } from '../../types/invocation/index.js'
58
59
  import type { MemoryStore } from '../../types/memory/index.js'
59
60
  import {
@@ -64,24 +65,28 @@ import {
64
65
  import type { AgentPersona } from '../../types/persona/index.js'
65
66
  import type { LLMProvider } from '../../types/provider/index.js'
66
67
  import type { TaskRouterConfig } from '../../types/router/index.js'
67
- import type { ReviewAnswer } from '../../types/run/answer-review.js'
68
- import type { CheckpointStore, FencingToken } from '../../types/run/checkpoint-store.js'
69
- import type { RunEventCursor, RunEventReplay } from '../../types/run/event-cursor.js'
68
+ import type { Sandbox, SandboxProvider } from '../../types/sandbox/index.js'
69
+ import type { ReviewAnswer } from '../../types/session/answer-review.js'
70
+ import type { ProjectId, TopicId } from '../../types/session/ids.js'
70
71
  import type {
71
- AgentRunConfig,
72
72
  BeforeStep,
73
73
  PrepareStepChain,
74
- Run,
75
- RunEvent,
76
- RunEventListener,
77
74
  StepResult,
78
75
  StopCondition,
79
- } from '../../types/run/index.js'
80
- import type { PromoteMemory } from '../../types/run/memory-promotion.js'
81
- import type { RunStore } from '../../types/run/store.js'
82
- import type { TokenBudgetStore } from '../../types/run/token-budget-store.js'
83
- import type { Sandbox, SandboxProvider } from '../../types/sandbox/index.js'
84
- import type { ProjectId, TopicId } from '../../types/session/ids.js'
76
+ } from '../../types/session/index.js'
77
+ import {
78
+ type Origin,
79
+ type SessionEvent,
80
+ type SessionEventListener,
81
+ type SessionLogCursor,
82
+ type SessionLogReplay,
83
+ type Turn,
84
+ type TurnConfig,
85
+ type TurnForkOrigin,
86
+ type TurnId,
87
+ isTurnInProgressError,
88
+ } from '../../types/session/index.js'
89
+ import type { PromoteMemory } from '../../types/session/memory-promotion.js'
85
90
  import type { Skill } from '../../types/skills/index.js'
86
91
  import type { StructuredOutputConfig } from '../../types/structured-output/index.js'
87
92
  import type { TaskStore } from '../../types/task/index.js'
@@ -96,7 +101,8 @@ import { AwaitedJobs } from '../jobs/awaited-jobs.js'
96
101
  import type { BackgroundJobRegistry } from '../jobs/registry.js'
97
102
  import { catchUpFromCursor, settlePreStartCancellation } from './cancelled-before-start.js'
98
103
  import { CheckpointManager, findPendingCheckpoint } from './checkpoint.js'
99
- import { finalizeRun } from './finalize-run.js'
104
+ import type { EventTranslator } from './events.js'
105
+ import { finalizeTurn } from './finalize-turn.js'
100
106
  import { GuardCoordinator } from './guard.js'
101
107
  import { runInputGuardrails } from './guardrails.js'
102
108
  import { IterationOrchestrator } from './iteration/index.js'
@@ -105,17 +111,17 @@ import { isWorkingMemoryMessage } from './iteration/phases/working-memory.js'
105
111
  import { applyLifecycleHookResults } from './plugin-hooks.js'
106
112
  import {
107
113
  type SelectedResumeState,
108
- prepareRun,
114
+ prepareTurn,
109
115
  projectStateBearingHistory,
110
116
  resolveProviderContextWindow,
111
117
  selectedResumeStates,
112
- } from './prepare-run.js'
118
+ } from './prepare-turn.js'
113
119
  import type { ProjectInstructionContext } from './project-instructions.js'
114
120
  import type { PromptCache } from './prompt-cache.js'
115
121
  import { PromptBuilder } from './prompt.js'
116
122
  import type { PromptSegments } from './prompt.js'
117
123
  import { PendingAnswers, QuestionParkBinding } from './question-park.js'
118
- import { releaseRunResources } from './release-run.js'
124
+ import { releaseTurnResources } from './release-turn.js'
119
125
  import { RepeatCallTracker } from './repeat-call.js'
120
126
  import { ResultAssembler } from './result.js'
121
127
  import {
@@ -137,10 +143,14 @@ import { ToolingBootstrap } from './tooling.js'
137
143
  export interface QueryParams {
138
144
  /** Share observations across turns of one conversation and filesystem; otherwise run-local. */
139
145
  fileReadTracker?: import('../../types/tool/index.js').FileReadTracker
140
- /** One account shared with the task scheduler and descendant runs. */
141
- budget?: TokenBudget
142
- /** Canonical tree ledger; defaults to disk beside the root run. */
143
- tokenBudgetStore?: TokenBudgetStore
146
+ /** One ledger shared with the task scheduler and descendant child sessions, keyed by (rootSessionId, rootTurnId). */
147
+ budget?: SessionTokenBudget
148
+ /**
149
+ * Where root-turn ledgers are kept (`<root-session-id>/budgets/<root-turn-id>.json`).
150
+ * Absent: beside the session under {@link QueryParams.paths}, or in memory
151
+ * for an in-memory {@link QueryParams.sessionLog}.
152
+ */
153
+ tokenBudgetStore?: SessionTokenBudgetStore
144
154
  /**
145
155
  * Notice when the model issues the identical tool call repeatedly, and
146
156
  * say so on the next `tool_result`. Defaults on.
@@ -152,7 +162,7 @@ export interface QueryParams {
152
162
  repeatCallAdvisory?: boolean
153
163
 
154
164
  /**
155
- * Tool names this run may not use, subtracted from its effective list.
165
+ * Tool names this turn may not use, subtracted from its effective list.
156
166
  * See {@link import('../../types/agent/base.js').BaseAgentConfig.deniedTools}.
157
167
  */
158
168
  deniedTools?: readonly string[]
@@ -164,7 +174,7 @@ export interface QueryParams {
164
174
  provider: LLMProvider
165
175
  /**
166
176
  * Transient-failure policy for model calls. A single 429 or 503 used to
167
- * terminate a run outright — no driver in the estate retries. Defaults
177
+ * terminate a turn outright — no driver in the estate retries. Defaults
168
178
  * to {@link DEFAULT_PROVIDER_RETRY}; pass `false` to opt out (e.g. when
169
179
  * the host already wraps the provider with its own policy).
170
180
  *
@@ -190,38 +200,18 @@ export interface QueryParams {
190
200
  */
191
201
  fallbackProviders?: readonly ProviderChainMember[]
192
202
 
193
- /**
194
- * Install process-level crash handlers that dump this run's state to
195
- * `<runDir>/../emergency/<runId>.json` on SIGINT, SIGTERM or an
196
- * uncaught exception. `replay({ fromCheckpoint: 'emergency' })` reads
197
- * that file.
198
- *
199
- * **Off by default, and it must stay that way.** `attach` registers
200
- * `process.on(...)` handlers that call `process.exit()`. A library
201
- * seizing a host's termination path is an overreach in any embedded
202
- * context (an API server has its own drain sequence), and the manager
203
- * is a singleton whose `attach` detaches whoever held it before — so
204
- * with concurrent runs the last one to start would silently become the
205
- * only one that gets saved.
206
- *
207
- * Turn it on for a process the run owns end-to-end: a CLI, a worker
208
- * that handles one run at a time. The handlers are removed when the
209
- * run settles.
210
- */
211
- emergencySave?: boolean
212
-
213
203
  /**
214
204
  * Durability for questions raised by a tool that closed over its
215
- * binding before the run existed.
205
+ * binding before the turn existed.
216
206
  *
217
207
  * The built-in `ask_user_question` is built with the agent's tool
218
208
  * registry, so only whoever builds the tools can hand it one — that is
219
- * what lets a single tool instance be durable inside a run and inert
209
+ * what lets a single tool instance be durable inside a turn and inert
220
210
  * outside one. Without it, THAT tool's park is only a suspended
221
211
  * `await`: kill the process while somebody is looking at the card and
222
212
  * the answer can never be applied.
223
213
  *
224
- * Not required for `ToolContext.requestPause`. The run builds that
214
+ * Not required for `ToolContext.requestPause`. The turn builds that
225
215
  * seam per call and binds its own recorder when none is passed, so a
226
216
  * pause raised from a host-authored tool is durable on every surface
227
217
  * rather than only on the one agent class that supplies this.
@@ -242,9 +232,9 @@ export interface QueryParams {
242
232
  * The registry a re-entered `ask_user_question` reads its answer from.
243
233
  *
244
234
  * Same shape, same reason and same limit as {@link questionParks}: it
245
- * exists for a tool that closed over the instance before the run did,
246
- * and without it a resumed run re-asks that tool's question. A pause
247
- * from `ToolContext.requestPause` needs none, because the run fills
235
+ * exists for a tool that closed over the instance before the turn did,
236
+ * and without it a resumed turn re-asks that tool's question. A pause
237
+ * from `ToolContext.requestPause` needs none, because the turn fills
248
238
  * its own on the resume path.
249
239
  */
250
240
  pendingAnswers?: PendingAnswers
@@ -252,29 +242,29 @@ export interface QueryParams {
252
242
  /** Default per-tool execution deadline. See {@link ToolDefinition.timeoutMs}. */
253
243
  toolTimeoutMs?: number
254
244
  /**
255
- * Where background jobs this run starts are held, and killed.
245
+ * Where background jobs this turn starts are held, and killed.
256
246
  *
257
- * Host-owned so it can outlive one run — a registry built per run could
258
- * never be the thing that kills a run's jobs when the run is already
259
- * gone. This run's jobs are torn down in the `finally` below; another
260
- * run's are untouched. The registry launches host processes, so a run
247
+ * Host-owned so it can outlive one turn — a registry built per turn could
248
+ * never be the thing that kills a turn's jobs when the turn is already
249
+ * gone. This turn's jobs are torn down in the `finally` below; another
250
+ * run's are untouched. The registry launches host processes, so a turn
261
251
  * that also supplies a {@link sandboxProvider} does not expose it to tools:
262
252
  * background execution is refused rather than silently bypassing the sandbox.
263
253
  */
264
254
  backgroundJobs?: BackgroundJobRegistry
265
255
  /**
266
- * Which owner the run's background jobs belong to. Absent, the run id:
267
- * jobs are stopped when the run ends. A host that wants a job to
256
+ * Which owner the turn's background jobs belong to. Absent, the turn id:
257
+ * jobs are stopped when the turn ends. A host that wants a job to
268
258
  * outlive the turn that started it — a dev server started in one turn
269
259
  * and read in the next — passes its session id here and calls
270
- * `backgroundJobs.killOwner(sessionId)` when the session ends; the run
260
+ * `backgroundJobs.killOwner(sessionId)` when the session ends; the turn
271
261
  * then stops nothing at its end and still tells the model when a job
272
262
  * finishes.
273
263
  */
274
264
  backgroundJobOwner?: string
275
265
 
276
266
  /**
277
- * What else goes in this run's prompt.
267
+ * What else goes in this turn's prompt.
278
268
  *
279
269
  * `static` and `dynamic` contributions reach the system prompt through
280
270
  * `PromptBuilder`; `turn` contributions reach the ephemeral trailing
@@ -287,8 +277,8 @@ export interface QueryParams {
287
277
  * Where the `skill` tool loads from.
288
278
  *
289
279
  * Separate from `skills`, which is the LIST that goes in the prompt
290
- * manifest. A run can have the manifest without the tool — that is what
291
- * every run did before the tool existed — and the two are wired
280
+ * manifest. A turn can have the manifest without the tool — that is what
281
+ * every turn did before the tool existed — and the two are wired
292
282
  * independently on purpose: a host may want the guidance visible without
293
283
  * granting a way to pull bodies in mid-run.
294
284
  */
@@ -297,19 +287,19 @@ export interface QueryParams {
297
287
  /**
298
288
  * Where a message's stored attachments are resolved from.
299
289
  *
300
- * Absent is fine for every run whose attachments are inline, which is
301
- * every run that existed before this. A message carrying a ref with no
290
+ * Absent is fine for every turn whose attachments are inline, which is
291
+ * every turn that existed before this. A message carrying a ref with no
302
292
  * store REFUSES rather than dropping the attachment.
303
293
  */
304
294
  attachmentStore?: import('../../store/attachment/index.js').AttachmentStore
305
295
  /**
306
- * Maximum wall-clock time for resolving the run's stored attachments.
296
+ * Maximum wall-clock time for resolving the turn's stored attachments.
307
297
  * Defaults to one minute; `0` retains the prior unbounded wait.
308
298
  */
309
299
  attachmentResolveTimeoutMs?: number
310
300
 
311
301
  /**
312
- * How this run reaches the web.
302
+ * How this turn reaches the web.
313
303
  *
314
304
  * `fetch` and `search` are independent, and this kernel ships only the
315
305
  * first — see `connector/web` for why choosing a search backend here
@@ -330,12 +320,12 @@ export interface QueryParams {
330
320
 
331
321
  /** Max concurrently-executing concurrency-safe tools in one batch. */
332
322
  maxToolConcurrency?: number
333
- /** Per-run cumulative tool attempt limit, including nested calls and retries. Unset is unlimited. Re-supply on resume; durable reservations are never refunded. */
323
+ /** Per-turn cumulative tool attempt limit, including nested calls and retries. Unset is unlimited. Re-supply on resume; durable reservations are never refunded. */
334
324
  maxToolCalls?: number
335
325
 
336
326
  /**
337
327
  * Model-visible size cap for a single tool result. Over-budget output is
338
- * spilled to the run directory and replaced with a head+tail preview
328
+ * spilled to the turn directory and replaced with a head+tail preview
339
329
  * naming the path, so nothing is lost and tokens are paid only if the
340
330
  * agent decides the rest is worth re-reading. Set `0` to disable.
341
331
  */
@@ -344,9 +334,9 @@ export interface QueryParams {
344
334
  * Screens to run against every tool result, where the registry was not
345
335
  * built with its own.
346
336
  *
347
- * This is the run's half of a boundary whose only other door is the
337
+ * This is the turn's half of a boundary whose only other door is the
348
338
  * registry constructor — and a registry is usually the HOST's, assembled
349
- * before the run exists, so a run-config option is the only way a run
339
+ * before the turn exists, so a turn-config option is the only way a turn
350
340
  * screens a registry it did not build. A registry built WITH
351
341
  * `resultGuardrails` states its own policy and wins, `[]` included.
352
342
  *
@@ -392,7 +382,7 @@ export interface QueryParams {
392
382
  *
393
383
  * Before this the only halt was `GuardCoordinator`, which sees four
394
384
  * numeric budgets and never the messages — so a terminal
395
- * `submit_answer` tool could not end a run, and the model had to be
385
+ * `submit_answer` tool could not end a turn, and the model had to be
396
386
  * prompt-begged to stop with `maxIterations: 200` as the only backstop.
397
387
  *
398
388
  * Helpers: `stepCountIs`, `hasToolCall`, `anyOf`.
@@ -400,30 +390,30 @@ export interface QueryParams {
400
390
  stopWhen?: StopCondition
401
391
 
402
392
  /**
403
- * Judge the answer the run is about to settle with, and hand it back
393
+ * Judge the answer the turn is about to settle with, and hand it back
404
394
  * with feedback when it is not good enough.
405
395
  *
406
396
  * `stopWhen` is only consulted after tools have run, so there was no
407
- * seam at the point the model stops calling them: the run finalized
397
+ * seam at the point the model stops calling them: the turn finalized
408
398
  * with whatever it had. Verify-then-fix — run the build, feed the
409
- * failure back, let it try again — meant starting a new run and
399
+ * failure back, let it try again — meant starting a new turn and
410
400
  * re-supplying the context the first one had already assembled.
411
401
  *
412
402
  * Bounded by {@link maxAnswerReviews}. Never called on the forced-final
413
403
  * turn, which exists to extract a closing summary under pressure.
414
- * Exceptions or malformed verdicts fail the run; cancellation stops waiting.
404
+ * Exceptions or malformed verdicts fail the turn; cancellation stops waiting.
415
405
  */
416
406
  reviewAnswer?: ReviewAnswer
417
407
 
418
408
  /**
419
- * Decide what this run should leave behind when it settles.
409
+ * Decide what this turn should leave behind when it settles.
420
410
  *
421
411
  * See {@link PromoteMemory}. Absent means nothing is offered and the
422
412
  * run behaves exactly as it did.
423
413
  */
424
414
  promoteMemory?: PromoteMemory
425
415
 
426
- /** Corrections allowed before the run stops. Nonnegative safe integer; default 3. Consumed rejections survive checkpoints. */
416
+ /** Corrections allowed before the turn stops. Nonnegative safe integer; default 3. Consumed rejections survive checkpoints. */
427
417
  maxAnswerReviews?: number
428
418
 
429
419
  /** Called with each completed step, as it completes. */
@@ -433,11 +423,11 @@ export interface QueryParams {
433
423
  * Shape each step before the model is called: narrow the tool surface,
434
424
  * swap the model, add one-step guidance, change sampling.
435
425
  *
436
- * `stopWhen` let a run decide TO STOP from what its steps produced;
426
+ * `stopWhen` let a turn decide TO STOP from what its steps produced;
437
427
  * this is the other half — deciding how the next step should look.
438
428
  * Without it, the tool surface and model are fixed at `query()` time,
439
429
  * so a phased agent (research with search tools, write with file tools,
440
- * verify with a cheaper model) had to be three separate runs, each
430
+ * verify with a cheaper model) had to be three separate turns, each
441
431
  * starting blind to the last one's context.
442
432
  *
443
433
  * Narrowing `activeTools` costs a prompt-cache prefix, since tools
@@ -446,7 +436,7 @@ export interface QueryParams {
446
436
  * `allowed_tools`, and moving `tool_choice` invalidates cached MESSAGE
447
437
  * blocks too, which is a strictly worse trade for the same effect.
448
438
  *
449
- * Fails open — a throw leaves the step with the run's configuration.
439
+ * Fails open — a throw leaves the step with the turn's configuration.
450
440
  */
451
441
  prepareStep?: PrepareStepChain
452
442
  /**
@@ -463,7 +453,7 @@ export interface QueryParams {
463
453
  structuredOutput?: StructuredOutputConfig
464
454
 
465
455
  /**
466
- * Checks run BEFORE the first model call. A block settles the run as
456
+ * Checks run BEFORE the first model call. A block settles the turn as
467
457
  * `input_guardrail` having spent nothing.
468
458
  *
469
459
  * namzu's three tool gates all point one way — they protect the world
@@ -472,7 +462,7 @@ export interface QueryParams {
472
462
  inputGuardrails?: readonly InputGuardrailSpec[]
473
463
 
474
464
  /**
475
- * Checks run against the FINAL result. A block settles the run as
465
+ * Checks run against the FINAL result. A block settles the turn as
476
466
  * `output_guardrail`; a `rewrite` replaces the text (so a PII policy
477
467
  * can redact rather than discard the whole answer).
478
468
  *
@@ -482,17 +472,46 @@ export interface QueryParams {
482
472
  */
483
473
  outputGuardrails?: readonly OutputGuardrailSpec[]
484
474
  tools: ToolRegistryContract
485
- runConfig: AgentRunConfig
475
+ turnConfig: TurnConfig
486
476
  allowedTools?: string[]
487
477
  agentId: string
488
478
  agentName: string
489
479
  workingDirectory?: string
490
480
  /**
491
481
  * Directories besides the working directory the file tools may reach,
492
- * absolute; a sandboxed run binds each read-write. See
482
+ * absolute; a sandboxed turn binds each read-write. See
493
483
  * `ToolContext.additionalDirectories`.
494
484
  */
495
485
  additionalDirectories?: readonly string[]
486
+ /**
487
+ * What a file tool's path outside `workingDirectory` and
488
+ * `additionalDirectories` becomes, on a turn with no sandbox.
489
+ *
490
+ * `'refuse'` (the default) keeps the boundary a refusal the tool returns.
491
+ * `'review'` makes it a question asked before the call runs: the call is
492
+ * marked (`ToolCallSummary.escalation.outsidePaths`), routed to the
493
+ * turn's review even when its tool only reads and even where an `allow`
494
+ * rule or a remembered grant would have covered it, and — once approved
495
+ * — reaches exactly the named paths for that call alone. A `deny` rule
496
+ * still refuses it. The review's own mode decides it, so a turn whose
497
+ * policy approves everything approves these too, on the audit record.
498
+ *
499
+ * Only tools that declare `pathArgument` are looked at; a sandboxed turn
500
+ * is never, because the path is not mounted there to be reached.
501
+ */
502
+ outsideRootAccess?: 'refuse' | 'review'
503
+ /**
504
+ * Whether a call may ask to run outside the turn's sandbox (the shipped
505
+ * `bash` tool's `dangerously_disable_sandbox`).
506
+ *
507
+ * `'refuse'` (the default) refuses every such request. `'review'` routes
508
+ * it to the turn's review every time; it runs unconfined only when the
509
+ * decision confirms its id (`HITLResumeDecision.confirmedEscalations`),
510
+ * which `createReviewHandler` does only after asking a person, or with
511
+ * `unattendedSandboxEscape: 'allow'`. Every confirmation and refusal is
512
+ * written to the audit trail.
513
+ */
514
+ sandboxEscape?: 'refuse' | 'review'
496
515
  pricing?: ModelPricing
497
516
  enableActivityTracking?: boolean
498
517
  messages: Message[]
@@ -505,7 +524,7 @@ export interface QueryParams {
505
524
  * out-of-band — typically in a different process.
506
525
  *
507
526
  * Recording a park makes the request survive a restart; this is what
508
- * makes the ANSWER survive one. Without it a resumed run repairs the
527
+ * makes the ANSWER survive one. Without it a resumed turn repairs the
509
528
  * unanswered `tool_use` blocks away and lets the model re-decide, so a
510
529
  * human's "yes, delete that row" degrades into "ask the model again and
511
530
  * hope it asks for the same thing".
@@ -525,128 +544,142 @@ export interface QueryParams {
525
544
  * A park is only worth persisting if a human is actually looking at it:
526
545
  * a programmatic handler answers in microseconds, and the iteration
527
546
  * gate runs on every iteration, so recording every park unconditionally
528
- * would take a long run from one full-history checkpoint write per
547
+ * would take a long turn from one full-history checkpoint write per
529
548
  * iteration to three. Set `0` to record every park (tests, or a host
530
549
  * that wants an unconditional audit trail).
531
550
  */
532
551
  parkRecordDelayMs?: number
533
552
 
534
553
  /**
535
- * Span this run should hang off, when it is a delegated one.
554
+ * Span this turn should hang off, when it is a delegated one.
536
555
  *
537
556
  * A spawned sub-agent is part of its parent's work, and a trace that
538
557
  * shows the delegation is the whole reason to trace a supervisor at
539
- * all. Absent for a top-level run, which correctly starts its own root.
558
+ * all. Absent for a top-level turn, which correctly starts its own root.
540
559
  */
541
560
  parentSpan?: import('@opentelemetry/api').Span
542
561
 
543
- /** Session scope for the run. Required — every run is attributed to a Session. */
562
+ /** Session scope for the turn. Required — every turn is attributed to a Session. */
544
563
  sessionId: SessionId
545
564
 
546
565
  /**
547
- * Topic the Session lives under. Required — every run carries the full
548
- * five-layer scope (Tenant → Project → Topic → Session → Run).
566
+ * Topic the Session lives under. Required — every turn carries the full
567
+ * five-layer scope (Tenant → Project → Topic → Session → Turn).
549
568
  * Denormalized from `session.topicId`; callers build this alongside
550
569
  * `sessionId` so the query pipeline never needs a second SessionStore
551
570
  * round-trip to recover it.
552
571
  */
553
572
  topicId: TopicId
554
573
 
555
- /** Long-lived goal scope for the run. Required. */
574
+ /** Long-lived goal scope for the turn. Required. */
556
575
  projectId: ProjectId
557
576
 
558
577
  /** Isolation boundary (Convention #17). Required. */
559
578
  tenantId: TenantId
560
579
 
561
580
  /**
562
- * Optional path layout override. Defaults to a {@link DefaultPathBuilder}
563
- * rooted at `{workingDirectory}/.namzu`. First-call filesystem migration
564
- * runs against this builder's root too, so an injected layout never touches
565
- * the fallback working-directory store as a side effect.
581
+ * Where the session lives on disk (`<NAMZU_HOME>/projects/<slug>/…`).
582
+ * Defaults to `SessionPaths` under `resolveNamzuHome()`. Namzu never writes
583
+ * under the working directory.
566
584
  */
567
- pathBuilder?: PathBuilder
585
+ paths?: SessionPaths
568
586
 
569
587
  /**
570
- * Optional checkpoint persistence override. Absent ⇒ iteration
571
- * checkpoints go to the disk layout under the run's output directory
572
- * (today's behavior). A host injects a scope-keyed
573
- * {@link CheckpointStore} (e.g. Postgres-backed) so mid-turn resume
574
- * survives machines that lose their local disk.
588
+ * Optional checkpoint persistence override. Absent: checkpoint documents go
589
+ * to `<session-id>/checkpoints/`, or stay in memory for an in-memory
590
+ * {@link QueryParams.sessionLog}.
575
591
  */
576
- checkpointStore?: CheckpointStore
592
+ checkpointStore?: SessionCheckpointStore
577
593
 
578
594
  /**
579
- * The fence of the claim this worker holds on the run, from `claimRun`.
580
- *
581
- * Presented on every checkpoint the run writes, so a worker that stalled
582
- * past its lease is refused rather than writing into a run somebody else
583
- * has taken over. Omit it for single-writer deployments, which is what
584
- * every run did before claims existed.
585
- *
586
- * This hop did not exist for a release. The claim, the fence and the
587
- * store-side refusal were all built and tested, and no path between a run
588
- * and its store carried the number — so every checkpoint a RUN wrote went
589
- * out unfenced while the tests, which called the store directly, all
590
- * passed. A capability complete except for the wire between its halves
591
- * reads exactly like a working one.
592
- *
593
- * It fences checkpoints and nothing else. {@link QueryParams.runStore}
594
- * takes no fence, so two workers that both took one run still overwrite
595
- * each other's run record, transcript and report — see the changeset.
595
+ * The lease this worker holds on the session, from `claimSession`. Every
596
+ * record the turn appends carries its fence (`gen`), so a worker that
597
+ * stalled past its lease is refused rather than writing into a session
598
+ * somebody else has taken over. Absent: `query()` claims the lease itself
599
+ * and releases it when the turn settles or parks.
596
600
  */
597
- claimFence?: FencingToken
601
+ lease?: SessionLease
598
602
 
599
603
  /**
600
- * Where this run records its own evidence — the run record, its messages,
601
- * its transcript and its report. Defaults to the disk layout under the
602
- * resolved output directory.
603
- *
604
- * The sibling of {@link QueryParams.checkpointStore}, and it should always
605
- * have been one: checkpoints could be pointed at durable storage and the
606
- * evidence could not.
604
+ * The session log this turn appends to. Defaults to the log at
605
+ * {@link QueryParams.paths}. An `InMemorySessionLog` with no `paths` keeps
606
+ * the whole session in memory: its checkpoints, its ledger and its child
607
+ * sessions.
607
608
  */
608
- runStore?: RunStore
609
+ sessionLog?: SessionLog
609
610
 
610
611
  /**
611
- * Where a reconnecting consumer left off, so this run's stream can start by
612
+ * Where a reconnecting consumer left off, so this turn's stream can start by
612
613
  * handing back what it missed.
613
614
  *
614
615
  * The case this serves is the one that exists without a network hop: the
615
- * process holding the run died, and the consumer watching it is coming back
616
- * to a run that has to be resumed. Pair it with `resumeFromCheckpoint` — or
617
- * reach it through {@link import('./resume-run.js').resumeRun}, which is the
616
+ * process holding the turn died, and the consumer watching it is coming back
617
+ * to a turn that has to be resumed. Pair it with `resumeFromCheckpoint` — or
618
+ * reach it through {@link import('./resume-session.js').resumeSession}, which is the
618
619
  * surface that does both — and the missed durable events are yielded, in
619
- * order, before the resumed run emits anything of its own.
620
+ * order, before the resumed turn emits anything of its own.
620
621
  *
621
- * On a run with no log to catch up on the cursor is answered honestly rather
622
+ * On a turn with no log to catch up on the cursor is answered honestly rather
622
623
  * than ignored: a `sinceSeq` above what exists is `cursor_ahead`, not
623
624
  * silence.
624
625
  *
625
626
  * What comes back is message-granular. Streaming deltas are never persisted
626
- * — see {@link import('../../types/run/store.js').RunStore.appendEvent} —
627
+ * — see {@link import('../../types/session/events.js').isEphemeralEvent} —
627
628
  * so a late subscriber recovers the assistant text, the tool results and the
628
629
  * lifecycle, not the keystroke cadence that produced them.
629
630
  */
630
- eventCursor?: RunEventCursor
631
+ eventCursor?: SessionLogCursor
631
632
 
632
633
  /**
633
634
  * What became of {@link QueryParams.eventCursor}.
634
635
  *
635
636
  * A callback rather than an event on the stream, because the answer is about
636
- * the SUBSCRIPTION and not about the run — and rather than a throw, because
637
- * a stale cursor is a client's problem and must not be able to stop a run
637
+ * the SUBSCRIPTION and not about the turn — and rather than a throw, because
638
+ * a stale cursor is a client's problem and must not be able to stop a turn
638
639
  * from continuing. A host that receives `unavailable` re-derives from the
639
640
  * transcript; one that receives nothing at all would splice a hole into its
640
641
  * state and never know.
641
642
  *
642
- * Called once, before the run's first event, and only when a cursor was
643
+ * Called once, before the turn's first event, and only when a cursor was
643
644
  * supplied.
644
645
  */
645
- onEventReplay?: (replay: RunEventReplay) => void
646
+ onEventReplay?: (replay: SessionLogReplay) => void
646
647
 
647
- runId?: RunId
648
+ /**
649
+ * Continue this turn (with `resumeFromCheckpoint`). Absent: a new turn is
650
+ * begun, and refused with `TurnInProgressError` when the session already
651
+ * has an active one.
652
+ */
653
+ turnId?: TurnId
654
+
655
+ /**
656
+ * Close an `interrupted` active turn — one whose process is gone — with
657
+ * `turn_failed{interrupted}` before this turn begins, instead of refusing
658
+ * with `TurnInProgressError`. A running or paused turn is never closed
659
+ * this way. An interactive host that never resumes an interrupted turn
660
+ * sets it.
661
+ */
662
+ abandonInterrupted?: boolean
663
+
664
+ /**
665
+ * Which protocol opened this turn, and the caller-side ids it used
666
+ * (`turn_started.origin`). A protocol adapter records the client's own
667
+ * turn id here (`externalTurnId`) rather than making it a namzu id.
668
+ */
669
+ origin?: Origin
670
+
671
+ /**
672
+ * Present when this session was forked from another session's checkpoint:
673
+ * written into `session_started.forkedFrom` when the log is started, and
674
+ * carried on the returned turn. See `prepareForkState`.
675
+ */
676
+ forkedFrom?: TurnForkOrigin
677
+
678
+ /** Present on a child session: the session that delegated it. */
679
+ parentSessionId?: SessionId
648
680
 
649
- parentRunId?: RunId
681
+ /** Present on a child session: the parent turn whose tool call spawned it. */
682
+ parentTurnId?: TurnId
650
683
 
651
684
  depth?: number
652
685
 
@@ -665,10 +698,10 @@ export interface QueryParams {
665
698
  taskScheduler?: import('../../types/agent/scheduler.js').TaskScheduler
666
699
 
667
700
  /**
668
- * Text queued for this run since its last turn, drained at the boundary.
701
+ * Text queued for this turn since its last turn, drained at the boundary.
669
702
  *
670
703
  * A callback because the queue belongs to whoever accepts the messages,
671
- * and an array captured here would be whatever was queued before the run
704
+ * and an array captured here would be whatever was queued before the turn
672
705
  * started. See `BaseAgentConfig.inboundMessages` for what it closes.
673
706
  */
674
707
  inboundMessages?: () => import('../../types/message/index.js').Message[]
@@ -681,7 +714,7 @@ export interface QueryParams {
681
714
  waitForInbound?: (signal: AbortSignal) => Promise<void>
682
715
 
683
716
  /**
684
- * Live project policy for this run. Unlike `inboundMessages`, snapshot
717
+ * Live project policy for this turn. Unlike `inboundMessages`, snapshot
685
718
  * replacement is durable state and never implies another model turn.
686
719
  */
687
720
  projectInstructionContext?: ProjectInstructionContext
@@ -689,9 +722,9 @@ export interface QueryParams {
689
722
  /**
690
723
  * Where this conversation's durable state lives.
691
724
  *
692
- * Supplies the permission mode when `runConfig.permissionMode` names
725
+ * Supplies the permission mode when `turnConfig.permissionMode` names
693
726
  * none, and receives the flip when a plan is approved. Absent is the
694
- * ordinary case: a run with no topic state behaves exactly as it did.
727
+ * ordinary case: a turn with no topic state behaves exactly as it did.
695
728
  */
696
729
  topicStateStore?: import('../../store/topic/state.js').TopicStateStore
697
730
 
@@ -716,15 +749,15 @@ export interface QueryParams {
716
749
  approvalPolicyName?: string
717
750
 
718
751
  /**
719
- * Receive this run's approval-policy box, so it can be swapped mid-run.
752
+ * Receive this turn's approval-policy box, so it can be swapped mid-run.
720
753
  *
721
754
  * The box is built HERE rather than passed in, unlike
722
755
  * {@link permissionModeRef}, because changing the policy emits a durable
723
- * event and only the run holds the emitter. A host that constructed its
756
+ * event and only the turn holds the emitter. A host that constructed its
724
757
  * own box would be able to change the policy without recording it, which
725
758
  * is the one thing this must not allow.
726
759
  */
727
- onApprovalPolicy?: (policy: import('../../types/hitl/policy.js').RunApprovalPolicy) => void
760
+ onApprovalPolicy?: (policy: import('../../types/hitl/policy.js').SessionApprovalPolicy) => void
728
761
 
729
762
  /**
730
763
  * Where a worker completion goes when no tool call is waiting for it.
@@ -747,11 +780,11 @@ export interface QueryParams {
747
780
  compactionConfig?: CompactionConfig
748
781
 
749
782
  /**
750
- * Where what the run learned is written when it ends: its decisions,
783
+ * Where what the turn learned is written when it ends: its decisions,
751
784
  * discoveries and failures, as one entry tagged `learning`. Episodic
752
- * memory (the working state) dies with the run; this is the bridge to
753
- * the semantic store a later run searches. Absent means nothing is
754
- * written. A store that fails is logged and never fails the run.
785
+ * memory (the working state) dies with the turn; this is the bridge to
786
+ * the semantic store a later turn searches. Absent means nothing is
787
+ * written. A store that fails is logged and never fails the turn.
755
788
  */
756
789
  consolidateInto?: MemoryStore
757
790
 
@@ -759,13 +792,13 @@ export interface QueryParams {
759
792
  * Optional neutral working-memory seam. When set, the iteration loop
760
793
  * re-renders the provider's string into a single pinned leading system
761
794
  * message every turn (the primacy-edge, compaction-preserved slot).
762
- * Absent ⇒ `refreshWorkingMemory` early-returns and the run path is
795
+ * Absent ⇒ `refreshWorkingMemory` early-returns and the turn path is
763
796
  * byte-identical.
764
797
  */
765
798
  workingMemoryProvider?: WorkingMemoryProvider
766
799
 
767
800
  /**
768
- * Replace context reduction for this run.
801
+ * Replace context reduction for this turn.
769
802
  *
770
803
  * Outranks `compactionConfig.strategy`, and the built-in structured pass
771
804
  * does not also run: two mechanisms editing one history in the same pass
@@ -783,10 +816,10 @@ export interface QueryParams {
783
816
  sandboxProvider?: SandboxProvider
784
817
 
785
818
  /**
786
- * Maximum time the run waits for sandbox teardown, in milliseconds.
819
+ * Maximum time the turn waits for sandbox teardown, in milliseconds.
787
820
  *
788
821
  * Defaults to 30 seconds. A fresh private signal is passed to `destroy()`;
789
- * the run also races the returned promise so an implementation that ignores
822
+ * the turn also races the returned promise so an implementation that ignores
790
823
  * cancellation cannot pin `drainQuery()`. Set `0` to retain an unbounded
791
824
  * teardown wait.
792
825
  */
@@ -803,7 +836,7 @@ export interface QueryParams {
803
836
  * explicitly (tool surfaces stripped from prompt + request;
804
837
  * attachments left unmapped by the driver). The same policy is checked
805
838
  * immediately before every request for image/document blocks produced by a
806
- * tool, because those do not exist at run setup. `true`: throw instead of
839
+ * tool, because those do not exist at turn setup. `true`: throw instead of
807
840
  * degrading.
808
841
  */
809
842
  strictCapabilities?: boolean
@@ -815,7 +848,7 @@ export interface QueryParams {
815
848
  * The plan re-appends the exact assistant with real/denied/recovered results.
816
849
  * Generic history repair must not synthesize a competing result first. Any
817
850
  * partial results for that turn are removed too; the executor reconstructs
818
- * them from the durable run transcript through `recoveredResults`.
851
+ * them from the durable turn transcript through `recoveredResults`.
819
852
  */
820
853
  function withoutOwnedResumeTurn(
821
854
  messages: readonly Message[],
@@ -886,10 +919,10 @@ function withOwnedResumeOutcomes(
886
919
  ]
887
920
  }
888
921
 
889
- export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run> {
890
- const prepared = await prepareRun(params)
922
+ export async function* query(params: QueryParams): AsyncGenerator<SessionEvent, Turn> {
923
+ const prepared = await prepareTurn(params)
891
924
  const {
892
- runConfig,
925
+ turnConfig,
893
926
  budget,
894
927
  log,
895
928
  ctx,
@@ -902,6 +935,7 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
902
935
  executeUserInterruptHooks,
903
936
  pendingHistoryRepairs,
904
937
  initialMessages,
938
+ historyIds,
905
939
  queuedForThisRun,
906
940
  selectedResumeState,
907
941
  attachmentResolutionCancelled,
@@ -912,1465 +946,1505 @@ export async function* query(params: QueryParams): AsyncGenerator<RunEvent, Run>
912
946
  } = prepared
913
947
 
914
948
  if (attachmentResolutionCancelled) {
915
- return yield* settlePreStartCancellation(params, prepared)
949
+ try {
950
+ return yield* settlePreStartCancellation(params, prepared)
951
+ } finally {
952
+ await ctx.recorder.release()
953
+ }
916
954
  }
917
955
 
918
- const unsubscribeTaskStore = params.taskStore
919
- ? eventTranslator.wireTaskStore(params.taskStore, ctx.runId)
920
- : undefined
921
-
922
- if (params.taskStore) {
923
- const taskTools = buildTaskTools(params.taskStore, ctx.runId)
924
- const overrides = params.runtimeToolOverrides
925
- for (const tool of taskTools) {
926
- const override = overrides?.[tool.name]
927
- if (override === 'disabled') continue
928
- params.tools.register(tool, override ?? 'deferred')
956
+ // Everything from here to the turn body can refuse (a capability the
957
+ // provider lacks, a sandbox mode it does not offer); the lease the
958
+ // prelude took is given back on the way out.
959
+ let unsubscribeChildSessions: (() => void) | undefined
960
+ try {
961
+ const unsubscribeTaskStore = params.taskStore
962
+ ? eventTranslator.wireTaskStore(params.taskStore, ctx.sessionId)
963
+ : undefined
964
+ // The children this turn delegates to are recorded in this session's
965
+ // log: `child_session_spawned` when one starts, `child_session_ended`
966
+ // (read from the child's own log) when it goes idle. That is what lets
967
+ // the parent list and replay its children once the process is gone.
968
+ unsubscribeChildSessions = taskScheduler?.onChildSessionEvent?.((event) => {
969
+ // Looked up now, while the manager still holds the child's spawn record.
970
+ const childLog =
971
+ event.type === 'child_session_idled' ? childSessionLog(event.childSessionId) : undefined
972
+ void ctx.recorder.recordChildSessionEvent(event, childLog).catch((err: unknown) => {
973
+ ctx.log.warn('A child session record could not be appended', {
974
+ [NAMZU.TURN_ID]: ctx.turnId,
975
+ 'namzu.child_session.id': event.childSessionId,
976
+ 'exception.message': err instanceof Error ? err.message : String(err),
977
+ })
978
+ })
979
+ })
980
+
981
+ if (params.taskStore) {
982
+ const taskTools = buildTaskTools(params.taskStore, {
983
+ sessionId: ctx.sessionId,
984
+ turnId: ctx.turnId,
985
+ // A resumed turn began when its `turn_started` was recorded, maybe
986
+ // in another process: tasks it closed before the pause are still
987
+ // "closed in this turn".
988
+ turnStartedAt:
989
+ (params.resumeFromCheckpoint
990
+ ? await recordedTurnStart(ctx.recorder.log, ctx.turnId)
991
+ : undefined) ?? ctx.recorder.getTurn().startedAt,
992
+ })
993
+ const overrides = params.runtimeToolOverrides
994
+ for (const tool of taskTools) {
995
+ const override = overrides?.[tool.name]
996
+ if (override === 'disabled') continue
997
+ params.tools.register(tool, override ?? 'deferred')
998
+ }
929
999
  }
930
- }
931
1000
 
932
- if (!params.tools.has(SearchToolsTool.name)) {
933
- const hasDeferred = params.tools
934
- .listNames()
935
- .some((n) => params.tools.getAvailability(n) === 'deferred')
936
- if (hasDeferred) {
937
- params.tools.register(SearchToolsTool)
1001
+ if (!params.tools.has(SearchToolsTool.name)) {
1002
+ const hasDeferred = params.tools
1003
+ .listNames()
1004
+ .some((n) => params.tools.getAvailability(n) === 'deferred')
1005
+ if (hasDeferred) {
1006
+ params.tools.register(SearchToolsTool)
1007
+ }
938
1008
  }
939
- }
940
1009
 
941
- // Registered HERE, before the first turn, not when the model is nearly
942
- // done. Tools render at prefix position 0, so injecting one late would
943
- // invalidate the whole prompt cache for the rest of the run — the same
944
- // reason the forced-final turn keeps its tools array and uses
945
- // `toolChoice: 'none'` instead of dropping it.
946
- if (
947
- params.structuredOutput &&
948
- params.structuredOutput.mode !== 'native' &&
949
- !params.tools.has(STRUCTURED_OUTPUT_TOOL_NAME)
950
- ) {
951
- params.tools.register(createStructuredOutputTool(params.structuredOutput.schema))
952
- }
1010
+ // Registered HERE, before the first turn, not when the model is nearly
1011
+ // done. Tools render at prefix position 0, so injecting one late would
1012
+ // invalidate the whole prompt cache for the rest of the turn — the same
1013
+ // reason the forced-final turn keeps its tools array and uses
1014
+ // `toolChoice: 'none'` instead of dropping it.
1015
+ if (
1016
+ params.structuredOutput &&
1017
+ params.structuredOutput.mode !== 'native' &&
1018
+ !params.tools.has(STRUCTURED_OUTPUT_TOOL_NAME)
1019
+ ) {
1020
+ params.tools.register(createStructuredOutputTool(params.structuredOutput.schema))
1021
+ }
953
1022
 
954
- // ─── Provider capability negotiation (before tooling bootstrap) ────────
955
- // Compare what the request asks for with what the DRIVER declared it
956
- // does. Undeclared capabilities resolve permissively (today's behavior
957
- // for third-party providers); declared gaps degrade loudly instead of
958
- // silently.
959
- const capabilities = resolveProviderCapabilities(params.provider)
960
- const registeredToolCount = params.tools.listNames().length
961
- const stripToolSurfaces = !capabilities.supportsTools && registeredToolCount > 0
962
- // Counted separately because they are separate wire shapes: a driver can
963
- // map images and drop documents, and a vision warning would send the
964
- // reader looking at the wrong half.
965
- const carries = (m: (typeof params.messages)[number], kind: 'image' | 'document') =>
966
- m.role === 'user' && (m.attachments ?? []).some((a) => (a.type ?? 'image') === kind)
967
-
968
- const attachmentMessageCount = capabilities.supportsVision
969
- ? 0
970
- : params.messages.filter((m) => carries(m, 'image')).length
971
- const documentMessageCount = capabilities.supportsDocuments
972
- ? 0
973
- : params.messages.filter((m) => carries(m, 'document')).length
974
-
975
- if (stripToolSurfaces) {
976
- const message = `Provider '${params.provider.id}' declares supportsTools: false but ${registeredToolCount} tool(s) are registered — stripping all tool surfaces from the prompt and request so the model is never told about tools it cannot call. Pass strictCapabilities: true to fail instead, or use a tools-capable provider.`
977
- if (params.strictCapabilities) {
978
- throw new NamzuError({
979
- code: 'capability_unavailable',
980
- message,
981
- details: {
982
- providerId: params.provider.id,
983
- capability: 'tools',
984
- registeredToolCount,
985
- },
1023
+ // ─── Provider capability negotiation (before tooling bootstrap) ────────
1024
+ // Compare what the request asks for with what the DRIVER declared it
1025
+ // does. Undeclared capabilities resolve permissively (today's behavior
1026
+ // for third-party providers); declared gaps degrade loudly instead of
1027
+ // silently.
1028
+ const capabilities = resolveProviderCapabilities(params.provider)
1029
+ const registeredToolCount = params.tools.listNames().length
1030
+ const stripToolSurfaces = !capabilities.supportsTools && registeredToolCount > 0
1031
+ // Counted separately because they are separate wire shapes: a driver can
1032
+ // map images and drop documents, and a vision warning would send the
1033
+ // reader looking at the wrong half.
1034
+ const carries = (m: (typeof params.messages)[number], kind: 'image' | 'document') =>
1035
+ m.role === 'user' && (m.attachments ?? []).some((a) => (a.type ?? 'image') === kind)
1036
+
1037
+ const attachmentMessageCount = capabilities.supportsVision
1038
+ ? 0
1039
+ : params.messages.filter((m) => carries(m, 'image')).length
1040
+ const documentMessageCount = capabilities.supportsDocuments
1041
+ ? 0
1042
+ : params.messages.filter((m) => carries(m, 'document')).length
1043
+
1044
+ if (stripToolSurfaces) {
1045
+ const message = `Provider '${params.provider.id}' declares supportsTools: false but ${registeredToolCount} tool(s) are registered — stripping all tool surfaces from the prompt and request so the model is never told about tools it cannot call. Pass strictCapabilities: true to fail instead, or use a tools-capable provider.`
1046
+ if (params.strictCapabilities) {
1047
+ throw new NamzuError({
1048
+ code: 'capability_unavailable',
1049
+ message,
1050
+ details: {
1051
+ providerId: params.provider.id,
1052
+ capability: 'tools',
1053
+ registeredToolCount,
1054
+ },
1055
+ })
1056
+ }
1057
+ ctx.log.warn('Capability mismatch: the provider declares no tool support', {
1058
+ 'namzu.capability.detail': message,
1059
+ [GENAI.SYSTEM]: params.provider.id,
1060
+ 'namzu.runtime.registered_tool_count': registeredToolCount,
986
1061
  })
987
1062
  }
988
- ctx.log.warn('Capability mismatch: the provider declares no tool support', {
989
- 'namzu.capability.detail': message,
990
- [GENAI.SYSTEM]: params.provider.id,
991
- 'namzu.runtime.registered_tool_count': registeredToolCount,
992
- })
993
- }
994
1063
 
995
- if (attachmentMessageCount > 0) {
996
- const message = `Provider '${params.provider.id}' declares supportsVision: false but ${attachmentMessageCount} user message(s) carry image attachments — the driver will not map them, so the model never sees the images. Pass strictCapabilities: true to fail instead, or use a vision-capable provider.`
997
- if (params.strictCapabilities) {
998
- throw new NamzuError({
999
- code: 'capability_unavailable',
1000
- message,
1001
- details: {
1002
- providerId: params.provider.id,
1003
- capability: 'vision',
1004
- attachmentMessageCount,
1005
- },
1064
+ if (attachmentMessageCount > 0) {
1065
+ const message = `Provider '${params.provider.id}' declares supportsVision: false but ${attachmentMessageCount} user message(s) carry image attachments — the driver will not map them, so the model never sees the images. Pass strictCapabilities: true to fail instead, or use a vision-capable provider.`
1066
+ if (params.strictCapabilities) {
1067
+ throw new NamzuError({
1068
+ code: 'capability_unavailable',
1069
+ message,
1070
+ details: {
1071
+ providerId: params.provider.id,
1072
+ capability: 'vision',
1073
+ attachmentMessageCount,
1074
+ },
1075
+ })
1076
+ }
1077
+ ctx.log.warn('Capability mismatch: the provider declares no vision support', {
1078
+ 'namzu.capability.detail': message,
1079
+ [GENAI.SYSTEM]: params.provider.id,
1080
+ 'namzu.runtime.attachment_message_count': attachmentMessageCount,
1006
1081
  })
1007
1082
  }
1008
- ctx.log.warn('Capability mismatch: the provider declares no vision support', {
1009
- 'namzu.capability.detail': message,
1010
- [GENAI.SYSTEM]: params.provider.id,
1011
- 'namzu.runtime.attachment_message_count': attachmentMessageCount,
1012
- })
1013
- }
1014
1083
 
1015
- if (documentMessageCount > 0) {
1016
- const message = `Provider '${params.provider.id}' declares supportsDocuments: false but ${documentMessageCount} user message(s) carry document attachments — the driver will not map them, so the model never sees the documents. Pass strictCapabilities: true to fail instead, or use a document-capable provider.`
1017
- if (params.strictCapabilities) {
1018
- throw new NamzuError({
1019
- code: 'capability_unavailable',
1020
- message,
1021
- details: {
1022
- providerId: params.provider.id,
1023
- capability: 'documents',
1024
- documentMessageCount,
1025
- },
1084
+ if (documentMessageCount > 0) {
1085
+ const message = `Provider '${params.provider.id}' declares supportsDocuments: false but ${documentMessageCount} user message(s) carry document attachments — the driver will not map them, so the model never sees the documents. Pass strictCapabilities: true to fail instead, or use a document-capable provider.`
1086
+ if (params.strictCapabilities) {
1087
+ throw new NamzuError({
1088
+ code: 'capability_unavailable',
1089
+ message,
1090
+ details: {
1091
+ providerId: params.provider.id,
1092
+ capability: 'documents',
1093
+ documentMessageCount,
1094
+ },
1095
+ })
1096
+ }
1097
+ ctx.log.warn('Capability mismatch: the provider declares no document support', {
1098
+ 'namzu.capability.detail': message,
1099
+ [GENAI.SYSTEM]: params.provider.id,
1100
+ 'namzu.runtime.document_message_count': documentMessageCount,
1026
1101
  })
1027
1102
  }
1028
- ctx.log.warn('Capability mismatch: the provider declares no document support', {
1029
- 'namzu.capability.detail': message,
1030
- [GENAI.SYSTEM]: params.provider.id,
1031
- 'namzu.runtime.document_message_count': documentMessageCount,
1032
- })
1033
- }
1034
-
1035
- // Denied names are subtracted LAST, after the allow-list is resolved
1036
- // against the registry — so a deny reaches a run that named no
1037
- // allow-list at all, which is the ordinary case for a delegated child.
1038
- // Applied to `effectiveAllowedTools`, which `query()` binds to both the
1039
- // request tool list AND the `ToolExecutor`: narrowing only the request
1040
- // shows the model fewer tools and lets it call any of them by name.
1041
- const allowedBeforeDenial = stripToolSurfaces
1042
- ? []
1043
- : withDeferredDiscoveryTool(params.tools, params.allowedTools)
1044
- const denied = new Set(params.deniedTools ?? [])
1045
- const effectiveAllowedTools: string[] | undefined =
1046
- denied.size === 0
1047
- ? allowedBeforeDenial
1048
- : // An absent allow-list means "every registered tool", so a deny
1049
- // with no allow-list has to be resolved against the registry
1050
- // here — otherwise the subtraction would be from an empty list
1051
- // and would deny nothing, which is the shape a delegated child
1052
- // arrives in.
1053
- [...(allowedBeforeDenial ?? params.tools.listNames())].filter((name) => !denied.has(name))
1054
-
1055
- // The two halves of a durable pause, owned by the RUN when the host
1056
- // does not own them.
1057
- //
1058
- // `SupervisorAgent` builds both before the run exists, because the
1059
- // tools it builds close over them, and it passes them in. Nothing else
1060
- // could: neither type is exported from `public-runtime.ts`, so a host
1061
- // on `ReactiveAgent`, `drainQuery` or `resumeRun` had no way to supply
1062
- // either — and `ToolContext.requestPause`, which every tool author is
1063
- // handed, silently wrote no checkpoint and could receive no answer on
1064
- // those surfaces. Which agent class the host happened to pick is not
1065
- // visible at the call site, so the degradation was invisible too.
1066
- //
1067
- // A run-local pair is enough for the general seam because `query()`
1068
- // builds its `createToolPause` itself, below, and can hand it the
1069
- // run's own. Pinned by the "a pause is durable on any surface" cases
1070
- // in `__tests__/tool-pause-resume.test.ts`.
1071
- const questionParks = params.questionParks ?? new QuestionParkBinding()
1072
- const pendingAnswers = params.pendingAnswers ?? new PendingAnswers()
1073
-
1074
- // One gate instance owns both model-issued calls and calls dispatched by
1075
- // another tool. Constructing it only inside the iteration review left the
1076
- // nested registry path outside the operator's policy entirely.
1077
- const gateConfig = params.authorizationGate
1078
- const verificationGate = gateConfig?.enabled
1079
- ? new AuthorizationGate(gateConfig, ctx.log)
1080
- : undefined
1081
-
1082
- // The store is initialized when the async query starts, after tooling is
1083
- // composed. Resolve lazily at execution time: capturing getRunDir() here
1084
- // permanently disabled retention for fresh disk-backed invocations.
1085
- const toolOutputDir = () => {
1086
- const runDir = ctx.runMgr.getRunDir()
1087
- return runDir ? join(runDir, TOOL_OUTPUT_DIR_NAME) : undefined
1088
- }
1089
- // The same invocation-owned capability serves tools and optional preparation.
1090
- // Local cancellation cannot override the run's cancellation or settled state.
1091
- const captureRunEvidence = async (maxReadBytes?: number, signal?: AbortSignal) => {
1092
- const combined = signal
1093
- ? AbortSignal.any([ctx.abortController.signal, signal])
1094
- : ctx.abortController.signal
1095
- combined.throwIfAborted()
1096
- const source = await eventTranslator.captureRunEvidence(maxReadBytes, combined)
1097
- combined.throwIfAborted()
1098
- return source
1099
- }
1100
1103
 
1101
- // Whose jobs this run speaks for: its own by default, the session's when
1102
- // the host said so. Resolved before the tools are built, because the
1103
- // wait-intent recorder below is bound into them.
1104
- const jobOwner = params.backgroundJobOwner ?? ctx.runId
1105
- // What the model reads when a job ends. Built up here, ahead of the
1106
- // subscription that fills it below, because the wait-intent recorder needs
1107
- // to ask whether its text has been read yet.
1108
- const jobNotices = params.backgroundJobs ? new SteeringBinding() : undefined
1109
- // Jobs the model told `wait_for_job` it is waiting on, which is the only
1110
- // thing that can hold this run open for a job. Built only where there is a
1111
- // registry, so a host with no background mode carries no recorder and the
1112
- // bound ref has no `markAwaited` to offer.
1113
- const awaitedJobs = params.backgroundJobs
1114
- ? new AwaitedJobs(params.backgroundJobs, jobOwner, () => jobNotices?.pending ?? false)
1115
- : undefined
1116
- awaitedJobs?.attach()
1117
-
1118
- const toolExecutor = ToolingBootstrap.init(
1119
- {
1120
- tools: params.tools,
1121
- runId: ctx.runId,
1122
- workingDirectory: ctx.cwd,
1123
- ...(params.additionalDirectories?.length
1124
- ? { additionalDirectories: params.additionalDirectories }
1125
- : {}),
1126
- permissionMode: () => ctx.permissionMode.current,
1127
- env: runConfig.env ?? {},
1128
- abortSignal: ctx.abortController.signal,
1129
- allowedTools: effectiveAllowedTools,
1130
- invocationState: params.invocationState,
1131
- pluginManager: params.pluginManager,
1132
- ...(params.backgroundJobs ? { backgroundJobs: params.backgroundJobs } : {}),
1133
- ...(params.backgroundJobOwner ? { backgroundJobOwner: params.backgroundJobOwner } : {}),
1134
- ...(awaitedJobs ? { onJobAwaited: (id: string) => awaitedJobs.expect(id) } : {}),
1135
- // The `skill` tool's registry. Threaded from the run rather than
1136
- // held by the tool, because a tool that reached for a module-level
1137
- // registry would answer about whatever the last run configured.
1138
- ...(params.skillRegistry ? { skills: params.skillRegistry } : {}),
1139
- ...(params.web ? { web: params.web } : {}),
1140
- ...(params.fileReadTracker ? { fileReadTracker: params.fileReadTracker } : {}),
1141
- ...(params.toolTimeoutMs !== undefined ? { toolTimeoutMs: params.toolTimeoutMs } : {}),
1142
- ...(params.toolRetryBackoff !== undefined
1143
- ? { toolRetryBackoff: params.toolRetryBackoff }
1144
- : {}),
1145
- ...(params.maxToolCalls !== undefined
1146
- ? {
1147
- maxToolCalls: params.maxToolCalls,
1148
- readToolCallBudgetEvents: () => eventTranslator.readEvents({ integrity: 'strict' }),
1149
- }
1150
- : {}),
1151
- ...(params.maxToolConcurrency !== undefined
1152
- ? { maxToolConcurrency: params.maxToolConcurrency }
1153
- : {}),
1154
- ...(params.maxToolOutputChars !== undefined
1155
- ? { maxToolOutputChars: params.maxToolOutputChars }
1156
- : {}),
1157
- ...(params.toolResultGuardrails !== undefined
1158
- ? { toolResultGuardrails: params.toolResultGuardrails }
1159
- : {}),
1160
- ...(params.retainedToolPreviewChars !== undefined
1161
- ? { retainedToolPreviewChars: params.retainedToolPreviewChars }
1162
- : {}),
1163
- ...(params.maxToolContentBytes !== undefined
1164
- ? { maxToolContentBytes: params.maxToolContentBytes }
1165
- : {}),
1166
- // Overflow lands beside the run's other artifacts, so it is
1167
- // cleaned up with the run and reachable by the model's own
1168
- // `read`/`grep` without a new affordance.
1169
- toolOutputDir,
1170
- captureRunEvidence,
1171
- ...(params.repairToolCall ? { repairToolCall: params.repairToolCall } : {}),
1172
- ...(verificationGate ? { authorizationGate: verificationGate } : {}),
1173
- recordAudit: (input) => ctx.runMgr.recordAudit(input),
1174
- // The durable pause, reachable from any tool rather than from the
1175
- // four kernel-owned points that used to own it. Built here from
1176
- // the machinery the run already holds; the recorder binds a few
1177
- // lines below, and until it does a pause is in-process only —
1178
- // the same degradation the built-in question tool has.
1179
- toolPause: (toolUseId) =>
1180
- createToolPause({
1181
- runId: ctx.runId,
1182
- toolUseId,
1183
- parkHandler: (request) => approvalPolicy.current.handler(request),
1184
- recorder: questionParks,
1185
- pendingAnswers,
1186
- }),
1187
- },
1188
- ctx.activityStore,
1189
- eventTranslator.emitEvent,
1190
- ctx.log,
1191
- )
1104
+ // Denied names are subtracted LAST, after the allow-list is resolved
1105
+ // against the registry — so a deny reaches a turn that named no
1106
+ // allow-list at all, which is the ordinary case for a delegated child.
1107
+ // Applied to `effectiveAllowedTools`, which `query()` binds to both the
1108
+ // request tool list AND the `ToolExecutor`: narrowing only the request
1109
+ // shows the model fewer tools and lets it call any of them by name.
1110
+ const allowedBeforeDenial = stripToolSurfaces
1111
+ ? []
1112
+ : withDeferredDiscoveryTool(params.tools, params.allowedTools)
1113
+ const denied = new Set(params.deniedTools ?? [])
1114
+ const effectiveAllowedTools: string[] | undefined =
1115
+ denied.size === 0
1116
+ ? allowedBeforeDenial
1117
+ : // An absent allow-list means "every registered tool", so a deny
1118
+ // with no allow-list has to be resolved against the registry
1119
+ // here — otherwise the subtraction would be from an empty list
1120
+ // and would deny nothing, which is the shape a delegated child
1121
+ // arrives in.
1122
+ [...(allowedBeforeDenial ?? params.tools.listNames())].filter((name) => !denied.has(name))
1123
+
1124
+ // The two halves of a durable pause, owned by the TURN when the host
1125
+ // does not own them.
1126
+ //
1127
+ // `SupervisorAgent` builds both before the turn exists, because the
1128
+ // tools it builds close over them, and it passes them in. Nothing else
1129
+ // could: neither type is exported from `public-runtime.ts`, so a host
1130
+ // on `ReactiveAgent`, `drainQuery` or `resumeSession` had no way to supply
1131
+ // either — and `ToolContext.requestPause`, which every tool author is
1132
+ // handed, silently wrote no checkpoint and could receive no answer on
1133
+ // those surfaces. Which agent class the host happened to pick is not
1134
+ // visible at the call site, so the degradation was invisible too.
1135
+ //
1136
+ // A run-local pair is enough for the general seam because `query()`
1137
+ // builds its `createToolPause` itself, below, and can hand it the
1138
+ // run's own. Pinned by the "a pause is durable on any surface" cases
1139
+ // in `__tests__/tool-pause-resume.test.ts`.
1140
+ const questionParks = params.questionParks ?? new QuestionParkBinding()
1141
+ const pendingAnswers = params.pendingAnswers ?? new PendingAnswers()
1142
+
1143
+ // One gate instance owns both model-issued calls and calls dispatched by
1144
+ // another tool. Constructing it only inside the iteration review left the
1145
+ // nested registry path outside the operator's policy entirely.
1146
+ const gateConfig = params.authorizationGate
1147
+ const verificationGate = gateConfig?.enabled
1148
+ ? new AuthorizationGate(gateConfig, ctx.log)
1149
+ : undefined
1150
+
1151
+ // Oversized tool output is spilled beside the session log
1152
+ // (`<session-id>/tool-results/`). An in-memory session has nowhere to
1153
+ // spill it, so the ordinary output budget applies.
1154
+ const toolOutputDir = () => ctx.toolResultsDir
1155
+ // The same invocation-owned capability serves tools and optional preparation.
1156
+ // Local cancellation cannot override the turn's cancellation or settled state.
1157
+ const captureSessionEvidence = async (maxReadBytes?: number, signal?: AbortSignal) => {
1158
+ const combined = signal
1159
+ ? AbortSignal.any([ctx.abortController.signal, signal])
1160
+ : ctx.abortController.signal
1161
+ combined.throwIfAborted()
1162
+ const source = await eventTranslator.captureSessionEvidence(maxReadBytes, combined)
1163
+ combined.throwIfAborted()
1164
+ return source
1165
+ }
1192
1166
 
1193
- // A background job's exit reaches the model as a notice on its next tool
1194
- // result, and the host as an event — without either polling. Subscribed
1195
- // for the owner the run's jobs are bound to, so a session-owned job that
1196
- // ends during this run is reported here too.
1197
- const unsubscribeJobExits = params.backgroundJobs?.onExit((job) => {
1198
- if (job.owner !== jobOwner) return
1199
- const outcome =
1200
- job.status === 'killed'
1201
- ? 'was stopped'
1202
- : `exited with code ${job.exitCode ?? 'unknown'}${job.signal ? ` (${job.signal})` : ''}`
1203
- jobNotices?.steer(
1204
- `Background job ${job.id} (${job.command}) ${outcome}. Read its output with the job tool if you need it.`,
1167
+ // Whose jobs this turn speaks for: its own by default, the session's when
1168
+ // the host said so. Resolved before the tools are built, because the
1169
+ // wait-intent recorder below is bound into them.
1170
+ const jobOwner = params.backgroundJobOwner ?? ctx.turnId
1171
+ // What the model reads when a job ends. Built up here, ahead of the
1172
+ // subscription that fills it below, because the wait-intent recorder needs
1173
+ // to ask whether its text has been read yet.
1174
+ const jobNotices = params.backgroundJobs ? new SteeringBinding() : undefined
1175
+ // Jobs the model told `wait_for_job` it is waiting on, which is the only
1176
+ // thing that can hold this turn open for a job. Built only where there is a
1177
+ // registry, so a host with no background mode carries no recorder and the
1178
+ // bound ref has no `markAwaited` to offer.
1179
+ const awaitedJobs = params.backgroundJobs
1180
+ ? new AwaitedJobs(params.backgroundJobs, jobOwner, () => jobNotices?.pending ?? false)
1181
+ : undefined
1182
+ awaitedJobs?.attach()
1183
+
1184
+ const toolExecutor = ToolingBootstrap.init(
1185
+ {
1186
+ tools: params.tools,
1187
+ sessionId: ctx.sessionId,
1188
+ turnId: ctx.turnId,
1189
+ workingDirectory: ctx.cwd,
1190
+ ...(params.additionalDirectories?.length
1191
+ ? { additionalDirectories: params.additionalDirectories }
1192
+ : {}),
1193
+ ...(params.outsideRootAccess ? { outsideRootAccess: params.outsideRootAccess } : {}),
1194
+ ...(params.sandboxEscape ? { sandboxEscape: params.sandboxEscape } : {}),
1195
+ permissionMode: () => ctx.permissionMode.current,
1196
+ env: turnConfig.env ?? {},
1197
+ abortSignal: ctx.abortController.signal,
1198
+ allowedTools: effectiveAllowedTools,
1199
+ invocationState: params.invocationState,
1200
+ pluginManager: params.pluginManager,
1201
+ ...(params.backgroundJobs ? { backgroundJobs: params.backgroundJobs } : {}),
1202
+ ...(params.backgroundJobOwner ? { backgroundJobOwner: params.backgroundJobOwner } : {}),
1203
+ ...(awaitedJobs ? { onJobAwaited: (id: string) => awaitedJobs.expect(id) } : {}),
1204
+ // The `skill` tool's registry. Threaded from the turn rather than
1205
+ // held by the tool, because a tool that reached for a module-level
1206
+ // registry would answer about whatever the last turn configured.
1207
+ ...(params.skillRegistry ? { skills: params.skillRegistry } : {}),
1208
+ ...(params.web ? { web: params.web } : {}),
1209
+ ...(params.fileReadTracker ? { fileReadTracker: params.fileReadTracker } : {}),
1210
+ ...(params.toolTimeoutMs !== undefined ? { toolTimeoutMs: params.toolTimeoutMs } : {}),
1211
+ ...(params.toolRetryBackoff !== undefined
1212
+ ? { toolRetryBackoff: params.toolRetryBackoff }
1213
+ : {}),
1214
+ ...(params.maxToolCalls !== undefined
1215
+ ? {
1216
+ maxToolCalls: params.maxToolCalls,
1217
+ readToolCallBudgetRecords: () => eventTranslator.readRecords({ mode: 'strict' }),
1218
+ }
1219
+ : {}),
1220
+ ...(params.maxToolConcurrency !== undefined
1221
+ ? { maxToolConcurrency: params.maxToolConcurrency }
1222
+ : {}),
1223
+ ...(params.maxToolOutputChars !== undefined
1224
+ ? { maxToolOutputChars: params.maxToolOutputChars }
1225
+ : {}),
1226
+ ...(params.toolResultGuardrails !== undefined
1227
+ ? { toolResultGuardrails: params.toolResultGuardrails }
1228
+ : {}),
1229
+ ...(params.retainedToolPreviewChars !== undefined
1230
+ ? { retainedToolPreviewChars: params.retainedToolPreviewChars }
1231
+ : {}),
1232
+ ...(params.maxToolContentBytes !== undefined
1233
+ ? { maxToolContentBytes: params.maxToolContentBytes }
1234
+ : {}),
1235
+ // Overflow lands beside the turn's other artifacts, so it is
1236
+ // cleaned up with the turn and reachable by the model's own
1237
+ // `read`/`grep` without a new affordance.
1238
+ toolOutputDir,
1239
+ captureSessionEvidence,
1240
+ ...(params.repairToolCall ? { repairToolCall: params.repairToolCall } : {}),
1241
+ ...(verificationGate ? { authorizationGate: verificationGate } : {}),
1242
+ recordAudit: (input) => ctx.recorder.recordAudit(input),
1243
+ // The durable pause, reachable from any tool rather than from the
1244
+ // four kernel-owned points that used to own it. Built here from
1245
+ // the machinery the turn already holds; the recorder binds a few
1246
+ // lines below, and until it does a pause is in-process only —
1247
+ // the same degradation the built-in question tool has.
1248
+ toolPause: (toolUseId) =>
1249
+ createToolPause({
1250
+ sessionId: ctx.sessionId,
1251
+ turnId: ctx.turnId,
1252
+ toolUseId,
1253
+ parkHandler: (request) => approvalPolicy.current.handler(request),
1254
+ recorder: questionParks,
1255
+ pendingAnswers,
1256
+ }),
1257
+ },
1258
+ ctx.activityStore,
1259
+ eventTranslator.emitEvent,
1260
+ ctx.log,
1205
1261
  )
1206
- void eventTranslator
1207
- .emitEvent({
1208
- type: 'background_job_exited',
1209
- runId: ctx.runId,
1210
- jobId: job.id,
1211
- command: job.command,
1212
- status: job.status === 'killed' ? 'killed' : 'exited',
1213
- ...(job.exitCode !== undefined ? { exitCode: job.exitCode } : {}),
1214
- ...(job.signal ? { signal: job.signal } : {}),
1215
- })
1216
- .catch(() => {})
1217
- })
1218
- let workingStateManager: WorkingStateManager | undefined
1219
- // Normalised once, defaults applied. A host that passes a partial
1220
- // object — a strategy and a window, nothing else — used to reach the
1221
- // phase with `triggerThreshold` undefined, and `usage < undefined` is
1222
- // false: the pass ran on every iteration and the salience strategy fell
1223
- // through to the stale-result clearing it exists to replace. The eval
1224
- // suite that passed exactly that object found it.
1225
- const compactionConfig = params.compactionConfig
1226
- ? CompactionConfigSchema.parse(params.compactionConfig)
1227
- : undefined
1228
- if (compactionConfig && compactionConfig.strategy !== 'disabled') {
1229
- workingStateManager = new WorkingStateManager(compactionConfig)
1230
- toolExecutor.setWorkingStateManager(workingStateManager)
1231
- }
1232
1262
 
1233
- // The run's own registry when the host passed none, so a hook's
1234
- // annotation has somewhere to land.
1235
- const promptContributions = params.promptContributions ?? new PromptContributionRegistry()
1236
-
1237
- const promptBuilder = new PromptBuilder({
1238
- systemPrompt: params.systemPrompt,
1239
- persona: params.persona,
1240
- skills: params.skills,
1241
- basePrompt: params.basePrompt,
1242
- tools: params.tools,
1243
- allowedTools: effectiveAllowedTools,
1244
- runtimeContext: params.runtimeContext,
1245
- contributions: promptContributions,
1246
- })
1263
+ // A background job's exit reaches the model as a notice on its next tool
1264
+ // result, and the host as an event — without either polling. Subscribed
1265
+ // for the owner the turn's jobs are bound to, so a session-owned job that
1266
+ // ends during this turn is reported here too.
1267
+ const unsubscribeJobExits = params.backgroundJobs?.onExit((job) => {
1268
+ if (job.owner !== jobOwner) return
1269
+ const outcome =
1270
+ job.status === 'killed'
1271
+ ? 'was stopped'
1272
+ : `exited with code ${job.exitCode ?? 'unknown'}${job.signal ? ` (${job.signal})` : ''}`
1273
+ jobNotices?.steer(
1274
+ `Background job ${job.id} (${job.command}) ${outcome}. Read its output with the job tool if you need it.`,
1275
+ )
1276
+ void eventTranslator
1277
+ .emitEvent({
1278
+ type: 'background_job_exited',
1279
+ turnId: ctx.turnId,
1280
+ jobId: job.id,
1281
+ command: job.command,
1282
+ status: job.status === 'killed' ? 'killed' : 'exited',
1283
+ ...(job.exitCode !== undefined ? { exitCode: job.exitCode } : {}),
1284
+ ...(job.signal ? { signal: job.signal } : {}),
1285
+ })
1286
+ .catch(() => {})
1287
+ })
1288
+ let workingStateManager: WorkingStateManager | undefined
1289
+ // Normalised once, defaults applied. A host that passes a partial
1290
+ // object — a strategy and a window, nothing else — used to reach the
1291
+ // phase with `triggerThreshold` undefined, and `usage < undefined` is
1292
+ // false: the pass ran on every iteration and the salience strategy fell
1293
+ // through to the stale-result clearing it exists to replace. The eval
1294
+ // suite that passed exactly that object found it.
1295
+ const compactionConfig = params.compactionConfig
1296
+ ? CompactionConfigSchema.parse(params.compactionConfig)
1297
+ : undefined
1298
+ if (compactionConfig && compactionConfig.strategy !== 'disabled') {
1299
+ workingStateManager = new WorkingStateManager(compactionConfig)
1300
+ toolExecutor.setWorkingStateManager(workingStateManager)
1301
+ }
1247
1302
 
1248
- const guard = new GuardCoordinator({
1249
- tokenBudget: runConfig.tokenBudget,
1250
- timeoutMs: runConfig.timeoutMs,
1251
- costLimitUsd: runConfig.costLimitUsd,
1252
- maxIterations: runConfig.maxIterations,
1253
- })
1303
+ // The turn's own registry when the host passed none, so a hook's
1304
+ // annotation has somewhere to land.
1305
+ const promptContributions = params.promptContributions ?? new PromptContributionRegistry()
1254
1306
 
1255
- const checkpointMgr = new CheckpointManager(
1256
- ctx.runMgr.getCheckpointStore(),
1257
- ctx.runMgr.getRunScope(),
1258
- )
1307
+ const promptBuilder = new PromptBuilder({
1308
+ systemPrompt: params.systemPrompt,
1309
+ persona: params.persona,
1310
+ skills: params.skills,
1311
+ basePrompt: params.basePrompt,
1312
+ tools: params.tools,
1313
+ allowedTools: effectiveAllowedTools,
1314
+ runtimeContext: params.runtimeContext,
1315
+ contributions: promptContributions,
1316
+ })
1259
1317
 
1260
- // Every checkpoint carries compaction's accumulated state, so a run that
1261
- // comes back in a new process can adopt it (see the restore block).
1262
- // Without it, compaction's own justification for dropping the prior
1263
- // `[COMPACTED CONTEXT]` block — that `serializeState` is cumulative —
1264
- // holds within one process and fails across a resume.
1265
- if (workingStateManager) {
1266
- const manager = workingStateManager
1267
- checkpointMgr.setWorkingStateSource(() => snapshotWorkingState(manager))
1268
- }
1318
+ const guard = new GuardCoordinator({
1319
+ tokenBudget: turnConfig.tokenBudget,
1320
+ timeoutMs: turnConfig.timeoutMs,
1321
+ costLimitUsd: turnConfig.costLimitUsd,
1322
+ maxIterations: turnConfig.maxIterations,
1323
+ })
1269
1324
 
1270
- const resultAssembler = new ResultAssembler({
1271
- runMgr: ctx.runMgr,
1272
- planManager: ctx.planManager,
1273
- activityStore: ctx.activityStore,
1274
- log: ctx.log,
1275
- emitEvent: eventTranslator.emitEvent,
1276
- drainPending: () => eventTranslator.drainPending(),
1277
- // Read at settle time, not now: checkpoints are written per
1278
- // iteration, so the answer changes as the run proceeds.
1279
- resumeCheckpointId: () => checkpointMgr.lastCheckpointId,
1280
- // Read only to recover WHY a cancellation happened. The run loop
1281
- // already knows THAT it was cancelled; the origin lives on the abort
1282
- // reason and nothing else carries it this far.
1283
- signal: ctx.abortController.signal,
1284
- })
1325
+ const checkpointMgr = new CheckpointManager(ctx.recorder, ctx.storage.checkpoints, {
1326
+ tenantId: ctx.tenantId,
1327
+ projectId: ctx.projectId,
1328
+ sessionId: ctx.sessionId,
1329
+ turnId: ctx.turnId,
1330
+ })
1285
1331
 
1286
- let advisoryCtx: AdvisoryContext | undefined
1287
- if (params.advisory && params.advisory.advisors.length > 0) {
1288
- // Advisors are model calls owned by this run even when they use a
1289
- // different provider. Sending the raw definitions into the registry
1290
- // lets a triggered or model-requested consultation bypass both the
1291
- // finite stream-silence bound and Stop. Bind every advisor provider at
1292
- // the query boundary, where the effective timeout and run signal are
1293
- // already known; standalone AdvisoryExecutor callers retain their
1294
- // explicitly chosen provider/cancellation policy.
1295
- const boundedAdvisors = params.advisory.advisors.map((advisor) => ({
1296
- ...advisor,
1297
- provider: withTokenBudget(
1298
- withStreamIdleTimeout(advisor.provider, {
1299
- idleTimeoutMs: streamIdleTimeoutMs,
1300
- log: ctx.log,
1301
- }),
1302
- budget,
1303
- ),
1304
- }))
1305
- const advisorRegistry = new AdvisorRegistry(boundedAdvisors, params.advisory.defaultAdvisorId)
1306
- // A budget the runtime cannot measure is refused here rather than
1307
- // silently ignored for the length of the run.
1308
- assertBudgetEnforceable(params.advisory)
1309
- const advisoryExecutor = new AdvisoryExecutor(
1310
- ctx.log,
1311
- params.advisory.budget,
1312
- ctx.abortController.signal,
1313
- )
1314
- const triggerEvaluator = new TriggerEvaluator(
1315
- params.advisory.triggers ?? [],
1316
- params.advisory.budget,
1317
- )
1318
- advisoryCtx = new AdvisoryContext(
1319
- advisorRegistry,
1320
- advisoryExecutor,
1321
- triggerEvaluator,
1322
- params.advisory.budget,
1323
- )
1332
+ // Every checkpoint carries compaction's accumulated state, so a turn that
1333
+ // comes back in a new process can adopt it (see the restore block).
1334
+ // Without it, compaction's own justification for dropping the prior
1335
+ // `[COMPACTED CONTEXT]` block — that `serializeState` is cumulative —
1336
+ // holds within one process and fails across a resume.
1337
+ if (workingStateManager) {
1338
+ const manager = workingStateManager
1339
+ checkpointMgr.setWorkingStateSource(() => snapshotWorkingState(manager))
1340
+ }
1324
1341
 
1325
- // What the run looks like when the MODEL consults an advisor, as
1326
- // opposed to when a trigger does. The trigger path has always passed
1327
- // this; the tool path passed an empty context, so an advisor the model
1328
- // asked for help saw the question and nothing else.
1329
- //
1330
- // `includeToolCatalog` and `useCompactedContext` are read here and
1331
- // nowhere else. Both were declared on `AdvisoryConfig` /
1332
- // `AdvisorDefinition` and consulted by nothing, so a host who turned
1333
- // the catalogue off still paid for it in every advisory prompt.
1334
- const advisoryConfig = params.advisory
1335
- advisoryCtx.setCallContextProvider(() => {
1336
- const summary =
1337
- workingStateManager && advisoryConfig.advisors.some((a) => a.useCompactedContext)
1338
- ? serializeWorkingState(workingStateManager.getState())
1339
- : undefined
1340
- return {
1341
- messages: ctx.runMgr.messages,
1342
- turn: iterationOrchestrator.getAdvisoryTurnContext(),
1343
- ...(summary !== undefined ? { workingStateSummary: summary } : {}),
1344
- ...(advisoryConfig.includeToolCatalog
1345
- ? { toolCatalog: params.tools.toLLMTools(effectiveAllowedTools) }
1346
- : {}),
1347
- iteration: ctx.runMgr.currentIteration,
1348
- }
1342
+ const resultAssembler = new ResultAssembler({
1343
+ recorder: ctx.recorder,
1344
+ planManager: ctx.planManager,
1345
+ activityStore: ctx.activityStore,
1346
+ log: ctx.log,
1347
+ emitEvent: eventTranslator.emitEvent,
1348
+ drainPending: () => eventTranslator.drainPending(),
1349
+ // Read at settle time, not now: checkpoints are written per
1350
+ // iteration, so the answer changes as the turn proceeds. A turn
1351
+ // that fails before writing one (a 429 on its first request)
1352
+ // commits the state its loop began from, so it pauses like any
1353
+ // later failure rather than failing with nothing to resume.
1354
+ resumeCheckpointId: async () =>
1355
+ checkpointMgr.lastCheckpointId ?? (await checkpointMgr.createAtLoopStart(ctx.recorder))?.id,
1356
+ // Read only to recover WHY a cancellation happened. The turn loop
1357
+ // already knows THAT it was cancelled; the origin lives on the abort
1358
+ // reason and nothing else carries it this far.
1359
+ signal: ctx.abortController.signal,
1349
1360
  })
1350
1361
 
1351
- if (params.advisory.enableAgentTool) {
1352
- const advisoryTools = buildAdvisoryTools({ advisoryCtx })
1353
- const overrides = params.runtimeToolOverrides
1354
- for (const tool of advisoryTools) {
1355
- const override = overrides?.[tool.name]
1356
- if (override === 'disabled') continue
1357
- params.tools.register(tool, override ?? 'active')
1362
+ let advisoryCtx: AdvisoryContext | undefined
1363
+ if (params.advisory && params.advisory.advisors.length > 0) {
1364
+ // Advisors are model calls owned by this turn even when they use a
1365
+ // different provider. Sending the raw definitions into the registry
1366
+ // lets a triggered or model-requested consultation bypass both the
1367
+ // finite stream-silence bound and Stop. Bind every advisor provider at
1368
+ // the query boundary, where the effective timeout and run signal are
1369
+ // already known; standalone AdvisoryExecutor callers retain their
1370
+ // explicitly chosen provider/cancellation policy.
1371
+ const boundedAdvisors = params.advisory.advisors.map((advisor) => ({
1372
+ ...advisor,
1373
+ provider: withTokenBudget(
1374
+ withStreamIdleTimeout(advisor.provider, {
1375
+ idleTimeoutMs: streamIdleTimeoutMs,
1376
+ log: ctx.log,
1377
+ }),
1378
+ budget,
1379
+ ),
1380
+ }))
1381
+ const advisorRegistry = new AdvisorRegistry(boundedAdvisors, params.advisory.defaultAdvisorId)
1382
+ // A budget the runtime cannot measure is refused here rather than
1383
+ // silently ignored for the length of the turn.
1384
+ assertBudgetEnforceable(params.advisory)
1385
+ const advisoryExecutor = new AdvisoryExecutor(
1386
+ ctx.log,
1387
+ params.advisory.budget,
1388
+ ctx.abortController.signal,
1389
+ )
1390
+ const triggerEvaluator = new TriggerEvaluator(
1391
+ params.advisory.triggers ?? [],
1392
+ params.advisory.budget,
1393
+ )
1394
+ advisoryCtx = new AdvisoryContext(
1395
+ advisorRegistry,
1396
+ advisoryExecutor,
1397
+ triggerEvaluator,
1398
+ params.advisory.budget,
1399
+ )
1400
+
1401
+ // What the turn looks like when the MODEL consults an advisor, as
1402
+ // opposed to when a trigger does. The trigger path has always passed
1403
+ // this; the tool path passed an empty context, so an advisor the model
1404
+ // asked for help saw the question and nothing else.
1405
+ //
1406
+ // `includeToolCatalog` and `useCompactedContext` are read here and
1407
+ // nowhere else. Both were declared on `AdvisoryConfig` /
1408
+ // `AdvisorDefinition` and consulted by nothing, so a host who turned
1409
+ // the catalogue off still paid for it in every advisory prompt.
1410
+ const advisoryConfig = params.advisory
1411
+ advisoryCtx.setCallContextProvider(() => {
1412
+ const summary =
1413
+ workingStateManager && advisoryConfig.advisors.some((a) => a.useCompactedContext)
1414
+ ? serializeWorkingState(workingStateManager.getState())
1415
+ : undefined
1416
+ return {
1417
+ messages: ctx.recorder.messages,
1418
+ turn: iterationOrchestrator.getAdvisoryTurnContext(),
1419
+ ...(summary !== undefined ? { workingStateSummary: summary } : {}),
1420
+ ...(advisoryConfig.includeToolCatalog
1421
+ ? { toolCatalog: params.tools.toLLMTools(effectiveAllowedTools) }
1422
+ : {}),
1423
+ iteration: ctx.recorder.currentIteration,
1424
+ }
1425
+ })
1426
+
1427
+ if (params.advisory.enableAgentTool) {
1428
+ const advisoryTools = buildAdvisoryTools({ advisoryCtx })
1429
+ const overrides = params.runtimeToolOverrides
1430
+ for (const tool of advisoryTools) {
1431
+ const override = overrides?.[tool.name]
1432
+ if (override === 'disabled') continue
1433
+ params.tools.register(tool, override ?? 'active')
1434
+ }
1358
1435
  }
1359
1436
  }
1360
- }
1361
1437
 
1362
- const iterationOrchestrator = new IterationOrchestrator({
1363
- captureRunEvidence,
1364
- provider: resilientProvider,
1365
- providerCapabilities: capabilities,
1366
- strictCapabilities: params.strictCapabilities === true,
1367
- servingMember: () => serving.current,
1368
- runConfig,
1369
- ...(params.stopWhen ? { stopWhen: params.stopWhen } : {}),
1370
- ...(params.prepareStep ? { prepareStep: params.prepareStep } : {}),
1371
- ...(params.beforeStep ? { beforeStep: params.beforeStep } : {}),
1372
- ...(params.onStepFinish ? { onStepFinish: params.onStepFinish } : {}),
1373
- ...(params.reviewAnswer ? { reviewAnswer: params.reviewAnswer } : {}),
1374
- ...(params.maxAnswerReviews !== undefined ? { maxAnswerReviews: params.maxAnswerReviews } : {}),
1375
- ...(params.structuredOutput ? { structuredOutput: params.structuredOutput } : {}),
1376
- ...(params.parkRecordDelayMs !== undefined
1377
- ? { parkRecordDelayMs: params.parkRecordDelayMs }
1378
- : {}),
1379
- tools: params.tools,
1380
- allowedTools: effectiveAllowedTools,
1381
- runMgr: ctx.runMgr,
1382
- toolExecutor,
1383
- guard,
1384
- activityStore: ctx.activityStore,
1385
- emitEvent: eventTranslator.emitEvent,
1386
- drainPending: () => eventTranslator.drainPending(),
1387
- abortController: ctx.abortController,
1388
- log: ctx.log,
1389
- // Read through the box on every call, so a swap lands on the next
1390
- // question rather than the next run.
1391
- resumeHandler: (request) => approvalPolicy.current.handler(request),
1392
- takeApprovalPolicyChange: () => approvalPolicy.takeUnannouncedChange(),
1393
- promptContributions,
1394
- ...(params.steering ? { steering: params.steering } : {}),
1395
- ...(jobNotices ? { jobNotices } : {}),
1396
- ...(awaitedJobs ? { awaitedJobs } : {}),
1397
- checkpointMgr,
1398
- planManager: ctx.planManager,
1399
- taskGateway: taskScheduler,
1400
- completionInbox: params.completionInbox,
1401
- taskStore: params.taskStore,
1402
- // Run-scoped. An approval is a statement about this run's work;
1403
- // carrying one into a later run would be reuse nobody agreed to.
1404
- toolGrants: new ToolGrantSet(),
1405
- // Run-scoped for the same reason. A repeat count carried into a later
1406
- // run is a claim about work nobody repeated, and a module-level map
1407
- // would leak exactly that way.
1408
- ...(params.repeatCallAdvisory === false ? {} : { repeatCalls: new RepeatCallTracker() }),
1409
- compactionConfig,
1410
- ...(params.inboundMessages ? { inboundMessages: params.inboundMessages } : {}),
1411
- ...(params.resumeFromCheckpoint ? { resumedInput: queuedForThisRun } : {}),
1412
- ...(params.waitForInbound ? { waitForInbound: params.waitForInbound } : {}),
1413
- ...(params.projectInstructionContext
1414
- ? { projectInstructionContext: params.projectInstructionContext }
1415
- : {}),
1416
- ...(providerContextWindow !== undefined ? { providerContextWindow } : {}),
1417
- resolveModelContextWindow: async (model) => {
1418
- if (!modelContextWindows.has(model)) {
1419
- modelContextWindows.set(
1420
- model,
1421
- await resolveProviderContextWindow(
1422
- resilientProvider,
1438
+ const iterationOrchestrator = new IterationOrchestrator({
1439
+ captureSessionEvidence,
1440
+ provider: resilientProvider,
1441
+ providerCapabilities: capabilities,
1442
+ strictCapabilities: params.strictCapabilities === true,
1443
+ servingMember: () => serving.current,
1444
+ turnConfig,
1445
+ ...(params.stopWhen ? { stopWhen: params.stopWhen } : {}),
1446
+ ...(params.prepareStep ? { prepareStep: params.prepareStep } : {}),
1447
+ ...(params.beforeStep ? { beforeStep: params.beforeStep } : {}),
1448
+ ...(params.onStepFinish ? { onStepFinish: params.onStepFinish } : {}),
1449
+ ...(params.reviewAnswer ? { reviewAnswer: params.reviewAnswer } : {}),
1450
+ ...(params.maxAnswerReviews !== undefined
1451
+ ? { maxAnswerReviews: params.maxAnswerReviews }
1452
+ : {}),
1453
+ ...(params.structuredOutput ? { structuredOutput: params.structuredOutput } : {}),
1454
+ ...(params.parkRecordDelayMs !== undefined
1455
+ ? { parkRecordDelayMs: params.parkRecordDelayMs }
1456
+ : {}),
1457
+ tools: params.tools,
1458
+ allowedTools: effectiveAllowedTools,
1459
+ recorder: ctx.recorder,
1460
+ toolExecutor,
1461
+ guard,
1462
+ activityStore: ctx.activityStore,
1463
+ emitEvent: eventTranslator.emitEvent,
1464
+ drainPending: () => eventTranslator.drainPending(),
1465
+ abortController: ctx.abortController,
1466
+ log: ctx.log,
1467
+ // Read through the box on every call, so a swap lands on the next
1468
+ // question rather than the next turn.
1469
+ resumeHandler: (request) => approvalPolicy.current.handler(request),
1470
+ takeApprovalPolicyChange: () => approvalPolicy.takeUnannouncedChange(),
1471
+ promptContributions,
1472
+ ...(params.steering ? { steering: params.steering } : {}),
1473
+ ...(jobNotices ? { jobNotices } : {}),
1474
+ ...(awaitedJobs ? { awaitedJobs } : {}),
1475
+ checkpointMgr,
1476
+ planManager: ctx.planManager,
1477
+ taskGateway: taskScheduler,
1478
+ completionInbox: params.completionInbox,
1479
+ taskStore: params.taskStore,
1480
+ // Turn-scoped. An approval is a statement about this turn's work;
1481
+ // carrying one into a later turn would be reuse nobody agreed to.
1482
+ toolGrants: new ToolGrantSet(),
1483
+ // Turn-scoped for the same reason. A repeat count carried into a later
1484
+ // run is a claim about work nobody repeated, and a module-level map
1485
+ // would leak exactly that way.
1486
+ ...(params.repeatCallAdvisory === false ? {} : { repeatCalls: new RepeatCallTracker() }),
1487
+ compactionConfig,
1488
+ ...(params.inboundMessages ? { inboundMessages: params.inboundMessages } : {}),
1489
+ ...(params.resumeFromCheckpoint ? { resumedInput: queuedForThisRun } : {}),
1490
+ ...(params.waitForInbound ? { waitForInbound: params.waitForInbound } : {}),
1491
+ ...(params.projectInstructionContext
1492
+ ? { projectInstructionContext: params.projectInstructionContext }
1493
+ : {}),
1494
+ ...(providerContextWindow !== undefined ? { providerContextWindow } : {}),
1495
+ resolveModelContextWindow: async (model) => {
1496
+ if (!modelContextWindows.has(model)) {
1497
+ modelContextWindows.set(
1423
1498
  model,
1424
- ctx.abortController.signal,
1425
- runConfig.timeoutMs,
1426
- log,
1427
- ),
1428
- )
1429
- }
1430
- return modelContextWindows.get(model)
1431
- },
1432
- workingStateManager,
1433
- taskRouter: params.taskRouter,
1434
- contextReducer: params.contextReducer,
1435
- workingMemoryProvider: params.workingMemoryProvider,
1436
- advisoryCtx,
1437
- agentBus: params.agentBus,
1438
- verificationGate,
1439
- pluginManager: params.pluginManager,
1440
- })
1441
-
1442
- const tracer = getTracer()
1443
-
1444
- // Whether the run reached its settle. Read by the `finally` below, and
1445
- // the only thing that distinguishes a run that finished from one whose
1446
- // consumer walked away — see `settleAbandonedRun`.
1447
- let settled = false
1448
-
1449
- const runBody = (async function* (): AsyncGenerator<RunEvent, Run> {
1450
- // Parent explicitly when a caller supplied one. Without this every
1451
- // run starts its OWN root trace, so a supervisor delegating to three
1452
- // children produced four disconnected traces instead of one tree —
1453
- // the same defect that made a 20-turn run show up as 21 roots before
1454
- // iterations were parented, except across the spawn boundary, where
1455
- // it is worse: the delegation structure is the thing you most want
1456
- // to see.
1457
- const runStartedAt = Date.now()
1458
-
1459
- // Read before the span is minted, because a parent can only be set
1460
- // at creation. A resumed run used to start a brand-new trace with no
1461
- // link to the one that crashed, so the failure and its recovery
1462
- // could not be put on one timeline — the run id correlated them well
1463
- // enough to find both by query and not well enough to see a single
1464
- // waterfall, and for a replay fork (which mints a new run id) not
1465
- // even that. An explicit caller-supplied parent still wins: it is
1466
- // the more specific statement about where this run belongs.
1467
- const resumedTrace = selectedResumeState
1468
- ? selectedResumeState.traceContext
1469
- : params.resumeFromCheckpoint
1470
- ? await checkpointMgr.readTraceContext(params.resumeFromCheckpoint)
1471
- : undefined
1472
-
1473
- const rootSpan = tracer.startSpan(
1474
- agentRunSpanName(params.agentName),
1475
- {},
1476
- parentContext(params.parentSpan ?? resumedTrace),
1477
- )
1478
- // Hand the run span to the loop so every iteration parents to it.
1479
- iterationOrchestrator.setRootSpan(rootSpan)
1480
- // Every checkpoint from here on records the trace it was taken
1481
- // inside, so the next resume can join this one.
1482
- checkpointMgr.setTraceSource(() => serializeSpan(rootSpan))
1483
- // And every park it records carries an absolute deadline, so an
1484
- // unanswered approval cannot outlive the worker that asked for it.
1485
- checkpointMgr.setParkTtl(runConfig.hitlParkTtlMs)
1486
- // The claim this worker holds, if it took one. Without this hop the
1487
- // fence exists, the refusal exists, and no checkpoint a RUN writes ever
1488
- // carries a number — so a stalled worker is refused nowhere.
1489
- checkpointMgr.setClaimFence(params.claimFence)
1490
- // A question raised from inside a tool becomes a real checkpoint
1491
- // here. It used to park under a synthetic id nothing ever wrote, so
1492
- // the checkpoint did not exist: nothing on disk said a human owed
1493
- // this run an answer, and a remote host could not observe the
1494
- // question at all.
1495
- questionParks.bind({
1496
- record: async (question) => {
1497
- try {
1498
- const checkpoint = await checkpointMgr.create(ctx.runMgr, ctx.runMgr.currentIteration)
1499
- const parked = await checkpointMgr.park(checkpoint, {
1500
- type: 'user_question',
1501
- runId: ctx.runMgr.id,
1502
- checkpointId: checkpoint.id,
1503
- question,
1504
- })
1505
- await eventTranslator.emitEvent({
1506
- type: 'user_question_asked',
1507
- runId: ctx.runMgr.id,
1508
- checkpointId: parked.id,
1509
- questionId: question.questionId,
1510
- question: question.question,
1511
- })
1512
- return parked.id
1513
- } catch (err) {
1514
- // A store that cannot record the park must not take the
1515
- // tool down with it: the in-process await is still valid
1516
- // and only the cross-process handoff is lost. Loudly,
1517
- // because a host building an approval queue from durable
1518
- // state will not see this question.
1519
- ctx.log.error('Failed to record a question park — it is not resumable', {
1520
- [NAMZU.RUN_ID]: ctx.runMgr.id,
1521
- 'namzu.runtime.question_id': question.questionId,
1522
- 'exception.message': err instanceof Error ? err.message : String(err),
1523
- })
1524
- return null
1499
+ await resolveProviderContextWindow(
1500
+ resilientProvider,
1501
+ model,
1502
+ ctx.abortController.signal,
1503
+ turnConfig.timeoutMs,
1504
+ log,
1505
+ ),
1506
+ )
1525
1507
  }
1508
+ return modelContextWindows.get(model)
1526
1509
  },
1527
- resolve: async (checkpointId, decision) => {
1528
- await checkpointMgr.unpark(checkpointId, decision).catch((err: unknown) => {
1529
- ctx.log.error('Failed to clear a recorded question park', {
1530
- [NAMZU.RUN_ID]: ctx.runMgr.id,
1531
- 'namzu.checkpoint.id': checkpointId,
1532
- 'exception.message': err instanceof Error ? err.message : String(err),
1533
- })
1534
- return null
1535
- })
1536
- await eventTranslator.emitEvent({
1537
- type: 'user_question_answered',
1538
- runId: ctx.runMgr.id,
1539
- checkpointId,
1540
- ...(decision.action === 'answer_question' && decision.questionId !== undefined
1541
- ? { questionId: decision.questionId }
1542
- : {}),
1543
- answered: decision.action === 'answer_question',
1544
- })
1545
- },
1546
- })
1547
- rootSpan.setAttributes({
1548
- [NAMZU.RUN_ID]: ctx.runMgr.id,
1549
- [GENAI.AGENT_NAME]: params.agentName,
1550
- [GENAI.AGENT_ID]: params.agentId,
1551
- [GENAI.REQUEST_MODEL]: runConfig.model,
1552
- [GENAI.SYSTEM]: params.provider.id,
1510
+ workingStateManager,
1511
+ taskRouter: params.taskRouter,
1512
+ contextReducer: params.contextReducer,
1513
+ workingMemoryProvider: params.workingMemoryProvider,
1514
+ advisoryCtx,
1515
+ agentBus: params.agentBus,
1516
+ verificationGate,
1517
+ pluginManager: params.pluginManager,
1553
1518
  })
1554
1519
 
1555
- let sandbox: Sandbox | undefined
1556
- // Decided during checkpoint restore, executed after the sandbox
1557
- // exists — the approved tools may well need it.
1558
- let pendingResume: PendingResumePlan | null = null
1559
- /**
1560
- * The cadence park this resume answered, when the decision is one the
1561
- * ordinary continue path carries out. See the restore path below.
1562
- */
1563
- let answeredParkId: CheckpointId | undefined
1564
- /** Tool results recovered from the transcript; see the restore path. */
1565
- let recoveredResults: ReadonlyMap<string, { result: string; isError: boolean }> = new Map()
1566
- let emergencyManager: EmergencySaveManager | undefined
1520
+ const tracer = getTracer()
1521
+
1522
+ // Whether the turn reached its settle. Read by the `finally` below, and
1523
+ // the only thing that distinguishes a turn that finished from one whose
1524
+ // consumer walked away — see `settleAbandonedTurn`.
1525
+ let settled = false
1526
+
1527
+ const runBody = (async function* (): AsyncGenerator<SessionEvent, Turn> {
1528
+ // Parent explicitly when a caller supplied one. Without this every
1529
+ // run starts its OWN root trace, so a supervisor delegating to three
1530
+ // children produced four disconnected traces instead of one tree —
1531
+ // the same defect that made a 20-turn run show up as 21 roots before
1532
+ // iterations were parented, except across the spawn boundary, where
1533
+ // it is worse: the delegation structure is the thing you most want
1534
+ // to see.
1535
+ const runStartedAt = Date.now()
1536
+
1537
+ // Read before the span is minted, because a parent can only be set
1538
+ // at creation. A resumed turn used to start a brand-new trace with no
1539
+ // link to the one that crashed, so the failure and its recovery
1540
+ // could not be put on one timeline — the turn id correlated them well
1541
+ // enough to find both by query and not well enough to see a single
1542
+ // waterfall, and for a replay fork (which mints a new turn id) not
1543
+ // even that. An explicit caller-supplied parent still wins: it is
1544
+ // the more specific statement about where this turn belongs.
1545
+ const resumedTrace = selectedResumeState
1546
+ ? selectedResumeState.traceContext
1547
+ : params.resumeFromCheckpoint
1548
+ ? await checkpointMgr.readTraceContext(params.resumeFromCheckpoint)
1549
+ : undefined
1567
1550
 
1568
- try {
1569
- await ctx.runMgr.init()
1570
-
1571
- // A consumer coming back gets what it missed BEFORE the run says
1572
- // anything new, which is the only order that lets it fold one
1573
- // stream into one state. It has to follow `init()` — that is what
1574
- // binds the store and reads the log's head — and precede every
1575
- // emit below.
1576
- if (params.eventCursor) {
1577
- yield* catchUpFromCursor(
1578
- ctx.runMgr,
1579
- params.eventCursor,
1580
- params.onEventReplay,
1581
- params.claimFence,
1582
- (error) => {
1583
- ctx.log.warn('Replay observer failed', {
1584
- 'exception.message': toErrorMessage(error),
1551
+ const rootSpan = tracer.startSpan(
1552
+ agentTurnSpanName(params.agentName),
1553
+ {},
1554
+ parentContext(params.parentSpan ?? resumedTrace),
1555
+ )
1556
+ // Hand the turn span to the loop so every iteration parents to it.
1557
+ iterationOrchestrator.setRootSpan(rootSpan)
1558
+ // Every checkpoint from here on records the trace it was taken
1559
+ // inside, so the next resume can join this one.
1560
+ checkpointMgr.setTraceSource(() => serializeSpan(rootSpan))
1561
+ // And every park it records carries an absolute deadline, so an
1562
+ // unanswered approval cannot outlive the worker that asked for it.
1563
+ checkpointMgr.setParkTtl(turnConfig.hitlParkTtlMs)
1564
+ // A question raised from inside a tool becomes a real checkpoint
1565
+ // here. It used to park under a synthetic id nothing ever wrote, so
1566
+ // the checkpoint did not exist: nothing on disk said a human owed
1567
+ // this turn an answer, and a remote host could not observe the
1568
+ // question at all.
1569
+ questionParks.bind({
1570
+ record: async (question) => {
1571
+ try {
1572
+ const checkpoint = await checkpointMgr.create(
1573
+ ctx.recorder,
1574
+ ctx.recorder.currentIteration,
1575
+ )
1576
+ await checkpointMgr.park(checkpoint, {
1577
+ type: 'user_question',
1578
+ sessionId: ctx.sessionId,
1579
+ turnId: ctx.turnId,
1580
+ checkpointId: checkpoint.id,
1581
+ question,
1585
1582
  })
1586
- },
1587
- )
1588
- }
1589
-
1590
- ctx.log.info('Starting query', {
1591
- [NAMZU.RUN_ID]: ctx.runMgr.id,
1592
- 'namzu.runtime.agent': params.agentName,
1593
- [GENAI.REQUEST_MODEL]: runConfig.model,
1594
- 'namzu.runtime.token_budget': runConfig.tokenBudget,
1595
- 'namzu.runtime.activity_tracking': ctx.activityStore.enabled,
1596
- 'namzu.runtime.permission_mode': ctx.permissionMode.current,
1597
- 'namzu.runtime.resume_from_checkpoint': params.resumeFromCheckpoint ?? null,
1598
- })
1599
-
1600
- // The operator's prompt, before the model sees it. A hook may
1601
- // refuse it — the run ends here, before a prompt is built — or add
1602
- // to what the model is told; the addition rides the prompt as a
1603
- // dynamic contribution so every iteration of the run carries it.
1604
- if (params.pluginManager) {
1605
- const hookResults = await params.pluginManager.executeHooks(
1606
- 'user_prompt_submit',
1607
- {
1608
- runId: ctx.runId,
1609
- sessionId: params.sessionId,
1610
- prompt: lastUserPrompt(initialMessages),
1611
- signal: ctx.abortController.signal,
1612
- },
1613
- eventTranslator.emitEvent,
1614
- )
1615
- const annotations = applyLifecycleHookResults('user_prompt_submit', hookResults)
1616
- if (annotations.length > 0) {
1617
- promptContributions.replace({
1618
- id: 'hooks:user_prompt_submit',
1619
- placement: 'dynamic',
1620
- render: () => `Context from the operator's hooks:\n\n${annotations.join('\n\n')}`,
1583
+ await eventTranslator.emitEvent({
1584
+ type: 'user_question_asked',
1585
+ checkpointId: checkpoint.id,
1586
+ questionId: question.questionId,
1587
+ question: question.question,
1588
+ })
1589
+ return checkpoint.id
1590
+ } catch (err) {
1591
+ // A store that cannot record the park must not take the
1592
+ // tool down with it: the in-process await is still valid
1593
+ // and only the cross-process handoff is lost. Loudly,
1594
+ // because a host building an approval queue from durable
1595
+ // state will not see this question.
1596
+ ctx.log.error('Failed to record a question park — it is not resumable', {
1597
+ [NAMZU.TURN_ID]: ctx.recorder.turnId,
1598
+ 'namzu.runtime.question_id': question.questionId,
1599
+ 'exception.message': err instanceof Error ? err.message : String(err),
1600
+ })
1601
+ return null
1602
+ }
1603
+ },
1604
+ resolve: async (checkpointId, decision) => {
1605
+ await checkpointMgr.unpark(checkpointId, decision).catch((err: unknown) => {
1606
+ ctx.log.error('Failed to clear a recorded question park', {
1607
+ [NAMZU.TURN_ID]: ctx.recorder.turnId,
1608
+ 'namzu.checkpoint.id': checkpointId,
1609
+ 'exception.message': err instanceof Error ? err.message : String(err),
1610
+ })
1611
+ return null
1621
1612
  })
1622
- }
1623
- yield* eventTranslator.drainPending()
1624
- }
1625
-
1626
- const contextLevel = params.contextLevel ?? 'full'
1627
- const cacheInput = {
1628
- systemPrompt: params.systemPrompt,
1629
- persona: params.persona,
1630
- skills: params.skills,
1631
- basePrompt: contextLevel === 'full' ? params.basePrompt : undefined,
1632
- tools: params.tools,
1633
- allowedTools: effectiveAllowedTools,
1634
- runtimeContext: params.runtimeContext,
1635
- contributions: promptContributions,
1636
- }
1637
-
1638
- const segments: PromptSegments = promptCache
1639
- ? promptCache.getSystemPromptSegmented(cacheInput, contextLevel, params.workingDirectory)
1640
- : promptBuilder.buildSegmented(contextLevel, params.workingDirectory)
1641
-
1642
- ctx.log.info('Prompt segments assembled', {
1643
- 'namzu.runtime.static_length': segments.static.length,
1644
- 'namzu.runtime.dynamic_length': segments.dynamic.length,
1613
+ await eventTranslator.emitEvent({
1614
+ type: 'user_question_answered',
1615
+ checkpointId,
1616
+ ...(decision.action === 'answer_question' && decision.questionId !== undefined
1617
+ ? { questionId: decision.questionId }
1618
+ : {}),
1619
+ answered: decision.action === 'answer_question',
1620
+ })
1621
+ },
1622
+ })
1623
+ rootSpan.setAttributes({
1624
+ [GENAI.CONVERSATION_ID]: ctx.sessionId,
1625
+ [NAMZU.TURN_ID]: ctx.recorder.turnId,
1626
+ ...(params.parentSessionId !== undefined && {
1627
+ [NAMZU.SESSION_PARENT_ID]: params.parentSessionId,
1628
+ }),
1629
+ [GENAI.AGENT_NAME]: params.agentName,
1630
+ [GENAI.AGENT_ID]: params.agentId,
1631
+ [GENAI.REQUEST_MODEL]: turnConfig.model,
1632
+ [GENAI.SYSTEM]: params.provider.id,
1645
1633
  })
1646
1634
 
1647
- const pushSystemMessages = (): void => {
1648
- ctx.runMgr.pushMessage(createSystemMessage(segments.static, 'cache'))
1649
- if (segments.dynamic.length > 0) {
1650
- ctx.runMgr.pushMessage(createSystemMessage(segments.dynamic, 'ephemeral'))
1635
+ let sandbox: Sandbox | undefined
1636
+ // Decided during checkpoint restore, executed after the sandbox
1637
+ // exists — the approved tools may well need it.
1638
+ let pendingResume: PendingResumePlan | null = null
1639
+ /** The record id of the parked assistant message the plan re-appends. */
1640
+ let pendingResumeAssistantId: MessageId | undefined
1641
+ /**
1642
+ * The cadence park this resume answered, when the decision is one the
1643
+ * ordinary continue path carries out. See the restore path below.
1644
+ */
1645
+ let answeredParkId: CheckpointId | undefined
1646
+ /** Tool results recovered from the transcript; see the restore path. */
1647
+ let recoveredResults: ReadonlyMap<string, { result: string; isError: boolean }> = new Map()
1648
+
1649
+ try {
1650
+ // A consumer coming back gets what it missed BEFORE the turn says
1651
+ // anything new, which is the only order that lets it fold one
1652
+ // stream into one state. It follows the prelude's `open()` — which
1653
+ // took the lease and read the log's head — and precedes every emit
1654
+ // below.
1655
+ if (params.eventCursor) {
1656
+ yield* catchUpFromCursor(
1657
+ ctx.recorder,
1658
+ params.eventCursor,
1659
+ params.onEventReplay,
1660
+ (error) => {
1661
+ ctx.log.warn('Replay observer failed', {
1662
+ 'exception.message': toErrorMessage(error),
1663
+ })
1664
+ },
1665
+ )
1651
1666
  }
1652
- }
1653
1667
 
1654
- if (params.resumeFromCheckpoint) {
1655
- const checkpoint = await checkpointMgr.restore(params.resumeFromCheckpoint)
1656
- const projectedCheckpoint = {
1657
- ...checkpoint,
1658
- messages: projectStateBearingHistory(checkpoint.messages, {
1659
- pinCompaction: false,
1660
- }),
1661
- }
1662
- await eventTranslator.emitEvent({
1663
- type: 'run_resuming',
1664
- runId: ctx.runMgr.id,
1665
- fromCheckpointId: checkpoint.id,
1668
+ ctx.log.info('Starting query', {
1669
+ [NAMZU.TURN_ID]: ctx.recorder.turnId,
1670
+ 'namzu.runtime.agent': params.agentName,
1671
+ [GENAI.REQUEST_MODEL]: turnConfig.model,
1672
+ 'namzu.runtime.token_budget': turnConfig.tokenBudget,
1673
+ 'namzu.runtime.activity_tracking': ctx.activityStore.enabled,
1674
+ 'namzu.runtime.permission_mode': ctx.permissionMode.current,
1675
+ 'namzu.runtime.resume_from_checkpoint': params.resumeFromCheckpoint ?? null,
1666
1676
  })
1667
- yield* eventTranslator.drainPending()
1668
1677
 
1669
- // Budgets are properties of the RUN, not of the process hosting
1670
- // it. The checkpoint already carried all three; they were
1671
- // written and then discarded on the way back in, so a run
1672
- // recalled at $4.80 of a $5 cap came back with a fresh $5 and
1673
- // a fresh timeout clock. Restore before the first iteration so
1674
- // a resumed run that is already over budget stops immediately.
1675
- ctx.runMgr.restoreUsage(
1676
- checkpoint.tokenUsage,
1677
- checkpoint.costInfo,
1678
- checkpoint.guardState.iterationCount,
1679
- )
1680
- guard.restoreElapsed(checkpoint.guardState.elapsedMs)
1681
-
1682
- // Adopt the working state the earlier summary was built from.
1683
- // The `[COMPACTED CONTEXT]` block below is preserved precisely
1684
- // because it is the only surviving record of the history the
1685
- // first pass deleted — and without this, the NEXT compaction
1686
- // would drop it and replace it with a summary covering only
1687
- // what happened after the resume, silently losing the run's
1688
- // first hour.
1689
- if (workingStateManager && checkpoint.workingState && compactionConfig) {
1690
- const revived = restoreWorkingState(checkpoint.workingState, compactionConfig)
1691
- workingStateManager.replaceState(revived.getState())
1692
- ctx.log.info('Restored compaction working state from checkpoint', {
1693
- [NAMZU.RUN_ID]: ctx.runMgr.id,
1694
- 'namzu.checkpoint.id': checkpoint.id,
1695
- 'namzu.runtime.slots': workingStateManager.slotCount(),
1696
- })
1678
+ // The operator's prompt, before the model sees it. A hook may
1679
+ // refuse it — the turn ends here, before a prompt is built — or add
1680
+ // to what the model is told; the addition rides the prompt as a
1681
+ // dynamic contribution so every iteration of the turn carries it.
1682
+ if (params.pluginManager) {
1683
+ const hookResults = await params.pluginManager.executeHooks(
1684
+ 'user_prompt_submit',
1685
+ {
1686
+ turnId: ctx.turnId,
1687
+ sessionId: params.sessionId,
1688
+ prompt: lastUserPrompt(initialMessages),
1689
+ signal: ctx.abortController.signal,
1690
+ },
1691
+ eventTranslator.emitEvent,
1692
+ )
1693
+ const annotations = applyLifecycleHookResults('user_prompt_submit', hookResults)
1694
+ if (annotations.length > 0) {
1695
+ promptContributions.replace({
1696
+ id: 'hooks:user_prompt_submit',
1697
+ placement: 'dynamic',
1698
+ render: () => `Context from the operator's hooks:\n\n${annotations.join('\n\n')}`,
1699
+ })
1700
+ }
1701
+ yield* eventTranslator.drainPending()
1697
1702
  }
1698
- ctx.log.info('Restored budgets from checkpoint', {
1699
- [NAMZU.RUN_ID]: ctx.runMgr.id,
1700
- 'namzu.checkpoint.id': checkpoint.id,
1701
- 'namzu.usage.total_tokens': checkpoint.tokenUsage.totalTokens,
1702
- 'namzu.runtime.total_cost': checkpoint.costInfo.totalCost,
1703
- [NAMZU.ITERATION]: checkpoint.guardState.iterationCount,
1704
- 'namzu.runtime.elapsed_ms': checkpoint.guardState.elapsedMs,
1705
- })
1706
-
1707
- pushSystemMessages()
1708
-
1709
- // A human answered the park in a different process; apply that
1710
- // answer to the tool calls they were actually shown. Without
1711
- // this the repair below throws the approval away and the model
1712
- // re-decides, so "yes, delete that row" degrades into "ask
1713
- // again and hope it asks for the same thing".
1714
- pendingResume =
1715
- params.pendingDecision && projectedCheckpoint.pending
1716
- ? planPendingResume(projectedCheckpoint, params.pendingDecision, ctx.log)
1717
- : null
1718
1703
 
1719
- // The park this resume ANSWERS even though there is no plan to
1720
- // carry the decision out through.
1721
- //
1722
- // `planPendingResume` covers the two arms whose decision has to
1723
- // reach something — the calls a `tool_review` park is about, the
1724
- // tool a `user_question` park is inside. An `iteration_checkpoint`
1725
- // park has neither, so it returns no plan, and the unpark further
1726
- // down — which ran only when there was one — never fired for it.
1727
- // A run that parked on the cadence, was resumed with
1728
- // `{action: 'continue'}` and went on to finish its work therefore
1729
- // kept reporting an OUTSTANDING park to `findPendingCheckpoint`,
1730
- // so a second resume of the finished run was refused with
1731
- // `awaiting-decision` for a decision already taken, and because
1732
- // `prune` skips an unresolved park the row could no longer be
1733
- // collected by anything.
1734
- //
1735
- // The decision IS carried out here — continuing is exactly what
1736
- // the loop below does, and a plan verdict is the answer to the
1737
- // question the plan park asked — so the park is resolved at the
1738
- // same point and with the same meaning "resolved" carries
1739
- // everywhere else: the record stays, and only its pending state
1740
- // ends. A `pause` is deliberately not resolved: it holds the
1741
- // park rather than answering it, which is how the live path
1742
- // treats it too. `answersParkOf` is the whole map, park type to
1743
- // answering decision, so an arm cannot go missing by being
1744
- // absent from a condition again — which is how the plan arm
1745
- // leaked a finished run's park.
1746
- //
1747
- // Resolving it does not depend on the resumed process being able
1748
- // to act on it, and that is deliberate: the plan's own fate is a
1749
- // separate defect (nothing restores a plan on the resume path at
1750
- // all, so the new process has none to approve, execute or
1751
- // reject) and making the resolution wait for it would leave the
1752
- // row outstanding for exactly the runs that need it cleared.
1753
- const parked = projectedCheckpoint.pending
1754
- answeredParkId =
1755
- params.pendingDecision &&
1756
- parked !== undefined &&
1757
- parked.resolvedAt === undefined &&
1758
- answersParkOf(parked.request.type, params.pendingDecision)
1759
- ? projectedCheckpoint.id
1760
- : undefined
1704
+ const contextLevel = params.contextLevel ?? 'full'
1705
+ const cacheInput = {
1706
+ systemPrompt: params.systemPrompt,
1707
+ persona: params.persona,
1708
+ skills: params.skills,
1709
+ basePrompt: contextLevel === 'full' ? params.basePrompt : undefined,
1710
+ tools: params.tools,
1711
+ allowedTools: effectiveAllowedTools,
1712
+ runtimeContext: params.runtimeContext,
1713
+ contributions: promptContributions,
1714
+ }
1761
1715
 
1762
- // Recover completed observations and explicitly unknown outcomes.
1763
- // A recorded start is not proof that its external effect failed.
1764
- const unanswered = interruptedToolCalls(projectedCheckpoint.messages)
1765
- recoveredResults =
1766
- unanswered.length > 0
1767
- ? await recoverCompletedCalls(ctx.runMgr, unanswered, ctx.log, {
1768
- answers: pendingResume?.answers,
1769
- signal: ctx.abortController.signal,
1770
- })
1771
- : new Map()
1716
+ const segments: PromptSegments = promptCache
1717
+ ? promptCache.getSystemPromptSegmented(cacheInput, contextLevel, params.workingDirectory)
1718
+ : promptBuilder.buildSegmented(contextLevel, params.workingDirectory)
1772
1719
 
1773
- // Preserve both known and unknown outcomes before continuing calls
1774
- // whose absence of a start was established by a complete scan.
1775
- if (!pendingResume && recoveredResults.size > 0) {
1776
- pendingResume = planCrashResume(projectedCheckpoint, recoveredResults, ctx.log)
1777
- }
1720
+ ctx.log.info('Prompt segments assembled', {
1721
+ 'namzu.runtime.static_length': segments.static.length,
1722
+ 'namzu.runtime.dynamic_length': segments.dynamic.length,
1723
+ })
1778
1724
 
1779
- // An incomplete turn with a durable owner is NOT abandoned. A
1780
- // pending decision or crash-resume plan re-appends that exact
1781
- // assistant with real/denied/recovered results below. Remove it
1782
- // from the generic pass so no synthetic result competes with the
1783
- // authority that still owns the call. Everything else is abandoned
1784
- // history and is repaired conservatively rather than deleted.
1785
- const abandonedCheckpointMessages = pendingResume
1786
- ? withoutOwnedResumeTurn(projectedCheckpoint.messages, pendingResume.assistant)
1787
- : projectedCheckpoint.messages
1788
- const checkpointRepair = repairToolMessageHistory(abandonedCheckpointMessages)
1789
- const restoredMessages = checkpointRepair.messages
1790
- if (toolHistoryRepairChanged(checkpointRepair.report)) {
1791
- pendingHistoryRepairs.push({
1792
- source: 'abandoned-checkpoint',
1793
- report: checkpointRepair.report,
1794
- })
1795
- ctx.log.warn('Repaired abandoned tool history while restoring a checkpoint', {
1796
- [NAMZU.RUN_ID]: ctx.runMgr.id,
1797
- 'namzu.checkpoint.id': checkpoint.id,
1798
- 'namzu.history.source': 'abandoned-checkpoint',
1799
- 'namzu.history.duplicate_tool_results_removed':
1800
- checkpointRepair.report.duplicateToolResultsRemoved,
1801
- 'namzu.history.orphaned_tool_results_removed':
1802
- checkpointRepair.report.orphanedToolResultsRemoved,
1803
- 'namzu.history.synthetic_tool_results_inserted':
1804
- checkpointRepair.report.syntheticToolResultsInserted,
1725
+ // The prompt floor is rebuilt every turn and never recorded:
1726
+ // `turn_started.systemPrompt` carries it.
1727
+ const pushSystemMessages = (): void => {
1728
+ ctx.recorder.pushMessage(createSystemMessage(segments.static, 'cache'), {
1729
+ transient: true,
1805
1730
  })
1731
+ if (segments.dynamic.length > 0) {
1732
+ ctx.recorder.pushMessage(createSystemMessage(segments.dynamic, 'ephemeral'), {
1733
+ transient: true,
1734
+ })
1735
+ }
1736
+ }
1737
+ const pushRestored = (message: Message, ids: ReadonlyMap<Message, MessageId>): void => {
1738
+ const messageId = ids.get(message)
1739
+ ctx.recorder.pushMessage(message, messageId ? { messageId } : {})
1806
1740
  }
1807
1741
 
1808
- // The ledger is process state and a resumed run starts with an empty
1809
- // one, so until something reads a file again this run knows nothing
1810
- // about files the conversation already wrote in full — and re-reads
1811
- // them. Rebuilt from the REPAIRED history, which is what the model
1812
- // is about to be shown, rather than from the checkpoint's own
1813
- // messages — plus whatever of the owned resume turn actually ran,
1814
- // which the repaired list does not carry; see
1815
- // `withOwnedResumeOutcomes`. Reads no file's content: every
1816
- // fingerprint recovered here is still checked against the real one
1817
- // at mutation time.
1818
- try {
1819
- await toolExecutor.seedFileObservations(
1820
- pendingResume
1821
- ? withOwnedResumeOutcomes(restoredMessages, pendingResume.assistant, recoveredResults)
1822
- : restoredMessages,
1823
- params.sandboxProvider !== undefined,
1742
+ if (params.resumeFromCheckpoint) {
1743
+ const checkpoint = await checkpointMgr.restore(params.resumeFromCheckpoint)
1744
+ const projectedCheckpoint = {
1745
+ ...checkpoint,
1746
+ messages: projectStateBearingHistory(checkpoint.messages, {
1747
+ pinCompaction: false,
1748
+ }),
1749
+ }
1750
+ await eventTranslator.resumeTurn(checkpoint.id)
1751
+ yield* eventTranslator.drainPending()
1752
+
1753
+ // Budgets are properties of the TURN, not of the process hosting
1754
+ // it. The checkpoint already carried all three; they were
1755
+ // written and then discarded on the way back in, so a turn
1756
+ // recalled at $4.80 of a $5 cap came back with a fresh $5 and
1757
+ // a fresh timeout clock. Restore before the first iteration so
1758
+ // a resumed turn that is already over budget stops immediately.
1759
+ ctx.recorder.restoreUsage(
1760
+ checkpoint.document.tokenUsage,
1761
+ checkpoint.document.costInfo,
1762
+ checkpoint.document.guards.iteration,
1824
1763
  )
1825
- } catch (err: unknown) {
1826
- // A ledger that could not be rebuilt is the empty one every resume
1827
- // used to get, so the run continues without its witnesses and the
1828
- // model reads what it needs. Failing the resume over it would trade
1829
- // a conversation that works for one that does not, to protect an
1830
- // optimisation. Said out loud all the same, because a seeding that
1831
- // failed and one that found nothing are otherwise the same silence.
1832
- ctx.log.debug('Could not rebuild the file observation ledger on resume', {
1833
- [NAMZU.RUN_ID]: ctx.runMgr.id,
1764
+ guard.restoreElapsed(checkpoint.document.guards.elapsedMs)
1765
+
1766
+ // Adopt the working state the earlier summary was built from.
1767
+ // The `[COMPACTED CONTEXT]` block below is preserved precisely
1768
+ // because it is the only surviving record of the history the
1769
+ // first pass deleted — and without this, the NEXT compaction
1770
+ // would drop it and replace it with a summary covering only
1771
+ // what happened after the resume, silently losing the turn's
1772
+ // first hour.
1773
+ if (workingStateManager && checkpoint.document.workingState && compactionConfig) {
1774
+ const revived = restoreWorkingState(checkpoint.document.workingState, compactionConfig)
1775
+ workingStateManager.replaceState(revived.getState())
1776
+ ctx.log.info('Restored compaction working state from checkpoint', {
1777
+ [NAMZU.TURN_ID]: ctx.recorder.turnId,
1778
+ 'namzu.checkpoint.id': checkpoint.id,
1779
+ 'namzu.runtime.slots': workingStateManager.slotCount(),
1780
+ })
1781
+ }
1782
+ ctx.log.info('Restored budgets from checkpoint', {
1783
+ [NAMZU.TURN_ID]: ctx.recorder.turnId,
1834
1784
  'namzu.checkpoint.id': checkpoint.id,
1835
- 'exception.message': err instanceof Error ? err.message : String(err),
1785
+ 'namzu.usage.total_tokens': checkpoint.document.tokenUsage.totalTokens,
1786
+ 'namzu.runtime.total_cost': checkpoint.document.costInfo.totalCost,
1787
+ [NAMZU.ITERATION]: checkpoint.document.guards.iteration,
1788
+ 'namzu.runtime.elapsed_ms': checkpoint.document.guards.elapsedMs,
1836
1789
  })
1837
- }
1838
1790
 
1839
- for (const msg of restoredMessages) {
1840
- if (msg.role === 'system') {
1841
- // Re-push the FRESH static/dynamic floor (done above) but PRESERVE
1842
- // the two system messages that carry irreplaceable run state: the
1843
- // `[COMPACTED CONTEXT]` summary is the only surviving record of the
1844
- // older history a compaction pass deleted, and the working-memory
1845
- // slot pins the produced-artifact ledger. Dropping every system
1846
- // message on restore silently lost both on resume.
1847
- if (isCompactionMessage(msg.content) || isWorkingMemoryMessage(msg.content)) {
1848
- ctx.runMgr.pushMessage(msg)
1791
+ pushSystemMessages()
1792
+
1793
+ // A human answered the park in a different process; apply that
1794
+ // answer to the tool calls they were actually shown. Without
1795
+ // this the repair below throws the approval away and the model
1796
+ // re-decides, so "yes, delete that row" degrades into "ask
1797
+ // again and hope it asks for the same thing".
1798
+ pendingResume =
1799
+ params.pendingDecision && projectedCheckpoint.pending
1800
+ ? planPendingResume(projectedCheckpoint, params.pendingDecision, ctx.log)
1801
+ : null
1802
+
1803
+ // The park this resume ANSWERS even though there is no plan to
1804
+ // carry the decision out through.
1805
+ //
1806
+ // `planPendingResume` covers the two arms whose decision has to
1807
+ // reach something — the calls a `tool_review` park is about, the
1808
+ // tool a `user_question` park is inside. An `iteration_checkpoint`
1809
+ // park has neither, so it returns no plan, and the unpark further
1810
+ // down — which ran only when there was one — never fired for it.
1811
+ // A turn that parked on the cadence, was resumed with
1812
+ // `{action: 'continue'}` and went on to finish its work therefore
1813
+ // kept reporting an OUTSTANDING park to `findPendingCheckpoint`,
1814
+ // so a second resume of the finished turn was refused with
1815
+ // `awaiting-decision` for a decision already taken, and because
1816
+ // `prune` skips an unresolved park the row could no longer be
1817
+ // collected by anything.
1818
+ //
1819
+ // The decision IS carried out here — continuing is exactly what
1820
+ // the loop below does, and a plan verdict is the answer to the
1821
+ // question the plan park asked — so the park is resolved at the
1822
+ // same point and with the same meaning "resolved" carries
1823
+ // everywhere else: the record stays, and only its pending state
1824
+ // ends. A `pause` is deliberately not resolved: it holds the
1825
+ // park rather than answering it, which is how the live path
1826
+ // treats it too. `answersParkOf` is the whole map, park type to
1827
+ // answering decision, so an arm cannot go missing by being
1828
+ // absent from a condition again — which is how the plan arm
1829
+ // leaked a finished turn's park.
1830
+ //
1831
+ // Resolving it does not depend on the resumed process being able
1832
+ // to act on it, and that is deliberate: the plan's own fate is a
1833
+ // separate defect (nothing restores a plan on the resume path at
1834
+ // all, so the new process has none to approve, execute or
1835
+ // reject) and making the resolution wait for it would leave the
1836
+ // row outstanding for exactly the turns that need it cleared.
1837
+ const parked = projectedCheckpoint.pending
1838
+ answeredParkId =
1839
+ params.pendingDecision &&
1840
+ parked !== undefined &&
1841
+ parked.resolvedAt === undefined &&
1842
+ answersParkOf(parked.request.type, params.pendingDecision)
1843
+ ? projectedCheckpoint.id
1844
+ : undefined
1845
+
1846
+ // Recover completed observations and explicitly unknown outcomes.
1847
+ // A recorded start is not proof that its external effect failed.
1848
+ const unanswered = interruptedToolCalls(projectedCheckpoint.messages)
1849
+ recoveredResults =
1850
+ unanswered.length > 0
1851
+ ? await recoverCompletedCalls(ctx.recorder, unanswered, ctx.log, {
1852
+ answers: pendingResume?.answers,
1853
+ signal: ctx.abortController.signal,
1854
+ })
1855
+ : new Map()
1856
+
1857
+ // Preserve both known and unknown outcomes before continuing calls
1858
+ // whose absence of a start was established by a complete scan.
1859
+ if (!pendingResume && recoveredResults.size > 0) {
1860
+ pendingResume = planCrashResume(projectedCheckpoint, recoveredResults, ctx.log)
1861
+ }
1862
+
1863
+ // An incomplete turn with a durable owner is NOT abandoned. A
1864
+ // pending decision or crash-resume plan re-appends that exact
1865
+ // assistant with real/denied/recovered results below. Remove it
1866
+ // from the generic pass so no synthetic result competes with the
1867
+ // authority that still owns the call. Everything else is abandoned
1868
+ // history and is repaired conservatively rather than deleted.
1869
+ pendingResumeAssistantId = pendingResume
1870
+ ? checkpoint.messageIds.get(pendingResume.assistant)
1871
+ : undefined
1872
+ const abandonedCheckpointMessages = pendingResume
1873
+ ? withoutOwnedResumeTurn(projectedCheckpoint.messages, pendingResume.assistant)
1874
+ : projectedCheckpoint.messages
1875
+ const checkpointRepair = repairToolMessageHistory(abandonedCheckpointMessages)
1876
+ const restoredMessages = checkpointRepair.messages
1877
+ if (toolHistoryRepairChanged(checkpointRepair.report)) {
1878
+ pendingHistoryRepairs.push({
1879
+ source: 'abandoned-checkpoint',
1880
+ report: checkpointRepair.report,
1881
+ })
1882
+ ctx.log.warn('Repaired abandoned tool history while restoring a checkpoint', {
1883
+ [NAMZU.TURN_ID]: ctx.recorder.turnId,
1884
+ 'namzu.checkpoint.id': checkpoint.id,
1885
+ 'namzu.history.source': 'abandoned-checkpoint',
1886
+ 'namzu.history.duplicate_tool_results_removed':
1887
+ checkpointRepair.report.duplicateToolResultsRemoved,
1888
+ 'namzu.history.orphaned_tool_results_removed':
1889
+ checkpointRepair.report.orphanedToolResultsRemoved,
1890
+ 'namzu.history.synthetic_tool_results_inserted':
1891
+ checkpointRepair.report.syntheticToolResultsInserted,
1892
+ })
1893
+ }
1894
+
1895
+ // The ledger is process state and a resumed turn starts with an empty
1896
+ // one, so until something reads a file again this turn knows nothing
1897
+ // about files the conversation already wrote in full — and re-reads
1898
+ // them. Rebuilt from the REPAIRED history, which is what the model
1899
+ // is about to be shown, rather than from the checkpoint's own
1900
+ // messages — plus whatever of the owned resume turn actually ran,
1901
+ // which the repaired list does not carry; see
1902
+ // `withOwnedResumeOutcomes`. Reads no file's content: every
1903
+ // fingerprint recovered here is still checked against the real one
1904
+ // at mutation time.
1905
+ try {
1906
+ await toolExecutor.seedFileObservations(
1907
+ pendingResume
1908
+ ? withOwnedResumeOutcomes(
1909
+ restoredMessages,
1910
+ pendingResume.assistant,
1911
+ recoveredResults,
1912
+ )
1913
+ : restoredMessages,
1914
+ params.sandboxProvider !== undefined,
1915
+ )
1916
+ } catch (err: unknown) {
1917
+ // A ledger that could not be rebuilt is the empty one every resume
1918
+ // used to get, so the turn continues without its witnesses and the
1919
+ // model reads what it needs. Failing the resume over it would trade
1920
+ // a conversation that works for one that does not, to protect an
1921
+ // optimisation. Said out loud all the same, because a seeding that
1922
+ // failed and one that found nothing are otherwise the same silence.
1923
+ ctx.log.debug('Could not rebuild the file observation ledger on resume', {
1924
+ [NAMZU.TURN_ID]: ctx.recorder.turnId,
1925
+ 'namzu.checkpoint.id': checkpoint.id,
1926
+ 'exception.message': err instanceof Error ? err.message : String(err),
1927
+ })
1928
+ }
1929
+
1930
+ for (const msg of restoredMessages) {
1931
+ if (msg.role === 'system') {
1932
+ // Re-push the FRESH static/dynamic floor (done above) but PRESERVE
1933
+ // the two system messages that carry irreplaceable run state: the
1934
+ // `[COMPACTED CONTEXT]` summary is the only surviving record of the
1935
+ // older history a compaction pass deleted, and the working-memory
1936
+ // slot pins the produced-artifact ledger. Dropping every system
1937
+ // message on restore silently lost both on resume.
1938
+ if (isCompactionMessage(msg.content) || isWorkingMemoryMessage(msg.content)) {
1939
+ pushRestored(msg, checkpoint.messageIds)
1940
+ }
1941
+ continue
1849
1942
  }
1850
- continue
1943
+ pushRestored(msg, checkpoint.messageIds)
1851
1944
  }
1852
- ctx.runMgr.pushMessage(msg)
1853
- }
1854
1945
 
1855
- // The queue, on the resume path too. It is drained
1856
- // unconditionally above, so leaving this out would take a
1857
- // host's "start with this" off the record and deliver it
1858
- // nowhere — the one outcome a durable queue must not have.
1859
- //
1860
- // AFTER the restored history rather than before it: on a
1861
- // resume the conversation already exists, and a message left
1862
- // for "the next run" is the newest thing said, not the oldest.
1863
- for (const queued of queuedForThisRun) ctx.runMgr.pushMessage(queued)
1864
- } else if (params.continuationMode) {
1865
- for (const msg of initialMessages) {
1866
- ctx.runMgr.pushMessage(msg)
1867
- }
1868
- } else {
1869
- pushSystemMessages()
1870
- for (const msg of initialMessages) {
1871
- if (msg.role === 'system') {
1872
- // A fresh run rebuilds its current static/dynamic prompt above,
1873
- // so arbitrary historical system messages stay out. These two
1874
- // are different: they are conversation STATE, and dropping them
1875
- // deletes the only surviving record of compacted history or the
1876
- // produced-artifact ledger. A compaction summary arriving from a
1877
- // prior run is pinned because this new WorkingStateManager cannot
1878
- // prove it has reconstructed equivalent state yet.
1879
- if (isCompactionMessage(msg.content)) {
1880
- ctx.runMgr.pushMessage({ ...msg, retain: true })
1881
- } else if (isWorkingMemoryMessage(msg.content)) {
1882
- ctx.runMgr.pushMessage(msg)
1946
+ // The queue, on the resume path too. It is drained
1947
+ // unconditionally above, so leaving this out would take a
1948
+ // host's "start with this" off the record and deliver it
1949
+ // nowhere — the one outcome a durable queue must not have.
1950
+ //
1951
+ // AFTER the restored history rather than before it: on a
1952
+ // resume the conversation already exists, and a message left
1953
+ // for "the next turn" is the newest thing said, not the oldest.
1954
+ for (const queued of queuedForThisRun) ctx.recorder.pushMessage(queued)
1955
+ } else if (params.continuationMode) {
1956
+ for (const msg of initialMessages) pushRestored(msg, historyIds)
1957
+ } else {
1958
+ pushSystemMessages()
1959
+ for (const msg of initialMessages) {
1960
+ if (msg.role === 'system') {
1961
+ // A fresh turn rebuilds its current static/dynamic prompt above,
1962
+ // so arbitrary historical system messages stay out. These two
1963
+ // are different: they are conversation STATE, and dropping them
1964
+ // deletes the only surviving record of compacted history or the
1965
+ // produced-artifact ledger. A compaction summary arriving from a
1966
+ // prior turn is pinned because this new WorkingStateManager cannot
1967
+ // prove it has reconstructed equivalent state yet.
1968
+ if (isCompactionMessage(msg.content)) {
1969
+ // Pinned by the prelude already; a copy would lose its record id.
1970
+ pushRestored(msg.retain ? msg : { ...msg, retain: true }, historyIds)
1971
+ } else if (isWorkingMemoryMessage(msg.content)) {
1972
+ pushRestored(msg, historyIds)
1973
+ }
1974
+ continue
1883
1975
  }
1884
- continue
1976
+ pushRestored(msg, historyIds)
1885
1977
  }
1886
- ctx.runMgr.pushMessage(msg)
1887
1978
  }
1888
- }
1889
- // Fresh and continuation histories seed the same operator state.
1890
- // A worker report or project-policy message may have role `user`,
1891
- // but it must not become the task or an operator requirement.
1892
- // Resume restores this state and adopts only its newer queue arrivals.
1893
- if (!params.resumeFromCheckpoint && workingStateManager) {
1894
- let isFirstUserMessage = true
1895
- for (const message of initialMessages) {
1896
- if (!isOperatorUserMessage(message) || !message.content.trim()) continue
1897
- extractFromUserMessage(workingStateManager, message.content, isFirstUserMessage)
1898
- isFirstUserMessage = false
1979
+ // Fresh and continuation histories seed the same operator state.
1980
+ // A worker report or project-policy message may have role `user`,
1981
+ // but it must not become the task or an operator requirement.
1982
+ // Resume restores this state and adopts only its newer queue arrivals.
1983
+ if (!params.resumeFromCheckpoint && workingStateManager) {
1984
+ let isFirstUserMessage = true
1985
+ for (const message of initialMessages) {
1986
+ if (!isOperatorUserMessage(message) || !message.content.trim()) continue
1987
+ extractFromUserMessage(workingStateManager, message.content, isFirstUserMessage)
1988
+ isFirstUserMessage = false
1989
+ }
1899
1990
  }
1900
- }
1901
-
1902
- const assembledPrompt =
1903
- segments.dynamic.length > 0
1904
- ? `${segments.static}\n\n---\n\n${segments.dynamic}`
1905
- : segments.static
1906
-
1907
- ctx.runMgr.markRunning()
1908
- await eventTranslator.emitEvent({
1909
- type: 'run_started',
1910
- runId: ctx.runMgr.id,
1911
- systemPrompt: assembledPrompt,
1912
- })
1913
- yield* eventTranslator.drainPending()
1914
-
1915
- // Pre-run materialization can observe cancellation before RunContext
1916
- // exists. The exact input has now been seeded and the run is writable;
1917
- // hand the cancellation to the normal terminal path before invoking
1918
- // any host callback, guardrail, plugin, sandbox, or provider. Those
1919
- // boundaries are not all cooperative and must not regain withdrawn
1920
- // authority merely because the run record still had to be created.
1921
- ctx.abortController.signal.throwIfAborted()
1922
-
1923
- // Handed over here, and the position is load-bearing in three
1924
- // directions. It has to follow `wirePlanManager`, or a host that
1925
- // builds its plan in this callback does it into silence. It has to
1926
- // follow `runMgr.init()` and `run_started`, because plan events append
1927
- // to that durable run. It also has to follow the pre-model abort fence:
1928
- // a callback invoked after attachment resolution observed cancellation
1929
- // would regain withdrawn authority and could replace the cancellation
1930
- // with its own failure. This is still before the iteration loop, which
1931
- // is the guarantee the callback makes.
1932
- params.onContextCreated?.({ planManager: ctx.planManager })
1933
-
1934
- // The box is handed out HERE, after `run_started`, and the position
1935
- // is load-bearing rather than tidy. It moved twice:
1936
- //
1937
- // 1. Beside the box's construction — a host that called `set`
1938
- // synchronously reached `eventTranslator` inside its temporal
1939
- // dead zone and killed the run before it started.
1940
- // 2. Beside the translator's construction — the translator existed,
1941
- // but the run directory did not, so the durable append hit
1942
- // ENOENT on `transcript.jsonl`.
1943
- //
1944
- // Both were found by the test that takes the box and immediately
1945
- // swaps the policy, which is not an exotic host: it is the shape of
1946
- // "start unattended" wiring. A policy change is durably recorded
1947
- // before it takes effect, so the handout cannot precede the run
1948
- // being writable.
1949
- params.onApprovalPolicy?.(approvalPolicy)
1950
-
1951
- // History repair happens before the run manager sees the first model
1952
- // request, but its durable event cannot precede run_started: there is no
1953
- // writable run log until that event initializes it. Emit the measured
1954
- // counts here, still before any provider call, so hosts can tell that the
1955
- // model received a repaired projection rather than the raw history.
1956
- for (const repair of pendingHistoryRepairs) {
1957
- await eventTranslator.emitEvent({
1958
- type: 'message_history_repaired',
1959
- runId: ctx.runMgr.id,
1960
- source: repair.source,
1961
- ...repair.report,
1962
- })
1963
- yield* eventTranslator.drainPending()
1964
- }
1965
1991
 
1966
- // Surface capability degradation to the host as run events —
1967
- // explicit, not silent (the log.warn above fires at setup time;
1968
- // this is the machine-readable channel).
1969
- if (stripToolSurfaces) {
1970
- await eventTranslator.emitEvent({
1971
- type: 'capability_warning',
1972
- runId: ctx.runMgr.id,
1973
- capability: 'tools',
1974
- providerId: params.provider.id,
1975
- message: `Provider '${params.provider.id}' does not support tools — ${registeredToolCount} registered tool(s) were stripped from the prompt and request.`,
1976
- })
1977
- yield* eventTranslator.drainPending()
1978
- }
1979
- if (attachmentMessageCount > 0) {
1980
- await eventTranslator.emitEvent({
1981
- type: 'capability_warning',
1982
- runId: ctx.runMgr.id,
1983
- capability: 'vision',
1984
- providerId: params.provider.id,
1985
- message: `Provider '${params.provider.id}' does not support vision — image attachments on ${attachmentMessageCount} user message(s) will not reach the model.`,
1986
- })
1987
- yield* eventTranslator.drainPending()
1988
- }
1989
- if (documentMessageCount > 0) {
1990
- await eventTranslator.emitEvent({
1991
- type: 'capability_warning',
1992
- runId: ctx.runMgr.id,
1993
- capability: 'documents',
1994
- providerId: params.provider.id,
1995
- message: `Provider '${params.provider.id}' does not support documents — document attachments on ${documentMessageCount} user message(s) will not reach the model.`,
1996
- })
1992
+ const assembledPrompt =
1993
+ segments.dynamic.length > 0
1994
+ ? `${segments.static}\n\n---\n\n${segments.dynamic}`
1995
+ : segments.static
1996
+
1997
+ ctx.recorder.markRunning()
1998
+ // A resumed turn already began; `turn_resuming` above continued it.
1999
+ if (!params.resumeFromCheckpoint) {
2000
+ await eventTranslator.beginTurn({
2001
+ systemPrompt: assembledPrompt,
2002
+ ...(params.origin ? { origin: params.origin } : {}),
2003
+ ...(params.abandonInterrupted ? { abandonInterrupted: true } : {}),
2004
+ })
2005
+ }
1997
2006
  yield* eventTranslator.drainPending()
1998
- }
1999
2007
 
2000
- if (params.pluginManager) {
2001
- const hookResults = await params.pluginManager.executeHooks(
2002
- 'run_start',
2003
- { runId: ctx.runId, signal: ctx.abortController.signal },
2004
- eventTranslator.emitEvent,
2005
- )
2006
- applyLifecycleHookResults('run_start', hookResults)
2007
- yield* eventTranslator.drainPending()
2008
- }
2008
+ // Pre-run materialization can observe cancellation before TurnContext
2009
+ // exists. The exact input has now been seeded and the turn is writable;
2010
+ // hand the cancellation to the normal terminal path before invoking
2011
+ // any host callback, guardrail, plugin, sandbox, or provider. Those
2012
+ // boundaries are not all cooperative and must not regain withdrawn
2013
+ // authority merely because the turn record still had to be created.
2014
+ ctx.abortController.signal.throwIfAborted()
2015
+
2016
+ // Handed over here, and the position is load-bearing in three
2017
+ // directions. It has to follow `wirePlanManager`, or a host that
2018
+ // builds its plan in this callback does it into silence. It has to
2019
+ // follow `recorder.init()` and `turn_started`, because plan events append
2020
+ // to that durable turn. It also has to follow the pre-model abort fence:
2021
+ // a callback invoked after attachment resolution observed cancellation
2022
+ // would regain withdrawn authority and could replace the cancellation
2023
+ // with its own failure. This is still before the iteration loop, which
2024
+ // is the guarantee the callback makes.
2025
+ params.onContextCreated?.({ planManager: ctx.planManager })
2026
+
2027
+ // The box is handed out HERE, after `turn_started`, and the position
2028
+ // is load-bearing rather than tidy. It moved twice:
2029
+ //
2030
+ // 1. Beside the box's construction — a host that called `set`
2031
+ // synchronously reached `eventTranslator` inside its temporal
2032
+ // dead zone and killed the turn before it started.
2033
+ // 2. Beside the translator's construction — the translator existed,
2034
+ // but the turn directory did not, so the durable append hit
2035
+ // ENOENT on `transcript.jsonl`.
2036
+ //
2037
+ // Both were found by the test that takes the box and immediately
2038
+ // swaps the policy, which is not an exotic host: it is the shape of
2039
+ // "start unattended" wiring. A policy change is durably recorded
2040
+ // before it takes effect, so the handout cannot precede the turn
2041
+ // being writable.
2042
+ params.onApprovalPolicy?.(approvalPolicy)
2043
+
2044
+ // History repair happens before the turn manager sees the first model
2045
+ // request, but its durable event cannot precede turn_started: there is no
2046
+ // writable run log until that event initializes it. Emit the measured
2047
+ // counts here, still before any provider call, so hosts can tell that the
2048
+ // model received a repaired projection rather than the raw history.
2049
+ for (const repair of pendingHistoryRepairs) {
2050
+ await eventTranslator.emitEvent({
2051
+ type: 'message_history_repaired',
2052
+ turnId: ctx.recorder.turnId,
2053
+ source: repair.source,
2054
+ ...repair.report,
2055
+ })
2056
+ yield* eventTranslator.drainPending()
2057
+ }
2009
2058
 
2010
- // --- Sandbox lifecycle: create before iteration loop ---
2011
- if (params.sandboxProvider) {
2012
- const rootAtCwd = runConfig.sandbox?.workspace === 'working-directory'
2013
- // Checked against what the CALLER passed, not against `ctx.cwd`.
2014
- // `ctx.cwd` falls back to `process.cwd()`, so reading it here
2015
- // would silently root the sandbox at whatever directory the
2016
- // host process happens to be in — which is not the directory
2017
- // anybody asked to confine, and is worse than the temp dir the
2018
- // caller declined. Refused before the sandbox exists, and not
2019
- // downgraded to ephemeral: a caller who asked for confinement
2020
- // of a specific tree and quietly got an empty one has been
2021
- // told their files are protected by something that is not
2022
- // looking at them.
2023
- if (rootAtCwd && params.workingDirectory === undefined) {
2024
- throw new NamzuError({
2025
- code: 'invalid_config',
2026
- message:
2027
- "sandbox.workspace is 'working-directory' but this run has no workingDirectory. Pass one, or use the default 'ephemeral' — the kernel will not fall back to a temp directory, because that would confine a directory you did not name.",
2028
- details: { workspace: 'working-directory' },
2059
+ // Surface capability degradation to the host as run events —
2060
+ // explicit, not silent (the log.warn above fires at setup time;
2061
+ // this is the machine-readable channel).
2062
+ if (stripToolSurfaces) {
2063
+ await eventTranslator.emitEvent({
2064
+ type: 'capability_warning',
2065
+ turnId: ctx.recorder.turnId,
2066
+ capability: 'tools',
2067
+ providerId: params.provider.id,
2068
+ message: `Provider '${params.provider.id}' does not support tools — ${registeredToolCount} registered tool(s) were stripped from the prompt and request.`,
2029
2069
  })
2070
+ yield* eventTranslator.drainPending()
2030
2071
  }
2031
- if (rootAtCwd && !params.sandboxProvider.workspaceModes?.includes('working-directory')) {
2032
- throw new NamzuError({
2033
- code: 'invalid_config',
2034
- message: `Sandbox provider '${params.sandboxProvider.id}' does not advertise working-directory workspace support. Refusing instead of passing a project path the provider may ignore.`,
2035
- details: {
2036
- providerId: params.sandboxProvider.id,
2037
- workspace: 'working-directory',
2038
- },
2072
+ if (attachmentMessageCount > 0) {
2073
+ await eventTranslator.emitEvent({
2074
+ type: 'capability_warning',
2075
+ turnId: ctx.recorder.turnId,
2076
+ capability: 'vision',
2077
+ providerId: params.provider.id,
2078
+ message: `Provider '${params.provider.id}' does not support vision — image attachments on ${attachmentMessageCount} user message(s) will not reach the model.`,
2039
2079
  })
2080
+ yield* eventTranslator.drainPending()
2040
2081
  }
2041
- const acquisition = await acquireSandbox({
2042
- provider: params.sandboxProvider,
2043
- config: {
2044
- ...(rootAtCwd ? { workingDirectory: ctx.cwd } : {}),
2045
- ...(rootAtCwd && params.additionalDirectories?.length
2046
- ? { additionalDirectories: params.additionalDirectories }
2047
- : {}),
2048
- timeoutMs: runConfig.sandbox?.timeoutMs,
2049
- memoryLimitMb: runConfig.sandbox?.memoryLimitMb,
2050
- maxProcesses: runConfig.sandbox?.maxProcesses,
2051
- },
2052
- signal: ctx.abortController.signal,
2053
- timeoutMs: guard.remainingUntilTimeoutMs(),
2054
- teardownTimeoutMs: sandboxTeardownTimeoutMs,
2055
- onLateTeardown: (result) => {
2056
- if (result.kind === 'destroyed') {
2057
- ctx.log.info('Late sandbox allocation was destroyed after the run stopped', {
2058
- [NAMZU.RUN_ID]: ctx.runId,
2059
- })
2060
- return
2061
- }
2062
- ctx.log.error('Late sandbox allocation did not stop cleanly', {
2063
- [NAMZU.RUN_ID]: ctx.runId,
2064
- ...errorAttributes(result.error),
2082
+ if (documentMessageCount > 0) {
2083
+ await eventTranslator.emitEvent({
2084
+ type: 'capability_warning',
2085
+ turnId: ctx.recorder.turnId,
2086
+ capability: 'documents',
2087
+ providerId: params.provider.id,
2088
+ message: `Provider '${params.provider.id}' does not support documents — document attachments on ${documentMessageCount} user message(s) will not reach the model.`,
2089
+ })
2090
+ yield* eventTranslator.drainPending()
2091
+ }
2092
+
2093
+ if (params.pluginManager) {
2094
+ const hookResults = await params.pluginManager.executeHooks(
2095
+ 'turn_start',
2096
+ { sessionId: ctx.sessionId, turnId: ctx.turnId, signal: ctx.abortController.signal },
2097
+ eventTranslator.emitEvent,
2098
+ )
2099
+ applyLifecycleHookResults('turn_start', hookResults)
2100
+ yield* eventTranslator.drainPending()
2101
+ }
2102
+
2103
+ // --- Sandbox lifecycle: create before iteration loop ---
2104
+ if (params.sandboxProvider) {
2105
+ const rootAtCwd = turnConfig.sandbox?.workspace === 'working-directory'
2106
+ // Checked against what the CALLER passed, not against `ctx.cwd`.
2107
+ // `ctx.cwd` falls back to `process.cwd()`, so reading it here
2108
+ // would silently root the sandbox at whatever directory the
2109
+ // host process happens to be in — which is not the directory
2110
+ // anybody asked to confine, and is worse than the temp dir the
2111
+ // caller declined. Refused before the sandbox exists, and not
2112
+ // downgraded to ephemeral: a caller who asked for confinement
2113
+ // of a specific tree and quietly got an empty one has been
2114
+ // told their files are protected by something that is not
2115
+ // looking at them.
2116
+ if (rootAtCwd && params.workingDirectory === undefined) {
2117
+ throw new NamzuError({
2118
+ code: 'invalid_config',
2119
+ message:
2120
+ "sandbox.workspace is 'working-directory' but this turn has no workingDirectory. Pass one, or use the default 'ephemeral' — the kernel will not fall back to a temp directory, because that would confine a directory you did not name.",
2121
+ details: { workspace: 'working-directory' },
2065
2122
  })
2066
- },
2067
- })
2068
- if (acquisition.kind !== 'created') {
2069
- if (acquisition.createPending) {
2070
- ctx.log.warn(
2071
- 'Sandbox creation was unsettled when the run stopped; any returned handle will be released, but a remote allocation hidden behind a lost response requires provider-side reconciliation or a fleet reaper',
2072
- {
2073
- [NAMZU.RUN_ID]: ctx.runId,
2074
- 'namzu.sandbox.provider_id': params.sandboxProvider.id,
2075
- },
2076
- )
2077
2123
  }
2078
- if (acquisition.kind === 'cancelled') {
2079
- ctx.runMgr.markCancelled()
2080
- } else {
2081
- ctx.runMgr.setStopReason('timeout')
2082
- ctx.log.warn('Sandbox creation exhausted the run timeout', {
2083
- [NAMZU.RUN_ID]: ctx.runId,
2084
- 'namzu.sandbox.provider_id': params.sandboxProvider.id,
2085
- ...errorAttributes(acquisition.error),
2124
+ if (rootAtCwd && !params.sandboxProvider.workspaceModes?.includes('working-directory')) {
2125
+ throw new NamzuError({
2126
+ code: 'invalid_config',
2127
+ message: `Sandbox provider '${params.sandboxProvider.id}' does not advertise working-directory workspace support. Refusing instead of passing a project path the provider may ignore.`,
2128
+ details: {
2129
+ providerId: params.sandboxProvider.id,
2130
+ workspace: 'working-directory',
2131
+ },
2086
2132
  })
2087
2133
  }
2088
- yield* resultAssembler.completeRun(rootSpan)
2089
- // The run HAS settled, so the outer `finally` must not read
2090
- // this as an abandonment — it would persist a second time.
2134
+ const acquisition = await acquireSandbox({
2135
+ provider: params.sandboxProvider,
2136
+ config: {
2137
+ ...(rootAtCwd ? { workingDirectory: ctx.cwd } : {}),
2138
+ ...(rootAtCwd && params.additionalDirectories?.length
2139
+ ? { additionalDirectories: params.additionalDirectories }
2140
+ : {}),
2141
+ timeoutMs: turnConfig.sandbox?.timeoutMs,
2142
+ memoryLimitMb: turnConfig.sandbox?.memoryLimitMb,
2143
+ maxProcesses: turnConfig.sandbox?.maxProcesses,
2144
+ },
2145
+ signal: ctx.abortController.signal,
2146
+ timeoutMs: guard.remainingUntilTimeoutMs(),
2147
+ teardownTimeoutMs: sandboxTeardownTimeoutMs,
2148
+ onLateTeardown: (result) => {
2149
+ if (result.kind === 'destroyed') {
2150
+ ctx.log.info('Late sandbox allocation was destroyed after the turn stopped', {
2151
+ [NAMZU.TURN_ID]: ctx.turnId,
2152
+ })
2153
+ return
2154
+ }
2155
+ ctx.log.error('Late sandbox allocation did not stop cleanly', {
2156
+ [NAMZU.TURN_ID]: ctx.turnId,
2157
+ ...errorAttributes(result.error),
2158
+ })
2159
+ },
2160
+ })
2161
+ if (acquisition.kind !== 'created') {
2162
+ if (acquisition.createPending) {
2163
+ ctx.log.warn(
2164
+ 'Sandbox creation was unsettled when the turn stopped; any returned handle will be released, but a remote allocation hidden behind a lost response requires provider-side reconciliation or a fleet reaper',
2165
+ {
2166
+ [NAMZU.TURN_ID]: ctx.turnId,
2167
+ 'namzu.sandbox.provider_id': params.sandboxProvider.id,
2168
+ },
2169
+ )
2170
+ }
2171
+ if (acquisition.kind === 'cancelled') {
2172
+ ctx.recorder.markCancelled()
2173
+ } else {
2174
+ ctx.recorder.setStopReason('timeout')
2175
+ ctx.log.warn('Sandbox creation exhausted the turn timeout', {
2176
+ [NAMZU.TURN_ID]: ctx.turnId,
2177
+ 'namzu.sandbox.provider_id': params.sandboxProvider.id,
2178
+ ...errorAttributes(acquisition.error),
2179
+ })
2180
+ }
2181
+ yield* resultAssembler.completeTurn(rootSpan)
2182
+ // The turn HAS settled, so the outer `finally` must not read
2183
+ // this as an abandonment — it would persist a second time.
2184
+ settled = true
2185
+ return await resultAssembler.finalize()
2186
+ }
2187
+ sandbox = acquisition.sandbox
2188
+ toolExecutor.setSandbox(sandbox)
2189
+
2190
+ await eventTranslator.emitEvent({
2191
+ type: 'sandbox_created',
2192
+ turnId: ctx.turnId,
2193
+ sandboxId: sandbox.id,
2194
+ environment: sandbox.environment,
2195
+ })
2196
+ yield* eventTranslator.drainPending()
2197
+
2198
+ ctx.log.info('Sandbox created for run', {
2199
+ 'namzu.sandbox.id': sandbox.id,
2200
+ 'namzu.execution.environment': sandbox.environment,
2201
+ 'namzu.runtime.root_dir': sandbox.rootDir,
2202
+ })
2203
+ }
2204
+
2205
+ // Before the first model call: the cheapest place to refuse, since
2206
+ // nothing has been spent. Previously unreachable — `turn_start`
2207
+ // fires with only `{ sessionId, turnId }` and `turn_started` carries only the
2208
+ // system prompt, so no hook could see the user's message.
2209
+ const inputVerdict = await runInputGuardrails(
2210
+ params.inputGuardrails,
2211
+ {
2212
+ sessionId: ctx.sessionId,
2213
+ turnId: ctx.turnId,
2214
+ messages: ctx.recorder.messages,
2215
+ ...(segments?.static ? { systemPrompt: segments.static } : {}),
2216
+ },
2217
+ ctx.log,
2218
+ )
2219
+ if (inputVerdict.blocked) {
2220
+ await eventTranslator.emitEvent({
2221
+ type: 'guardrail_triggered',
2222
+ turnId: ctx.turnId,
2223
+ stage: 'input',
2224
+ action: 'block',
2225
+ ...(inputVerdict.name ? { guardrail: inputVerdict.name } : {}),
2226
+ ...(inputVerdict.reason ? { reason: inputVerdict.reason } : {}),
2227
+ })
2228
+ yield* eventTranslator.drainPending()
2229
+ // A guardrail block is a refusal — first-class in the audit trail
2230
+ // (LOG-14, design §5), not merely a SessionEvent a host happens to be
2231
+ // subscribed to when it fires.
2232
+ await ctx.recorder.recordAudit({
2233
+ what: { action: 'guardrail:input', resource: inputVerdict.name },
2234
+ outcome: 'refused',
2235
+ reason: inputVerdict.reason ?? 'blocked by an input guardrail',
2236
+ ...(params.persona?.identity.role ? { persona: params.persona.identity.role } : {}),
2237
+ })
2238
+ ctx.recorder.setStopReason('input_guardrail')
2239
+ ctx.recorder.setLastError(inputVerdict.reason ?? 'blocked by an input guardrail')
2240
+ yield* resultAssembler.completeTurn(rootSpan)
2241
+ // Same two lines as the sandbox path above, and for the same
2242
+ // reasons — with one that path does not have. This return used to
2243
+ // hand back `getRun()` without persisting, so the terminal state
2244
+ // reached the disk only because the abandonment path found
2245
+ // `settled` false and settled it a second time. A branch that
2246
+ // exists for runs which did NOT settle must not be the reason a
2247
+ // settled one is written down.
2091
2248
  settled = true
2092
2249
  return await resultAssembler.finalize()
2093
2250
  }
2094
- sandbox = acquisition.sandbox
2095
- toolExecutor.setSandbox(sandbox)
2096
-
2097
- await eventTranslator.emitEvent({
2098
- type: 'sandbox_created',
2099
- runId: ctx.runId,
2100
- sandboxId: sandbox.id,
2101
- environment: sandbox.environment,
2102
- })
2103
- yield* eventTranslator.drainPending()
2104
2251
 
2105
- ctx.log.info('Sandbox created for run', {
2106
- 'namzu.sandbox.id': sandbox.id,
2107
- 'namzu.execution.environment': sandbox.environment,
2108
- 'namzu.runtime.root_dir': sandbox.rootDir,
2109
- })
2110
- }
2252
+ // Honor the approval a human already gave, before the loop's
2253
+ // first model call. The sandbox exists by now, so an approved
2254
+ // tool that needs one gets it.
2255
+ if (pendingResume) {
2256
+ ctx.log.info('Applying a pending HITL decision to the checkpointed tool calls', {
2257
+ [NAMZU.TURN_ID]: ctx.turnId,
2258
+ 'namzu.tool.names': pendingResume.response.message.toolCalls?.map(
2259
+ (tc) => tc.function.name,
2260
+ ),
2261
+ 'namzu.runtime.denied': pendingResume.denials.size,
2262
+ })
2263
+ // Hand the recorded answer to the already-built tool. The tool
2264
+ // closed over its registry when the agent was constructed,
2265
+ // long before this turn existed, so the answers are copied in
2266
+ // rather than passed down.
2267
+ if (pendingResume.answers) {
2268
+ for (const [questionId, answer] of pendingResume.answers.entries()) {
2269
+ pendingAnswers.set(questionId, answer)
2270
+ }
2271
+ }
2111
2272
 
2112
- // Crash-save handlers live for exactly the run's lifetime, and are
2113
- // removed in the `finally` below. Opt-in — see `emergencySave`.
2114
- if (params.emergencySave) {
2115
- const runDir = ctx.runMgr.getRunDir()
2116
- if (runDir) {
2117
- emergencyManager = EmergencySaveManager.instance(ctx.log)
2118
- emergencyManager.attach(ctx.runMgr, runDir, ctx.log)
2119
- } else {
2120
- ctx.log.warn(
2121
- 'emergencySave requested but the run has no output directory — crash dumps disabled',
2122
- { [NAMZU.RUN_ID]: ctx.runId },
2273
+ await applyPendingResume(
2274
+ pendingResume,
2275
+ ctx.recorder,
2276
+ toolExecutor,
2277
+ recoveredResults,
2278
+ pendingResumeAssistantId,
2123
2279
  )
2280
+ yield* eventTranslator.drainPending()
2124
2281
  }
2125
- }
2126
2282
 
2127
- // Before the first model call: the cheapest place to refuse, since
2128
- // nothing has been spent. Previously unreachable — `run_start`
2129
- // fires with only `{ runId }` and `run_started` carries only the
2130
- // system prompt, so no hook could see the user's message.
2131
- const inputVerdict = await runInputGuardrails(
2132
- params.inputGuardrails,
2133
- {
2134
- runId: ctx.runId,
2135
- messages: ctx.runMgr.messages,
2136
- ...(segments?.static ? { systemPrompt: segments.static } : {}),
2137
- },
2138
- ctx.log,
2139
- )
2140
- if (inputVerdict.blocked) {
2141
- await eventTranslator.emitEvent({
2142
- type: 'guardrail_triggered',
2143
- runId: ctx.runId,
2144
- stage: 'input',
2145
- action: 'block',
2146
- ...(inputVerdict.name ? { guardrail: inputVerdict.name } : {}),
2147
- ...(inputVerdict.reason ? { reason: inputVerdict.reason } : {}),
2148
- })
2149
- yield* eventTranslator.drainPending()
2150
- // A guardrail block is a refusal — first-class in the audit trail
2151
- // (LOG-14, design §5), not merely a RunEvent a host happens to be
2152
- // subscribed to when it fires.
2153
- await ctx.runMgr.recordAudit({
2154
- what: { action: 'guardrail:input', resource: inputVerdict.name },
2155
- outcome: 'refused',
2156
- reason: inputVerdict.reason ?? 'blocked by an input guardrail',
2157
- ...(params.persona?.identity.role ? { persona: params.persona.identity.role } : {}),
2158
- })
2159
- ctx.runMgr.setStopReason('input_guardrail')
2160
- ctx.runMgr.setLastError(inputVerdict.reason ?? 'blocked by an input guardrail')
2161
- yield* resultAssembler.completeRun(rootSpan)
2162
- // Same two lines as the sandbox path above, and for the same
2163
- // reasons — with one that path does not have. This return used to
2164
- // hand back `getRun()` without persisting, so the terminal state
2165
- // reached the disk only because the abandonment path found
2166
- // `settled` false and settled it a second time. A branch that
2167
- // exists for runs which did NOT settle must not be the reason a
2168
- // settled one is written down.
2169
- settled = true
2170
- return await resultAssembler.finalize()
2171
- }
2172
-
2173
- // Honor the approval a human already gave, before the loop's
2174
- // first model call. The sandbox exists by now, so an approved
2175
- // tool that needs one gets it.
2176
- if (pendingResume) {
2177
- ctx.log.info('Applying a pending HITL decision to the checkpointed tool calls', {
2178
- [NAMZU.RUN_ID]: ctx.runId,
2179
- 'namzu.tool.names': pendingResume.response.message.toolCalls?.map(
2180
- (tc) => tc.function.name,
2181
- ),
2182
- 'namzu.runtime.denied': pendingResume.denials.size,
2183
- })
2184
- // Hand the recorded answer to the already-built tool. The tool
2185
- // closed over its registry when the agent was constructed,
2186
- // long before this run existed, so the answers are copied in
2187
- // rather than passed down.
2188
- if (pendingResume.answers) {
2189
- for (const [questionId, answer] of pendingResume.answers.entries()) {
2190
- pendingAnswers.set(questionId, answer)
2191
- }
2283
+ // The decision has now actually been carried out, so the park it
2284
+ // answered is no longer outstanding. Without this the checkpoint
2285
+ // keeps reporting `pending` with no `resolvedAt`, and an approval
2286
+ // queue re-serves a call that already ran — or a question already
2287
+ // answered — which defeats the entire point of recording the park.
2288
+ //
2289
+ // Two arms reach this point, and being outside `if (pendingResume)`
2290
+ // is what the second one needs. One is a plan whose decision was
2291
+ // applied to a batch above. The other is the cadence arm, for which
2292
+ // `planPendingResume` rightly produces no plan because the loop
2293
+ // resuming IS its decision being carried out (`answeredParkId`, set
2294
+ // on the restore path). Resolving only the first left a finished turn
2295
+ // reporting `awaiting-decision` forever.
2296
+ //
2297
+ // What is RECORDED depends on which of the two produced the plan. A
2298
+ // recovery plan means the batch was answered by the crash path
2299
+ // rather than by the decision — the calls the human was asked about
2300
+ // were closed with explicitly unknown outcomes — so the human's
2301
+ // answer must not be written down as what ended the park. The park is
2302
+ // still resolved: the question is moot, and leaving it outstanding
2303
+ // would have `findPendingCheckpoint` serve it as the newest
2304
+ // outstanding park, so a host resuming it would rewind this turn to
2305
+ // the checkpoint the crash happened on and re-execute a batch the turn
2306
+ // has long since moved past.
2307
+ const resolvedCheckpointId = pendingResume?.checkpointId ?? answeredParkId
2308
+ const recordedDecision =
2309
+ pendingResume?.source === 'recovery' && params.pendingDecision
2310
+ ? supersededByRecovery(params.pendingDecision)
2311
+ : params.pendingDecision
2312
+ if (recordedDecision && resolvedCheckpointId) {
2313
+ await checkpointMgr
2314
+ .unpark(resolvedCheckpointId, recordedDecision)
2315
+ .catch((err: unknown) => {
2316
+ ctx.log.error('Applied a pending decision but failed to clear the park', {
2317
+ [NAMZU.TURN_ID]: ctx.turnId,
2318
+ 'namzu.checkpoint.id': resolvedCheckpointId,
2319
+ 'exception.message': err instanceof Error ? err.message : String(err),
2320
+ })
2321
+ return null
2322
+ })
2192
2323
  }
2193
2324
 
2194
- await applyPendingResume(pendingResume, ctx.runMgr, toolExecutor, recoveredResults)
2195
- yield* eventTranslator.drainPending()
2196
- }
2325
+ yield* iterationOrchestrator.runLoop()
2197
2326
 
2198
- // The decision has now actually been carried out, so the park it
2199
- // answered is no longer outstanding. Without this the checkpoint
2200
- // keeps reporting `pending` with no `resolvedAt`, and an approval
2201
- // queue re-serves a call that already ran — or a question already
2202
- // answered — which defeats the entire point of recording the park.
2203
- //
2204
- // Two arms reach this point, and being outside `if (pendingResume)`
2205
- // is what the second one needs. One is a plan whose decision was
2206
- // applied to a batch above. The other is the cadence arm, for which
2207
- // `planPendingResume` rightly produces no plan because the loop
2208
- // resuming IS its decision being carried out (`answeredParkId`, set
2209
- // on the restore path). Resolving only the first left a finished run
2210
- // reporting `awaiting-decision` forever.
2211
- //
2212
- // What is RECORDED depends on which of the two produced the plan. A
2213
- // recovery plan means the batch was answered by the crash path
2214
- // rather than by the decision — the calls the human was asked about
2215
- // were closed with explicitly unknown outcomes — so the human's
2216
- // answer must not be written down as what ended the park. The park is
2217
- // still resolved: the question is moot, and leaving it outstanding
2218
- // would have `findPendingCheckpoint` serve it as the newest
2219
- // outstanding park, so a host resuming it would rewind this run to
2220
- // the checkpoint the crash happened on and re-execute a batch the run
2221
- // has long since moved past.
2222
- const resolvedCheckpointId = pendingResume?.checkpointId ?? answeredParkId
2223
- const recordedDecision =
2224
- pendingResume?.source === 'recovery' && params.pendingDecision
2225
- ? supersededByRecovery(params.pendingDecision)
2226
- : params.pendingDecision
2227
- if (recordedDecision && resolvedCheckpointId) {
2228
- await checkpointMgr.unpark(resolvedCheckpointId, recordedDecision).catch((err: unknown) => {
2229
- ctx.log.error('Applied a pending decision but failed to clear the park', {
2230
- [NAMZU.RUN_ID]: ctx.runId,
2231
- 'namzu.checkpoint.id': resolvedCheckpointId,
2232
- 'exception.message': err instanceof Error ? err.message : String(err),
2233
- })
2234
- return null
2327
+ yield* finalizeTurn({
2328
+ ctx,
2329
+ params,
2330
+ eventTranslator,
2331
+ takeSteps: () => iterationOrchestrator.getSteps(),
2332
+ workingStateManager,
2333
+ resultAssembler,
2334
+ rootSpan,
2335
+ })
2336
+ } catch (err) {
2337
+ // Another turn is active in this session: nothing of this turn was
2338
+ // written, so there is nothing to settle. The caller gets the
2339
+ // refusal itself.
2340
+ if (isTurnInProgressError(err) && !ctx.recorder.isActive) throw err
2341
+ // A failed turn still spent its steps; report them.
2342
+ ctx.recorder.setSteps(iterationOrchestrator.getSteps())
2343
+ await executeUserInterruptHooks(err)
2344
+ yield* eventTranslator.drainPending()
2345
+ yield* resultAssembler.handleError(err, rootSpan)
2346
+ } finally {
2347
+ yield* releaseTurnResources({
2348
+ ctx,
2349
+ eventTranslator,
2350
+ unsubscribeJobExits,
2351
+ unsubscribeTaskStore,
2352
+ awaitedJobs,
2353
+ backgroundJobs: params.backgroundJobs,
2354
+ backgroundJobOwner: params.backgroundJobOwner,
2355
+ questionParks,
2356
+ workingStateManager,
2357
+ promoteMemory: params.promoteMemory,
2358
+ sandbox,
2359
+ sandboxTeardownTimeoutMs,
2360
+ runStartedAt,
2361
+ rootSpan,
2235
2362
  })
2236
2363
  }
2237
2364
 
2238
- yield* iterationOrchestrator.runLoop()
2365
+ // Reached only by a turn that settled on its own terms. `finalize()` is
2366
+ // the only thing in this body that writes the durable half of the turn,
2367
+ // and a `return` completion arriving from a consumer (`break` out of
2368
+ // `for await`, `gen.return()`) runs the `finally` above and stops short
2369
+ // of here. The flag is what tells the two apart, and this is one of
2370
+ // three sites that set it — the sandbox-acquisition and input-guardrail
2371
+ // returns settle early and set it there. Set before the await rather
2372
+ // than after, because a store that throws on the way out must not send
2373
+ // the abandonment path over the same broken ground.
2374
+ settled = true
2375
+ return await resultAssembler.finalize()
2376
+ })()
2239
2377
 
2240
- yield* finalizeRun({
2241
- ctx,
2242
- params,
2243
- eventTranslator,
2244
- takeSteps: () => iterationOrchestrator.getSteps(),
2245
- workingStateManager,
2246
- resultAssembler,
2247
- rootSpan,
2248
- })
2249
- } catch (err) {
2250
- // A failed run still spent its steps; report them.
2251
- ctx.runMgr.setSteps(iterationOrchestrator.getSteps())
2252
- await executeUserInterruptHooks(err)
2253
- yield* eventTranslator.drainPending()
2254
- yield* resultAssembler.handleError(err, rootSpan)
2378
+ try {
2379
+ return yield* runBody
2255
2380
  } finally {
2256
- yield* releaseRunResources({
2257
- ctx,
2258
- eventTranslator,
2259
- emergencyManager,
2260
- unsubscribeJobExits,
2261
- unsubscribeTaskStore,
2262
- awaitedJobs,
2263
- backgroundJobs: params.backgroundJobs,
2264
- backgroundJobOwner: params.backgroundJobOwner,
2265
- questionParks,
2266
- workingStateManager,
2267
- promoteMemory: params.promoteMemory,
2268
- sandbox,
2269
- sandboxTeardownTimeoutMs,
2270
- runStartedAt,
2271
- rootSpan,
2272
- })
2381
+ if (!settled) await settleAbandonedTurn(ctx.recorder, eventTranslator, ctx.log)
2273
2382
  }
2274
-
2275
- // Reached only by a run that settled on its own terms. `finalize()` is
2276
- // the only thing in this body that writes the durable half of the run,
2277
- // and a `return` completion arriving from a consumer (`break` out of
2278
- // `for await`, `gen.return()`) runs the `finally` above and stops short
2279
- // of here. The flag is what tells the two apart, and this is one of
2280
- // three sites that set it — the sandbox-acquisition and input-guardrail
2281
- // returns settle early and set it there. Set before the await rather
2282
- // than after, because a store that throws on the way out must not send
2283
- // the abandonment path over the same broken ground.
2284
- settled = true
2285
- return await resultAssembler.finalize()
2286
- })()
2287
-
2288
- try {
2289
- return yield* runBody
2290
2383
  } finally {
2291
- if (!settled) await settleAbandonedRun(ctx.runMgr, ctx.log)
2384
+ unsubscribeChildSessions?.()
2385
+ // The lease `open()` took in the prelude; a caller-supplied lease is the
2386
+ // caller's to give back.
2387
+ await ctx.recorder.release()
2292
2388
  }
2293
2389
  }
2294
2390
 
2295
2391
  /**
2296
- * Write a terminal durable record for a run whose consumer walked away.
2297
- *
2298
- * `for await (… ) break` and an explicit `gen.return()` both end the run
2299
- * body early. Everything the run's `finally` owns still happens — background
2300
- * jobs are killed, the sandbox is destroyed, the span ends, the duration is
2301
- * recorded — and then the generator stops. `finalize()` never runs, so
2302
- * `persist()` never runs, and the store keeps whatever `init()` wrote: a
2303
- * non-terminal status for a run that no longer exists. `deriveRunStatus`
2304
- * reads that record back as `queued`, work waiting to start, and a host
2305
- * rebuilding its view from the store believes it.
2392
+ * Write a durable record for a turn whose consumer walked away.
2306
2393
  *
2307
- * There is nothing to emit here and nothing to emit it to: the consumer
2308
- * that would have received the events is the one that left. This is about
2309
- * the durable record only.
2394
+ * `for await (… ) break` and an explicit `gen.return()` both end the turn
2395
+ * body early. Everything the body's `finally` owns still happens — jobs are
2396
+ * killed, the sandbox is destroyed, the span ends — and then the generator
2397
+ * stops without settling. Without this the log would end mid-turn, and the
2398
+ * turn would read as `interrupted` for a process that is gone.
2310
2399
  *
2311
- * `cancelled` is the verdict, and it is chosen from the existing vocabulary
2312
- * because it is the one that is true. The run did not complete — no result
2313
- * was produced and no terminal event was ever delivered — and nothing
2314
- * failed, so `failed` would name an error that never happened; a run whose
2315
- * consumer stopped reading and whose processes were torn down under it is
2316
- * the same fact `markCancelled` already records when a run abort tears one
2317
- * down. It needs no new `RunExecutionStatus` and no new `StopReason`.
2318
- *
2319
- * A verdict the run already reached is left standing. A run that failed,
2320
- * or was cancelled, before the consumer left still says so; what the
2321
- * abandonment adds is that the record reaches the disk at all.
2322
- *
2323
- * Neither is a verdict written over a PARK. A park is a promise to a human
2324
- * that outlives the consumer: the run is resumable and somebody is still owed
2325
- * an answer, and `deriveRunStatus` reads a terminal status BEFORE it reads the
2326
- * park — so recording `cancelled` turns `awaiting_hitl` into `cancelled` for a
2327
- * run nobody answered for, while the unanswered question stays on the record
2328
- * and the checkpoint it belongs to stays the place a resume starts from. The
2329
- * durable state is asked rather than the in-memory one because the in-memory
2330
- * one is the misleading half here: `handleHITLDecision` emits `run_paused` and
2331
- * drains it BEFORE it calls `setStopReason('paused')`, so a consumer that
2332
- * leaves on that event leaves a run whose status is `running` and whose stop
2333
- * reason is unset at the exact instant its park is already durable.
2334
- * `findPendingCheckpoint` is the same read an approval queue is built from,
2335
- * expired parks included in its judgement: a park nobody answered in time is
2336
- * not somebody still being asked.
2400
+ * - A turn that already settled, or already paused, is left as it stands.
2401
+ * - A turn parked on a decision (an open `decision_requested`) is PAUSED on
2402
+ * that checkpoint: a park is a promise to a human that outlives the
2403
+ * consumer, and `resumeSession` continues it once the answer arrives.
2404
+ * - Any other turn is settled `cancelled` (`turn_completed`): it did not
2405
+ * complete and nothing failed; its consumer stopped reading.
2337
2406
  *
2338
2407
  * Never throws. It runs while an exception may already be unwinding, and a
2339
- * store that cannot be written must not replace the run's real failure with
2340
- * its own.
2408
+ * log that cannot be written must not replace the turn's real failure.
2341
2409
  */
2342
- async function settleAbandonedRun(runMgr: RunPersistence, log: Logger): Promise<void> {
2410
+ async function settleAbandonedTurn(
2411
+ recorder: TurnRecorder,
2412
+ eventTranslator: EventTranslator,
2413
+ log: Logger,
2414
+ ): Promise<void> {
2343
2415
  try {
2344
- // A terminal verdict is written whatever the park says: `deriveRunStatus`
2345
- // settles a run that finished, failed or was cancelled BEFORE it looks at
2346
- // a park ("terminal beats parked"), so a settled run is not waiting for
2347
- // anybody and the row it already wrote must reach the disk. This ordering
2348
- // is also what keeps a stale park from suppressing the write.
2349
- if (!isTerminalStatus(runMgr.status)) {
2350
- const parked = await findPendingCheckpoint(runMgr.getCheckpointStore(), runMgr.getRunScope())
2351
- if (parked) {
2352
- // Left exactly as it stands: no verdict, no write. The park row is
2353
- // this run's durable state, and `persist()` here would add a
2354
- // second claim — `running`, for a process that is gone — beside it.
2355
- log.info('Abandoned run left parked for a human to answer', {
2356
- [NAMZU.RUN_ID]: runMgr.id,
2357
- 'namzu.checkpoint.id': parked.id,
2358
- 'namzu.runtime.park_type': parked.pending?.request.type,
2359
- })
2360
- return
2361
- }
2362
- runMgr.markCancelled()
2416
+ if (recorder.isClosed || recorder.isPaused || !recorder.isActive) return
2417
+ await recorder.flush()
2418
+ const parked = await findPendingCheckpoint(recorder.log, { turnId: recorder.turnId })
2419
+ if (parked) {
2420
+ recorder.setStopReason('paused')
2421
+ await eventTranslator.emitEvent({
2422
+ type: 'turn_paused',
2423
+ checkpointId: parked.checkpointId,
2424
+ reason: 'The consumer stopped reading while the turn was awaiting a decision.',
2425
+ })
2426
+ await recorder.persist()
2427
+ log.info('Abandoned turn left paused for a human to answer', {
2428
+ [NAMZU.TURN_ID]: recorder.turnId,
2429
+ 'namzu.checkpoint.id': parked.checkpointId,
2430
+ 'namzu.runtime.park_type': parked.pending.request.type,
2431
+ })
2432
+ return
2363
2433
  }
2364
- // Once: the `finally` that calls this runs once, and every site in the
2365
- // run body that settles through `finalize()` sets `settled` before it
2366
- // returns, so the two can never both write.
2367
- await runMgr.persist()
2368
- log.info('Abandoned run recorded as cancelled', {
2369
- [NAMZU.RUN_ID]: runMgr.id,
2434
+ if (!isTerminalStatus(recorder.status)) recorder.markCancelled()
2435
+ await eventTranslator.emitEvent({
2436
+ type: 'turn_completed',
2437
+ result: recorder.getTurn().result ?? '',
2438
+ ...(recorder.stopReason ? { stopReason: recorder.stopReason } : {}),
2439
+ settlement: recorder.settlement(recorder.status === 'cancelled' ? 'cancelled' : 'completed'),
2440
+ })
2441
+ await recorder.persist()
2442
+ log.info('Abandoned turn recorded as cancelled', {
2443
+ [NAMZU.TURN_ID]: recorder.turnId,
2370
2444
  })
2371
2445
  } catch (err) {
2372
- log.error('Failed to record the terminal state of an abandoned run', {
2373
- [NAMZU.RUN_ID]: runMgr.id,
2446
+ log.error('Failed to record the end of an abandoned turn', {
2447
+ [NAMZU.TURN_ID]: recorder.turnId,
2374
2448
  'exception.message': err instanceof Error ? err.message : String(err),
2375
2449
  })
2376
2450
  }
@@ -2391,8 +2465,8 @@ type DrainQueryParams = Omit<QueryParams, 'resumeHandler'> & {
2391
2465
 
2392
2466
  async function drainPreparedQuery(
2393
2467
  fullParams: QueryParams,
2394
- listener?: RunEventListener,
2395
- ): Promise<Run> {
2468
+ listener?: SessionEventListener,
2469
+ ): Promise<Turn> {
2396
2470
  const gen = query(fullParams)
2397
2471
  let result = await gen.next()
2398
2472
 
@@ -2410,8 +2484,8 @@ export async function drainQuery(
2410
2484
  params: Omit<QueryParams, 'resumeHandler'> & {
2411
2485
  resumeHandler?: ResumeHandler
2412
2486
  },
2413
- listener?: RunEventListener,
2414
- ): Promise<Run> {
2487
+ listener?: SessionEventListener,
2488
+ ): Promise<Turn> {
2415
2489
  const fullParams: QueryParams = {
2416
2490
  ...params,
2417
2491
  resumeHandler: params.resumeHandler ?? autoApproveHandler,
@@ -2419,12 +2493,12 @@ export async function drainQuery(
2419
2493
  return await drainPreparedQuery(fullParams, listener)
2420
2494
  }
2421
2495
 
2422
- /** @internal Canonical resume state already selected by `resumeRun`. */
2496
+ /** @internal Canonical resume state already selected by `resumeSession`. */
2423
2497
  export async function drainQueryWithSelectedResumeState(
2424
2498
  params: DrainQueryParams,
2425
2499
  state: SelectedResumeState,
2426
- listener?: RunEventListener,
2427
- ): Promise<Run> {
2500
+ listener?: SessionEventListener,
2501
+ ): Promise<Turn> {
2428
2502
  const fullParams: QueryParams = {
2429
2503
  ...params,
2430
2504
  resumeHandler: params.resumeHandler ?? autoApproveHandler,
@@ -2439,17 +2513,17 @@ export async function drainQueryWithSelectedResumeState(
2439
2513
 
2440
2514
  function assertSelectedResumeAttribution(params: QueryParams, state: SelectedResumeState): void {
2441
2515
  const mismatchedFields: string[] = []
2442
- if (params.runId !== state.runId) mismatchedFields.push('runId')
2516
+ if (params.turnId !== state.turnId) mismatchedFields.push('turnId')
2443
2517
  if (params.sessionId !== state.sessionId) mismatchedFields.push('sessionId')
2444
2518
  if (params.topicId !== state.topicId) mismatchedFields.push('topicId')
2445
2519
  if (params.projectId !== state.projectId) mismatchedFields.push('projectId')
2446
2520
  if (params.tenantId !== state.tenantId) mismatchedFields.push('tenantId')
2447
- if (params.parentRunId !== state.parentRunId) mismatchedFields.push('parentRunId')
2521
+ if (params.parentSessionId !== state.parentSessionId) mismatchedFields.push('parentSessionId')
2448
2522
  if (mismatchedFields.length === 0) return
2449
2523
 
2450
2524
  throw new NamzuError({
2451
2525
  code: 'invalid_config',
2452
- message: 'The selected resume state does not match the run attribution supplied to the query.',
2526
+ message: 'The selected resume state does not match the turn attribution supplied to the query.',
2453
2527
  details: { fields: mismatchedFields },
2454
2528
  })
2455
2529
  }