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