@namzu/sdk 38.2.1 → 40.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (602) hide show
  1. package/CHANGELOG.md +851 -0
  2. package/dist/advisory/executor.d.ts +10 -1
  3. package/dist/advisory/executor.d.ts.map +1 -1
  4. package/dist/advisory/executor.js +5 -26
  5. package/dist/advisory/executor.js.map +1 -1
  6. package/dist/advisory/history.d.ts +9 -0
  7. package/dist/advisory/history.d.ts.map +1 -0
  8. package/dist/advisory/history.js +120 -0
  9. package/dist/advisory/history.js.map +1 -0
  10. package/dist/advisory/index.d.ts +1 -1
  11. package/dist/advisory/index.d.ts.map +1 -1
  12. package/dist/advisory/index.js.map +1 -1
  13. package/dist/agents/ReactiveAgent.d.ts.map +1 -1
  14. package/dist/agents/ReactiveAgent.js +3 -0
  15. package/dist/agents/ReactiveAgent.js.map +1 -1
  16. package/dist/agents/runAgent.d.ts +10 -0
  17. package/dist/agents/runAgent.d.ts.map +1 -1
  18. package/dist/agents/runAgent.js +3 -0
  19. package/dist/agents/runAgent.js.map +1 -1
  20. package/dist/compaction/manual.d.ts +6 -0
  21. package/dist/compaction/manual.d.ts.map +1 -1
  22. package/dist/compaction/manual.js +21 -2
  23. package/dist/compaction/manual.js.map +1 -1
  24. package/dist/compaction/summary.d.ts.map +1 -1
  25. package/dist/compaction/summary.js +4 -1
  26. package/dist/compaction/summary.js.map +1 -1
  27. package/dist/config/runtime.js +2 -2
  28. package/dist/config/runtime.js.map +1 -1
  29. package/dist/connector/mcp/adapter.d.ts.map +1 -1
  30. package/dist/connector/mcp/adapter.js +20 -6
  31. package/dist/connector/mcp/adapter.js.map +1 -1
  32. package/dist/contracts/schemas.js +1 -1
  33. package/dist/contracts/schemas.js.map +1 -1
  34. package/dist/eval/harness-protection.d.ts +18 -0
  35. package/dist/eval/harness-protection.d.ts.map +1 -0
  36. package/dist/eval/harness-protection.js +58 -0
  37. package/dist/eval/harness-protection.js.map +1 -0
  38. package/dist/eval/harness-verification.d.ts +6 -1
  39. package/dist/eval/harness-verification.d.ts.map +1 -1
  40. package/dist/eval/harness-verification.js +19 -2
  41. package/dist/eval/harness-verification.js.map +1 -1
  42. package/dist/eval/index.d.ts +1 -0
  43. package/dist/eval/index.d.ts.map +1 -1
  44. package/dist/eval/index.js.map +1 -1
  45. package/dist/manager/resident/activity.d.ts +50 -0
  46. package/dist/manager/resident/activity.d.ts.map +1 -0
  47. package/dist/manager/resident/activity.js +125 -0
  48. package/dist/manager/resident/activity.js.map +1 -0
  49. package/dist/manager/resident/agenda.d.ts +13 -1
  50. package/dist/manager/resident/agenda.d.ts.map +1 -1
  51. package/dist/manager/resident/agenda.js +40 -5
  52. package/dist/manager/resident/agenda.js.map +1 -1
  53. package/dist/manager/resident/consumption.d.ts +104 -0
  54. package/dist/manager/resident/consumption.d.ts.map +1 -0
  55. package/dist/manager/resident/consumption.js +233 -0
  56. package/dist/manager/resident/consumption.js.map +1 -0
  57. package/dist/manager/resident/evidence-recall.d.ts +24 -0
  58. package/dist/manager/resident/evidence-recall.d.ts.map +1 -0
  59. package/dist/manager/resident/evidence-recall.js +295 -0
  60. package/dist/manager/resident/evidence-recall.js.map +1 -0
  61. package/dist/manager/resident/history-disk.d.ts +10 -0
  62. package/dist/manager/resident/history-disk.d.ts.map +1 -0
  63. package/dist/manager/resident/history-disk.js +50 -0
  64. package/dist/manager/resident/history-disk.js.map +1 -0
  65. package/dist/manager/resident/history.d.ts +79 -0
  66. package/dist/manager/resident/history.d.ts.map +1 -0
  67. package/dist/manager/resident/history.js +203 -0
  68. package/dist/manager/resident/history.js.map +1 -0
  69. package/dist/manager/resident/initiative.d.ts.map +1 -1
  70. package/dist/manager/resident/initiative.js +11 -3
  71. package/dist/manager/resident/initiative.js.map +1 -1
  72. package/dist/manager/resident/learning-cycle.d.ts +131 -0
  73. package/dist/manager/resident/learning-cycle.d.ts.map +1 -0
  74. package/dist/manager/resident/learning-cycle.js +306 -0
  75. package/dist/manager/resident/learning-cycle.js.map +1 -0
  76. package/dist/manager/resident/learning-observation.d.ts +80 -0
  77. package/dist/manager/resident/learning-observation.d.ts.map +1 -0
  78. package/dist/manager/resident/learning-observation.js +22 -0
  79. package/dist/manager/resident/learning-observation.js.map +1 -0
  80. package/dist/manager/resident/learning-store.d.ts +106 -0
  81. package/dist/manager/resident/learning-store.d.ts.map +1 -0
  82. package/dist/manager/resident/learning-store.js +598 -0
  83. package/dist/manager/resident/learning-store.js.map +1 -0
  84. package/dist/manager/resident/learning.d.ts +246 -3
  85. package/dist/manager/resident/learning.d.ts.map +1 -1
  86. package/dist/manager/resident/learning.js +96 -6
  87. package/dist/manager/resident/learning.js.map +1 -1
  88. package/dist/manager/resident/outbox.d.ts +4 -4
  89. package/dist/manager/resident/store.d.ts +37 -4
  90. package/dist/manager/resident/store.d.ts.map +1 -1
  91. package/dist/manager/resident/store.js +27 -3
  92. package/dist/manager/resident/store.js.map +1 -1
  93. package/dist/manager/resident/tool-evidence.d.ts +71 -0
  94. package/dist/manager/resident/tool-evidence.d.ts.map +1 -0
  95. package/dist/manager/resident/tool-evidence.js +285 -0
  96. package/dist/manager/resident/tool-evidence.js.map +1 -0
  97. package/dist/manager/run/persistence.d.ts +8 -0
  98. package/dist/manager/run/persistence.d.ts.map +1 -1
  99. package/dist/manager/run/persistence.js +18 -0
  100. package/dist/manager/run/persistence.js.map +1 -1
  101. package/dist/plugin/loader.d.ts.map +1 -1
  102. package/dist/plugin/loader.js +5 -3
  103. package/dist/plugin/loader.js.map +1 -1
  104. package/dist/prompt/coding-agent-doctrine.d.ts +1 -1
  105. package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
  106. package/dist/prompt/coding-agent-doctrine.js +2 -0
  107. package/dist/prompt/coding-agent-doctrine.js.map +1 -1
  108. package/dist/prompt/index.d.ts +2 -0
  109. package/dist/prompt/index.d.ts.map +1 -1
  110. package/dist/prompt/index.js +1 -0
  111. package/dist/prompt/index.js.map +1 -1
  112. package/dist/prompt/resident-learning.d.ts +19 -0
  113. package/dist/prompt/resident-learning.d.ts.map +1 -0
  114. package/dist/prompt/resident-learning.js +125 -0
  115. package/dist/prompt/resident-learning.js.map +1 -0
  116. package/dist/prompt/resident-step.d.ts +8 -1
  117. package/dist/prompt/resident-step.d.ts.map +1 -1
  118. package/dist/prompt/resident-step.js +65 -4
  119. package/dist/prompt/resident-step.js.map +1 -1
  120. package/dist/provider/collect-chat-completion.d.ts +2 -1
  121. package/dist/provider/collect-chat-completion.d.ts.map +1 -1
  122. package/dist/provider/collect-chat-completion.js +7 -6
  123. package/dist/provider/collect-chat-completion.js.map +1 -1
  124. package/dist/provider/fallback.d.ts.map +1 -1
  125. package/dist/provider/fallback.js +2 -1
  126. package/dist/provider/fallback.js.map +1 -1
  127. package/dist/provider/stream-text.d.ts +16 -0
  128. package/dist/provider/stream-text.d.ts.map +1 -0
  129. package/dist/provider/stream-text.js +51 -0
  130. package/dist/provider/stream-text.js.map +1 -0
  131. package/dist/public-runtime.d.ts +16 -4
  132. package/dist/public-runtime.d.ts.map +1 -1
  133. package/dist/public-runtime.js +17 -4
  134. package/dist/public-runtime.js.map +1 -1
  135. package/dist/public-tools.d.ts +13 -0
  136. package/dist/public-tools.d.ts.map +1 -1
  137. package/dist/public-tools.js +16 -0
  138. package/dist/public-tools.js.map +1 -1
  139. package/dist/public-types.d.ts +15 -3
  140. package/dist/public-types.d.ts.map +1 -1
  141. package/dist/registry/tool/execute.d.ts.map +1 -1
  142. package/dist/registry/tool/execute.js +2 -3
  143. package/dist/registry/tool/execute.js.map +1 -1
  144. package/dist/registry/tool/portable.d.ts +65 -0
  145. package/dist/registry/tool/portable.d.ts.map +1 -0
  146. package/dist/registry/tool/portable.js +244 -0
  147. package/dist/registry/tool/portable.js.map +1 -0
  148. package/dist/registry/tool/schema.d.ts +32 -5
  149. package/dist/registry/tool/schema.d.ts.map +1 -1
  150. package/dist/registry/tool/schema.js +35 -9
  151. package/dist/registry/tool/schema.js.map +1 -1
  152. package/dist/registry/toolset/catalog.js +8 -8
  153. package/dist/registry/toolset/catalog.js.map +1 -1
  154. package/dist/run/LimitChecker.js +3 -3
  155. package/dist/run/LimitChecker.js.map +1 -1
  156. package/dist/run/evidence-query.d.ts +41 -0
  157. package/dist/run/evidence-query.d.ts.map +1 -0
  158. package/dist/run/evidence-query.js +270 -0
  159. package/dist/run/evidence-query.js.map +1 -0
  160. package/dist/run/evidence-recall.d.ts +99 -0
  161. package/dist/run/evidence-recall.d.ts.map +1 -0
  162. package/dist/run/evidence-recall.js +633 -0
  163. package/dist/run/evidence-recall.js.map +1 -0
  164. package/dist/run/index.d.ts +2 -0
  165. package/dist/run/index.d.ts.map +1 -1
  166. package/dist/run/index.js +1 -0
  167. package/dist/run/index.js.map +1 -1
  168. package/dist/run/json-claim-verifier.d.ts +83 -0
  169. package/dist/run/json-claim-verifier.d.ts.map +1 -0
  170. package/dist/run/json-claim-verifier.js +200 -0
  171. package/dist/run/json-claim-verifier.js.map +1 -0
  172. package/dist/run/preparation-context-error.d.ts +10 -0
  173. package/dist/run/preparation-context-error.d.ts.map +1 -0
  174. package/dist/run/preparation-context-error.js +15 -0
  175. package/dist/run/preparation-context-error.js.map +1 -0
  176. package/dist/run-query/index.d.ts +3 -1
  177. package/dist/run-query/index.d.ts.map +1 -1
  178. package/dist/runtime/jobs/awaited-jobs.d.ts +215 -0
  179. package/dist/runtime/jobs/awaited-jobs.d.ts.map +1 -0
  180. package/dist/runtime/jobs/awaited-jobs.js +259 -0
  181. package/dist/runtime/jobs/awaited-jobs.js.map +1 -0
  182. package/dist/runtime/jobs/registry.d.ts +33 -2
  183. package/dist/runtime/jobs/registry.d.ts.map +1 -1
  184. package/dist/runtime/jobs/registry.js +37 -0
  185. package/dist/runtime/jobs/registry.js.map +1 -1
  186. package/dist/runtime/query/callback-inference.d.ts +8 -0
  187. package/dist/runtime/query/callback-inference.d.ts.map +1 -0
  188. package/dist/runtime/query/callback-inference.js +89 -0
  189. package/dist/runtime/query/callback-inference.js.map +1 -0
  190. package/dist/runtime/query/checkpoint.d.ts +4 -0
  191. package/dist/runtime/query/checkpoint.d.ts.map +1 -1
  192. package/dist/runtime/query/checkpoint.js +13 -0
  193. package/dist/runtime/query/checkpoint.js.map +1 -1
  194. package/dist/runtime/query/events.d.ts +1 -0
  195. package/dist/runtime/query/events.d.ts.map +1 -1
  196. package/dist/runtime/query/events.js +18 -0
  197. package/dist/runtime/query/events.js.map +1 -1
  198. package/dist/runtime/query/executor.d.ts +35 -1
  199. package/dist/runtime/query/executor.d.ts.map +1 -1
  200. package/dist/runtime/query/executor.js +77 -8
  201. package/dist/runtime/query/executor.js.map +1 -1
  202. package/dist/runtime/query/file-evidence-context.d.ts +5 -0
  203. package/dist/runtime/query/file-evidence-context.d.ts.map +1 -0
  204. package/dist/runtime/query/file-evidence-context.js +180 -0
  205. package/dist/runtime/query/file-evidence-context.js.map +1 -0
  206. package/dist/runtime/query/file-evidence-replay.d.ts +260 -0
  207. package/dist/runtime/query/file-evidence-replay.d.ts.map +1 -0
  208. package/dist/runtime/query/file-evidence-replay.js +647 -0
  209. package/dist/runtime/query/file-evidence-replay.js.map +1 -0
  210. package/dist/runtime/query/file-evidence-seed.d.ts +50 -0
  211. package/dist/runtime/query/file-evidence-seed.d.ts.map +1 -0
  212. package/dist/runtime/query/file-evidence-seed.js +100 -0
  213. package/dist/runtime/query/file-evidence-seed.js.map +1 -0
  214. package/dist/runtime/query/guard.d.ts.map +1 -1
  215. package/dist/runtime/query/guard.js +4 -0
  216. package/dist/runtime/query/guard.js.map +1 -1
  217. package/dist/runtime/query/index.d.ts +10 -1
  218. package/dist/runtime/query/index.d.ts.map +1 -1
  219. package/dist/runtime/query/index.js +133 -26
  220. package/dist/runtime/query/index.js.map +1 -1
  221. package/dist/runtime/query/iteration/index.d.ts +92 -36
  222. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  223. package/dist/runtime/query/iteration/index.js +420 -117
  224. package/dist/runtime/query/iteration/index.js.map +1 -1
  225. package/dist/runtime/query/iteration/phases/advisory.d.ts +2 -1
  226. package/dist/runtime/query/iteration/phases/advisory.d.ts.map +1 -1
  227. package/dist/runtime/query/iteration/phases/advisory.js +2 -1
  228. package/dist/runtime/query/iteration/phases/advisory.js.map +1 -1
  229. package/dist/runtime/query/iteration/phases/context.d.ts +12 -1
  230. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  231. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  232. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  233. package/dist/runtime/query/iteration/phases/tool-review.js +8 -1
  234. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  235. package/dist/runtime/query/iteration/provider-rejected-image.d.ts +2 -1
  236. package/dist/runtime/query/iteration/provider-rejected-image.d.ts.map +1 -1
  237. package/dist/runtime/query/iteration/provider-rejected-image.js +5 -2
  238. package/dist/runtime/query/iteration/provider-rejected-image.js.map +1 -1
  239. package/dist/runtime/query/iteration/stream-turn.d.ts +4 -1
  240. package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
  241. package/dist/runtime/query/iteration/stream-turn.js +22 -8
  242. package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
  243. package/dist/runtime/query/plugin-hooks.d.ts +14 -0
  244. package/dist/runtime/query/plugin-hooks.d.ts.map +1 -1
  245. package/dist/runtime/query/plugin-hooks.js +18 -0
  246. package/dist/runtime/query/plugin-hooks.js.map +1 -1
  247. package/dist/runtime/query/repeat-call.d.ts +17 -4
  248. package/dist/runtime/query/repeat-call.d.ts.map +1 -1
  249. package/dist/runtime/query/repeat-call.js +26 -19
  250. package/dist/runtime/query/repeat-call.js.map +1 -1
  251. package/dist/runtime/query/resume-pending.d.ts +18 -33
  252. package/dist/runtime/query/resume-pending.d.ts.map +1 -1
  253. package/dist/runtime/query/resume-pending.js +59 -42
  254. package/dist/runtime/query/resume-pending.js.map +1 -1
  255. package/dist/runtime/query/review-policy.d.ts +4 -4
  256. package/dist/runtime/query/review-policy.d.ts.map +1 -1
  257. package/dist/runtime/query/review-policy.js +10 -9
  258. package/dist/runtime/query/review-policy.js.map +1 -1
  259. package/dist/runtime/query/sandbox-lifecycle.d.ts.map +1 -1
  260. package/dist/runtime/query/sandbox-lifecycle.js +4 -0
  261. package/dist/runtime/query/sandbox-lifecycle.js.map +1 -1
  262. package/dist/runtime/query/steering.d.ts +11 -1
  263. package/dist/runtime/query/steering.d.ts.map +1 -1
  264. package/dist/runtime/query/steering.js +12 -1
  265. package/dist/runtime/query/steering.js.map +1 -1
  266. package/dist/runtime/query/tool-output-budget.d.ts +10 -6
  267. package/dist/runtime/query/tool-output-budget.d.ts.map +1 -1
  268. package/dist/runtime/query/tool-output-budget.js +54 -12
  269. package/dist/runtime/query/tool-output-budget.js.map +1 -1
  270. package/dist/runtime/query/tooling.d.ts +5 -1
  271. package/dist/runtime/query/tooling.d.ts.map +1 -1
  272. package/dist/runtime/query/tooling.js +5 -0
  273. package/dist/runtime/query/tooling.js.map +1 -1
  274. package/dist/scheduler/completion-inbox.d.ts +49 -0
  275. package/dist/scheduler/completion-inbox.d.ts.map +1 -1
  276. package/dist/scheduler/completion-inbox.js +122 -2
  277. package/dist/scheduler/completion-inbox.js.map +1 -1
  278. package/dist/store/evidence/compaction-archive.d.ts +109 -0
  279. package/dist/store/evidence/compaction-archive.d.ts.map +1 -0
  280. package/dist/store/evidence/compaction-archive.js +125 -0
  281. package/dist/store/evidence/compaction-archive.js.map +1 -0
  282. package/dist/store/evidence/compaction-provenance.d.ts +7 -0
  283. package/dist/store/evidence/compaction-provenance.d.ts.map +1 -0
  284. package/dist/store/evidence/compaction-provenance.js +49 -0
  285. package/dist/store/evidence/compaction-provenance.js.map +1 -0
  286. package/dist/store/evidence/compaction-text.d.ts +16 -0
  287. package/dist/store/evidence/compaction-text.d.ts.map +1 -0
  288. package/dist/store/evidence/compaction-text.js +51 -0
  289. package/dist/store/evidence/compaction-text.js.map +1 -0
  290. package/dist/store/evidence/disk.d.ts +11 -0
  291. package/dist/store/evidence/disk.d.ts.map +1 -0
  292. package/dist/store/evidence/disk.js +367 -0
  293. package/dist/store/evidence/disk.js.map +1 -0
  294. package/dist/store/evidence/format.d.ts +25 -0
  295. package/dist/store/evidence/format.d.ts.map +1 -0
  296. package/dist/store/evidence/format.js +115 -0
  297. package/dist/store/evidence/format.js.map +1 -0
  298. package/dist/store/evidence/index-page.d.ts +208 -0
  299. package/dist/store/evidence/index-page.d.ts.map +1 -0
  300. package/dist/store/evidence/index-page.js +262 -0
  301. package/dist/store/evidence/index-page.js.map +1 -0
  302. package/dist/store/evidence/io.d.ts +24 -0
  303. package/dist/store/evidence/io.d.ts.map +1 -0
  304. package/dist/store/evidence/io.js +69 -0
  305. package/dist/store/evidence/io.js.map +1 -0
  306. package/dist/store/evidence/linked.d.ts +9 -0
  307. package/dist/store/evidence/linked.d.ts.map +1 -0
  308. package/dist/store/evidence/linked.js +314 -0
  309. package/dist/store/evidence/linked.js.map +1 -0
  310. package/dist/store/evidence/passages.d.ts +15 -0
  311. package/dist/store/evidence/passages.d.ts.map +1 -0
  312. package/dist/store/evidence/passages.js +72 -0
  313. package/dist/store/evidence/passages.js.map +1 -0
  314. package/dist/store/evidence/record-chain.d.ts +42 -0
  315. package/dist/store/evidence/record-chain.d.ts.map +1 -0
  316. package/dist/store/evidence/record-chain.js +111 -0
  317. package/dist/store/evidence/record-chain.js.map +1 -0
  318. package/dist/store/evidence/search-input.d.ts +21 -0
  319. package/dist/store/evidence/search-input.d.ts.map +1 -0
  320. package/dist/store/evidence/search-input.js +44 -0
  321. package/dist/store/evidence/search-input.js.map +1 -0
  322. package/dist/store/evidence/selection.d.ts +9 -0
  323. package/dist/store/evidence/selection.d.ts.map +1 -0
  324. package/dist/store/evidence/selection.js +17 -0
  325. package/dist/store/evidence/selection.js.map +1 -0
  326. package/dist/store/evidence/source-kind.d.ts +11 -0
  327. package/dist/store/evidence/source-kind.d.ts.map +1 -0
  328. package/dist/store/evidence/source-kind.js +26 -0
  329. package/dist/store/evidence/source-kind.js.map +1 -0
  330. package/dist/store/evidence/source-text.d.ts +51 -0
  331. package/dist/store/evidence/source-text.d.ts.map +1 -0
  332. package/dist/store/evidence/source-text.js +213 -0
  333. package/dist/store/evidence/source-text.js.map +1 -0
  334. package/dist/store/evidence/types.d.ts +162 -0
  335. package/dist/store/evidence/types.d.ts.map +1 -0
  336. package/dist/store/evidence/types.js +2 -0
  337. package/dist/store/evidence/types.js.map +1 -0
  338. package/dist/store/memory/disk.d.ts +2 -0
  339. package/dist/store/memory/disk.d.ts.map +1 -1
  340. package/dist/store/memory/disk.js +2 -1
  341. package/dist/store/memory/disk.js.map +1 -1
  342. package/dist/store/run/disk.d.ts +10 -0
  343. package/dist/store/run/disk.d.ts.map +1 -1
  344. package/dist/store/run/disk.js +87 -7
  345. package/dist/store/run/disk.js.map +1 -1
  346. package/dist/store/run/memory.d.ts +1 -0
  347. package/dist/store/run/memory.d.ts.map +1 -1
  348. package/dist/store/run/memory.js +10 -0
  349. package/dist/store/run/memory.js.map +1 -1
  350. package/dist/store/run/tool-executions.d.ts +13 -0
  351. package/dist/store/run/tool-executions.d.ts.map +1 -0
  352. package/dist/store/run/tool-executions.js +99 -0
  353. package/dist/store/run/tool-executions.js.map +1 -0
  354. package/dist/store/session/index.d.ts +2 -0
  355. package/dist/store/session/index.d.ts.map +1 -1
  356. package/dist/store/session/index.js +1 -0
  357. package/dist/store/session/index.js.map +1 -1
  358. package/dist/store/session/sqlite.d.ts +57 -0
  359. package/dist/store/session/sqlite.d.ts.map +1 -0
  360. package/dist/store/session/sqlite.js +430 -0
  361. package/dist/store/session/sqlite.js.map +1 -0
  362. package/dist/tools/builtins/bash.d.ts.map +1 -1
  363. package/dist/tools/builtins/bash.js +4 -10
  364. package/dist/tools/builtins/bash.js.map +1 -1
  365. package/dist/tools/builtins/edit-apply.d.ts +126 -0
  366. package/dist/tools/builtins/edit-apply.d.ts.map +1 -0
  367. package/dist/tools/builtins/edit-apply.js +360 -0
  368. package/dist/tools/builtins/edit-apply.js.map +1 -0
  369. package/dist/tools/builtins/edit.d.ts +143 -1
  370. package/dist/tools/builtins/edit.d.ts.map +1 -1
  371. package/dist/tools/builtins/edit.js +37 -219
  372. package/dist/tools/builtins/edit.js.map +1 -1
  373. package/dist/tools/builtins/index.d.ts +1 -0
  374. package/dist/tools/builtins/index.d.ts.map +1 -1
  375. package/dist/tools/builtins/index.js +9 -3
  376. package/dist/tools/builtins/index.js.map +1 -1
  377. package/dist/tools/builtins/job.d.ts.map +1 -1
  378. package/dist/tools/builtins/job.js +5 -6
  379. package/dist/tools/builtins/job.js.map +1 -1
  380. package/dist/tools/builtins/read-file.d.ts +2 -2
  381. package/dist/tools/builtins/read-file.d.ts.map +1 -1
  382. package/dist/tools/builtins/read-file.js +50 -65
  383. package/dist/tools/builtins/read-file.js.map +1 -1
  384. package/dist/tools/builtins/read-render.d.ts +56 -0
  385. package/dist/tools/builtins/read-render.d.ts.map +1 -0
  386. package/dist/tools/builtins/read-render.js +73 -0
  387. package/dist/tools/builtins/read-render.js.map +1 -0
  388. package/dist/tools/builtins/wait-for-job-bounds.d.ts +67 -0
  389. package/dist/tools/builtins/wait-for-job-bounds.d.ts.map +1 -0
  390. package/dist/tools/builtins/wait-for-job-bounds.js +108 -0
  391. package/dist/tools/builtins/wait-for-job-bounds.js.map +1 -0
  392. package/dist/tools/builtins/wait-for-job.d.ts +6 -0
  393. package/dist/tools/builtins/wait-for-job.d.ts.map +1 -0
  394. package/dist/tools/builtins/wait-for-job.js +162 -0
  395. package/dist/tools/builtins/wait-for-job.js.map +1 -0
  396. package/dist/tools/builtins/write-file.js +7 -2
  397. package/dist/tools/builtins/write-file.js.map +1 -1
  398. package/dist/tools/coordinator/index.d.ts.map +1 -1
  399. package/dist/tools/coordinator/index.js +1 -7
  400. package/dist/tools/coordinator/index.js.map +1 -1
  401. package/dist/tools/defineTool.d.ts +2 -1
  402. package/dist/tools/defineTool.d.ts.map +1 -1
  403. package/dist/tools/defineTool.js +1 -1
  404. package/dist/tools/defineTool.js.map +1 -1
  405. package/dist/tools/file-read-tracker.d.ts.map +1 -1
  406. package/dist/tools/file-read-tracker.js +90 -3
  407. package/dist/tools/file-read-tracker.js.map +1 -1
  408. package/dist/tools/resident-history.d.ts +10 -0
  409. package/dist/tools/resident-history.d.ts.map +1 -0
  410. package/dist/tools/resident-history.js +80 -0
  411. package/dist/tools/resident-history.js.map +1 -0
  412. package/dist/tools/resident-tool-evidence.d.ts +5 -0
  413. package/dist/tools/resident-tool-evidence.d.ts.map +1 -0
  414. package/dist/tools/resident-tool-evidence.js +57 -0
  415. package/dist/tools/resident-tool-evidence.js.map +1 -0
  416. package/dist/types/advisory/config.d.ts +7 -0
  417. package/dist/types/advisory/config.d.ts.map +1 -1
  418. package/dist/types/agent/reactive.d.ts +1 -0
  419. package/dist/types/agent/reactive.d.ts.map +1 -1
  420. package/dist/types/authorization/index.d.ts +9 -9
  421. package/dist/types/authorization/index.d.ts.map +1 -1
  422. package/dist/types/authorization/index.js +1 -1
  423. package/dist/types/authorization/index.js.map +1 -1
  424. package/dist/types/hitl/index.d.ts +4 -0
  425. package/dist/types/hitl/index.d.ts.map +1 -1
  426. package/dist/types/hitl/index.js.map +1 -1
  427. package/dist/types/message/index.d.ts +16 -2
  428. package/dist/types/message/index.d.ts.map +1 -1
  429. package/dist/types/message/index.js +10 -1
  430. package/dist/types/message/index.js.map +1 -1
  431. package/dist/types/provider/chat.d.ts +2 -0
  432. package/dist/types/provider/chat.d.ts.map +1 -1
  433. package/dist/types/provider/stream.d.ts +4 -0
  434. package/dist/types/provider/stream.d.ts.map +1 -1
  435. package/dist/types/run/answer-review.d.ts +34 -3
  436. package/dist/types/run/answer-review.d.ts.map +1 -1
  437. package/dist/types/run/config.d.ts +3 -0
  438. package/dist/types/run/config.d.ts.map +1 -1
  439. package/dist/types/run/entity.d.ts +20 -0
  440. package/dist/types/run/entity.d.ts.map +1 -1
  441. package/dist/types/run/events.d.ts +31 -8
  442. package/dist/types/run/events.d.ts.map +1 -1
  443. package/dist/types/run/events.js.map +1 -1
  444. package/dist/types/run/prepare-step.d.ts +53 -8
  445. package/dist/types/run/prepare-step.d.ts.map +1 -1
  446. package/dist/types/run/store.d.ts +29 -4
  447. package/dist/types/run/store.d.ts.map +1 -1
  448. package/dist/types/run/store.js +0 -28
  449. package/dist/types/run/store.js.map +1 -1
  450. package/dist/types/sandbox/index.d.ts +15 -14
  451. package/dist/types/sandbox/index.d.ts.map +1 -1
  452. package/dist/types/sandbox/index.js.map +1 -1
  453. package/dist/types/tool/index.d.ts +124 -1
  454. package/dist/types/tool/index.d.ts.map +1 -1
  455. package/dist/types/tool/index.js.map +1 -1
  456. package/dist/utils/await-with-abort.d.ts +8 -0
  457. package/dist/utils/await-with-abort.d.ts.map +1 -0
  458. package/dist/utils/await-with-abort.js +28 -0
  459. package/dist/utils/await-with-abort.js.map +1 -0
  460. package/dist/utils/env.d.ts +19 -0
  461. package/dist/utils/env.d.ts.map +1 -0
  462. package/dist/utils/env.js +25 -0
  463. package/dist/utils/env.js.map +1 -0
  464. package/dist/utils/evidence-time.d.ts +3 -0
  465. package/dist/utils/evidence-time.d.ts.map +1 -0
  466. package/dist/utils/evidence-time.js +10 -0
  467. package/dist/utils/evidence-time.js.map +1 -0
  468. package/dist/utils/evidence-tokens.d.ts +13 -0
  469. package/dist/utils/evidence-tokens.d.ts.map +1 -0
  470. package/dist/utils/evidence-tokens.js +29 -0
  471. package/dist/utils/evidence-tokens.js.map +1 -0
  472. package/package.json +1 -1
  473. package/src/advisory/executor.ts +15 -30
  474. package/src/advisory/history.ts +126 -0
  475. package/src/advisory/index.ts +5 -1
  476. package/src/agents/ReactiveAgent.ts +3 -0
  477. package/src/agents/runAgent.ts +14 -1
  478. package/src/compaction/manual.ts +30 -2
  479. package/src/compaction/summary.ts +4 -1
  480. package/src/config/runtime.ts +2 -2
  481. package/src/connector/mcp/adapter.ts +20 -6
  482. package/src/contracts/schemas.ts +1 -1
  483. package/src/eval/harness-protection.ts +79 -0
  484. package/src/eval/harness-verification.ts +31 -1
  485. package/src/eval/index.ts +1 -0
  486. package/src/manager/resident/activity.ts +187 -0
  487. package/src/manager/resident/agenda.ts +59 -5
  488. package/src/manager/resident/consumption.ts +311 -0
  489. package/src/manager/resident/evidence-recall.ts +363 -0
  490. package/src/manager/resident/history-disk.ts +63 -0
  491. package/src/manager/resident/history.ts +312 -0
  492. package/src/manager/resident/initiative.ts +13 -3
  493. package/src/manager/resident/learning-cycle.ts +499 -0
  494. package/src/manager/resident/learning-observation.ts +39 -0
  495. package/src/manager/resident/learning-store.ts +813 -0
  496. package/src/manager/resident/learning.ts +132 -8
  497. package/src/manager/resident/store.ts +31 -3
  498. package/src/manager/resident/tool-evidence.ts +412 -0
  499. package/src/manager/run/persistence.ts +18 -0
  500. package/src/plugin/loader.ts +8 -3
  501. package/src/prompt/coding-agent-doctrine.ts +2 -0
  502. package/src/prompt/index.ts +2 -0
  503. package/src/prompt/resident-learning.ts +143 -0
  504. package/src/prompt/resident-step.ts +83 -3
  505. package/src/provider/collect-chat-completion.ts +7 -6
  506. package/src/provider/fallback.ts +2 -1
  507. package/src/provider/stream-text.ts +56 -0
  508. package/src/public-runtime.ts +39 -1
  509. package/src/public-tools.ts +21 -0
  510. package/src/public-types.ts +98 -0
  511. package/src/registry/tool/execute.ts +2 -4
  512. package/src/registry/tool/portable.ts +264 -0
  513. package/src/registry/tool/schema.ts +38 -8
  514. package/src/registry/toolset/catalog.ts +8 -9
  515. package/src/run/LimitChecker.ts +3 -3
  516. package/src/run/evidence-query.ts +333 -0
  517. package/src/run/evidence-recall.ts +854 -0
  518. package/src/run/index.ts +11 -0
  519. package/src/run/json-claim-verifier.ts +298 -0
  520. package/src/run/preparation-context-error.ts +16 -0
  521. package/src/run-query/index.ts +1 -1
  522. package/src/runtime/jobs/awaited-jobs.ts +271 -0
  523. package/src/runtime/jobs/registry.ts +50 -0
  524. package/src/runtime/query/callback-inference.ts +94 -0
  525. package/src/runtime/query/checkpoint.ts +14 -0
  526. package/src/runtime/query/events.ts +22 -0
  527. package/src/runtime/query/executor.ts +100 -10
  528. package/src/runtime/query/file-evidence-context.ts +209 -0
  529. package/src/runtime/query/file-evidence-replay.ts +776 -0
  530. package/src/runtime/query/file-evidence-seed.ts +126 -0
  531. package/src/runtime/query/guard.ts +2 -0
  532. package/src/runtime/query/index.ts +153 -27
  533. package/src/runtime/query/iteration/index.ts +467 -110
  534. package/src/runtime/query/iteration/phases/advisory.ts +3 -0
  535. package/src/runtime/query/iteration/phases/context.ts +12 -0
  536. package/src/runtime/query/iteration/phases/tool-review.ts +7 -0
  537. package/src/runtime/query/iteration/provider-rejected-image.ts +6 -1
  538. package/src/runtime/query/iteration/stream-turn.ts +35 -8
  539. package/src/runtime/query/plugin-hooks.ts +20 -0
  540. package/src/runtime/query/repeat-call.ts +28 -18
  541. package/src/runtime/query/resume-pending.ts +65 -40
  542. package/src/runtime/query/review-policy.ts +13 -9
  543. package/src/runtime/query/sandbox-lifecycle.ts +3 -0
  544. package/src/runtime/query/steering.ts +11 -0
  545. package/src/runtime/query/tool-output-budget.ts +65 -13
  546. package/src/runtime/query/tooling.ts +10 -1
  547. package/src/scheduler/completion-inbox.ts +124 -2
  548. package/src/store/evidence/compaction-archive.ts +139 -0
  549. package/src/store/evidence/compaction-provenance.ts +52 -0
  550. package/src/store/evidence/compaction-text.ts +61 -0
  551. package/src/store/evidence/disk.ts +461 -0
  552. package/src/store/evidence/format.ts +126 -0
  553. package/src/store/evidence/index-page.ts +292 -0
  554. package/src/store/evidence/io.ts +95 -0
  555. package/src/store/evidence/linked.ts +365 -0
  556. package/src/store/evidence/passages.ts +88 -0
  557. package/src/store/evidence/record-chain.ts +108 -0
  558. package/src/store/evidence/search-input.ts +62 -0
  559. package/src/store/evidence/selection.ts +25 -0
  560. package/src/store/evidence/source-kind.ts +36 -0
  561. package/src/store/evidence/source-text.ts +285 -0
  562. package/src/store/evidence/types.ts +177 -0
  563. package/src/store/memory/disk.ts +4 -1
  564. package/src/store/run/disk.ts +110 -8
  565. package/src/store/run/memory.ts +10 -0
  566. package/src/store/run/tool-executions.ts +112 -0
  567. package/src/store/session/index.ts +2 -0
  568. package/src/store/session/sqlite.ts +584 -0
  569. package/src/tools/builtins/bash.ts +4 -10
  570. package/src/tools/builtins/edit-apply.ts +456 -0
  571. package/src/tools/builtins/edit.ts +39 -270
  572. package/src/tools/builtins/index.ts +9 -3
  573. package/src/tools/builtins/job.ts +5 -6
  574. package/src/tools/builtins/read-file.ts +56 -77
  575. package/src/tools/builtins/read-render.ts +104 -0
  576. package/src/tools/builtins/wait-for-job-bounds.ts +179 -0
  577. package/src/tools/builtins/wait-for-job.ts +184 -0
  578. package/src/tools/builtins/write-file.ts +7 -2
  579. package/src/tools/coordinator/index.ts +1 -7
  580. package/src/tools/defineTool.ts +4 -2
  581. package/src/tools/file-read-tracker.ts +86 -2
  582. package/src/tools/resident-history.ts +86 -0
  583. package/src/tools/resident-tool-evidence.ts +68 -0
  584. package/src/types/advisory/config.ts +7 -0
  585. package/src/types/agent/reactive.ts +1 -0
  586. package/src/types/authorization/index.ts +2 -2
  587. package/src/types/hitl/index.ts +4 -0
  588. package/src/types/message/index.ts +22 -0
  589. package/src/types/provider/chat.ts +2 -0
  590. package/src/types/provider/stream.ts +4 -0
  591. package/src/types/run/answer-review.ts +34 -3
  592. package/src/types/run/config.ts +3 -0
  593. package/src/types/run/entity.ts +21 -0
  594. package/src/types/run/events.ts +31 -8
  595. package/src/types/run/prepare-step.ts +59 -8
  596. package/src/types/run/store.ts +35 -4
  597. package/src/types/sandbox/index.ts +15 -14
  598. package/src/types/tool/index.ts +123 -1
  599. package/src/utils/await-with-abort.ts +26 -0
  600. package/src/utils/env.ts +23 -0
  601. package/src/utils/evidence-time.ts +9 -0
  602. package/src/utils/evidence-tokens.ts +32 -0
package/src/run/index.ts CHANGED
@@ -29,3 +29,14 @@ export { RUN_MEMORY_TAG, createMemoryPromoter } from './memory-promoter.js'
29
29
  export type { MemoryPromoterOptions } from './memory-promoter.js'
30
30
  export { createMemoryRecallStep } from './memory-recall.js'
31
31
  export type { MemoryRecallOptions } from './memory-recall.js'
32
+ export { createJsonClaimVerifier } from './json-claim-verifier.js'
33
+ export type {
34
+ JsonClaimValue,
35
+ JsonClaimRequirement,
36
+ JsonClaimReadRequest,
37
+ JsonClaimObservation,
38
+ JsonClaimReceipt,
39
+ JsonClaimVerdict,
40
+ JsonClaimVerifierOptions,
41
+ JsonClaimVerifier,
42
+ } from './json-claim-verifier.js'
@@ -0,0 +1,298 @@
1
+ import { createHash, randomUUID } from 'node:crypto'
2
+ import { performance } from 'node:perf_hooks'
3
+ import type { RunId } from '../types/ids/index.js'
4
+ import type { AnswerReviewContext } from '../types/run/answer-review.js'
5
+
6
+ /** Numbers are restricted to safe integers; use strings for exact decimal values. */
7
+ export type JsonClaimValue = string | number | boolean | null
8
+
9
+ export interface JsonClaimRequirement {
10
+ readonly id: string
11
+ /** Host-selected source identifier, never an address supplied by the candidate. */
12
+ readonly source: string
13
+ /** RFC 6901 pointer to a scalar in the complete JSON document. */
14
+ readonly pointer: string
15
+ /** Optional postcondition in addition to candidate/source equality. */
16
+ readonly expected?: JsonClaimValue
17
+ }
18
+
19
+ export interface JsonClaimReadRequest {
20
+ readonly scope: string
21
+ readonly runId: RunId
22
+ readonly iteration: number
23
+ readonly requestId: string
24
+ readonly startedAt: number
25
+ /** Remaining total allowance. The host must bound capture, not only the returned buffer. */
26
+ readonly maxBytes: number
27
+ readonly signal: AbortSignal
28
+ }
29
+
30
+ export interface JsonClaimObservation {
31
+ readonly scope: string
32
+ readonly runId: RunId
33
+ readonly iteration: number
34
+ readonly requestId: string
35
+ readonly source: string
36
+ readonly observedAt: number
37
+ readonly complete: boolean
38
+ readonly kind: 'current' | 'historical'
39
+ readonly bytes: Uint8Array
40
+ }
41
+
42
+ export interface JsonClaimReceipt {
43
+ readonly scope: string
44
+ readonly runId: RunId
45
+ readonly iteration: number
46
+ readonly claims: Readonly<Record<string, JsonClaimValue>>
47
+ readonly observations: readonly {
48
+ readonly source: string
49
+ readonly requestId: string
50
+ readonly observedAt: number
51
+ readonly bytes: number
52
+ readonly sha256: string
53
+ }[]
54
+ }
55
+
56
+ export type JsonClaimVerdict =
57
+ | { readonly accept: true; readonly receipt: JsonClaimReceipt }
58
+ | { readonly accept: false; readonly feedback: string }
59
+
60
+ export interface JsonClaimVerifierOptions {
61
+ /** Host-owned authorization scope, including the admitted revision/claim where applicable. */
62
+ readonly scope: string
63
+ readonly runId: RunId
64
+ readonly requirements: readonly JsonClaimRequirement[]
65
+ /**
66
+ * Trusted, read-only adapter. Enforce access, capture bounds and cancellation;
67
+ * observe during this call. A matching envelope is not authentication against
68
+ * a dishonest adapter. Do not replay an action or relabel an archive as current.
69
+ */
70
+ readonly observe: (source: string, request: JsonClaimReadRequest) => Promise<JsonClaimObservation>
71
+ /** Total captured source bytes per verification; default 1 MiB, at most 8 MiB. */
72
+ readonly maxBytes?: number
73
+ /** Whole verification deadline; default 2 seconds, at most 30 seconds. */
74
+ readonly timeoutMs?: number
75
+ }
76
+
77
+ export interface JsonClaimVerifier {
78
+ /** False while an observer is outstanding, including after timeout/cancellation. */
79
+ isDrained(): boolean
80
+ /** No success cache. Every call observes the configured sources again. */
81
+ verify(
82
+ claims: unknown,
83
+ context: Pick<AnswerReviewContext, 'runId' | 'iteration' | 'signal'>,
84
+ ): Promise<JsonClaimVerdict>
85
+ }
86
+
87
+ function scalar(value: unknown): value is JsonClaimValue {
88
+ return (
89
+ value === null ||
90
+ typeof value === 'boolean' ||
91
+ (typeof value === 'string' && value.length <= 2_000) ||
92
+ (typeof value === 'number' && Number.isSafeInteger(value))
93
+ )
94
+ }
95
+
96
+ function reject(reason: string): JsonClaimVerdict {
97
+ return {
98
+ accept: false,
99
+ feedback: `Claim verification failed: ${reason} Do not claim verified completion. Correct the claims using a permitted observation, or report that completion is unavailable.`,
100
+ }
101
+ }
102
+
103
+ function pointerParts(pointer: string): string[] {
104
+ if (pointer === '') return []
105
+ if (!pointer.startsWith('/') || pointer.length > 512 || /~(?:[^01]|$)/u.test(pointer))
106
+ throw new Error('Invalid JSON claim pointer.')
107
+ return pointer
108
+ .slice(1)
109
+ .split('/')
110
+ .map((part) => part.replaceAll('~1', '/').replaceAll('~0', '~'))
111
+ }
112
+
113
+ function select(document: unknown, parts: readonly string[]): unknown {
114
+ let value = document
115
+ for (const part of parts) {
116
+ if (value === null || typeof value !== 'object' || !Object.hasOwn(value, part)) return undefined
117
+ if (Array.isArray(value) && !/^(0|[1-9]\d*)$/u.test(part)) return undefined
118
+ value = (value as Record<string, unknown>)[part]
119
+ }
120
+ return value
121
+ }
122
+
123
+ /**
124
+ * Compare explicit candidate fields with fresh, host-authorized JSON observations.
125
+ * This does not judge prose or prove the broader task complete. A receipt describes
126
+ * observation time, not an atomic snapshot or continuing truth after the read.
127
+ */
128
+ export function createJsonClaimVerifier(options: JsonClaimVerifierOptions): JsonClaimVerifier {
129
+ const { scope, runId, observe } = options
130
+ const maxBytes = options.maxBytes ?? 1_048_576
131
+ const timeoutMs = options.timeoutMs ?? 2_000
132
+ if (
133
+ typeof scope !== 'string' ||
134
+ !scope ||
135
+ scope.length > 2_000 ||
136
+ typeof runId !== 'string' ||
137
+ !runId ||
138
+ typeof observe !== 'function'
139
+ )
140
+ throw new Error('JSON claim verification requires a scope, run ID and observer.')
141
+ if (
142
+ !Number.isSafeInteger(maxBytes) ||
143
+ maxBytes < 1 ||
144
+ maxBytes > 8_388_608 ||
145
+ !Number.isSafeInteger(timeoutMs) ||
146
+ timeoutMs < 1 ||
147
+ timeoutMs > 30_000
148
+ )
149
+ throw new Error('Invalid JSON claim verification bounds.')
150
+ if (!options.requirements.length || options.requirements.length > 32)
151
+ throw new Error('JSON claim verification requires 1–32 requirements.')
152
+ const ids = new Set<string>()
153
+ const requirements = options.requirements.map((item) => {
154
+ if (
155
+ !/^[a-zA-Z][a-zA-Z0-9_-]{0,99}$/u.test(item.id) ||
156
+ ids.has(item.id) ||
157
+ typeof item.source !== 'string' ||
158
+ !item.source ||
159
+ item.source.length > 512 ||
160
+ typeof item.pointer !== 'string' ||
161
+ (Object.hasOwn(item, 'expected') && !scalar(item.expected))
162
+ )
163
+ throw new Error('Invalid or duplicate JSON claim requirement.')
164
+ ids.add(item.id)
165
+ return { ...item, parts: pointerParts(item.pointer) }
166
+ })
167
+ let active = false
168
+ let pending = 0
169
+ return {
170
+ isDrained: () => !active && pending === 0,
171
+ async verify(claims, context) {
172
+ context.signal?.throwIfAborted()
173
+ if (
174
+ context.runId !== runId ||
175
+ !Number.isSafeInteger(context.iteration) ||
176
+ context.iteration < 0
177
+ )
178
+ return reject('The review belongs to a different run or invalid iteration.')
179
+ if (active || pending) return reject('A previous observation has not drained.')
180
+ if (
181
+ !claims ||
182
+ typeof claims !== 'object' ||
183
+ Array.isArray(claims) ||
184
+ Object.keys(claims).length !== requirements.length ||
185
+ Object.keys(claims).some((id) => !ids.has(id))
186
+ )
187
+ return reject('Supply exactly the configured claim IDs and scalar values.')
188
+ const values: Record<string, JsonClaimValue> = Object.create(null)
189
+ for (const item of requirements) {
190
+ if (!Object.hasOwn(claims, item.id)) return reject('A required claim is missing.')
191
+ const value = (claims as Record<string, unknown>)[item.id]
192
+ if (!scalar(value)) return reject(`Claim ${item.id} is not a supported scalar.`)
193
+ values[item.id] = value
194
+ }
195
+ active = true
196
+ const controller = new AbortController()
197
+ const expiresAt = performance.now() + timeoutMs
198
+ const ensureActive = () => {
199
+ // A synchronous adapter can delay timers; late bytes still cannot pass.
200
+ if (performance.now() >= expiresAt) controller.abort(new Error('Verification timed out.'))
201
+ controller.signal.throwIfAborted()
202
+ }
203
+ const onAbort = () => controller.abort(context.signal?.reason)
204
+ context.signal?.addEventListener('abort', onAbort, { once: true })
205
+ const timer = setTimeout(
206
+ () => controller.abort(new Error('Verification timed out.')),
207
+ timeoutMs,
208
+ )
209
+ const observations: JsonClaimReceipt['observations'][number][] = []
210
+ let remaining = maxBytes
211
+ let removeAbort: (() => void) | undefined
212
+ try {
213
+ for (const source of new Set(requirements.map((item) => item.source))) {
214
+ ensureActive()
215
+ if (remaining < 1) return reject('The source byte allowance is exhausted.')
216
+ const request = Object.freeze({
217
+ scope,
218
+ runId,
219
+ iteration: context.iteration,
220
+ requestId: randomUUID(),
221
+ startedAt: Date.now(),
222
+ maxBytes: remaining,
223
+ signal: controller.signal,
224
+ })
225
+ pending++
226
+ const work = Promise.resolve()
227
+ .then(() => {
228
+ ensureActive()
229
+ return observe(source, request)
230
+ })
231
+ .finally(() => {
232
+ pending--
233
+ })
234
+ const aborted = new Promise<never>((_, fail) => {
235
+ const listener = () => fail(controller.signal.reason)
236
+ controller.signal.addEventListener('abort', listener, { once: true })
237
+ removeAbort = () => controller.signal.removeEventListener('abort', listener)
238
+ })
239
+ const observation = await Promise.race([work, aborted])
240
+ removeAbort?.()
241
+ ensureActive()
242
+ if (
243
+ !observation ||
244
+ observation.scope !== scope ||
245
+ observation.runId !== runId ||
246
+ observation.iteration !== context.iteration ||
247
+ observation.requestId !== request.requestId ||
248
+ observation.source !== source ||
249
+ observation.complete !== true ||
250
+ observation.kind !== 'current' ||
251
+ !Number.isSafeInteger(observation.observedAt) ||
252
+ observation.observedAt < request.startedAt ||
253
+ observation.observedAt > Date.now() ||
254
+ !(observation.bytes instanceof Uint8Array)
255
+ )
256
+ return reject('The observation is incomplete, historical or outside this review scope.')
257
+ if (observation.bytes.byteLength > remaining)
258
+ return reject('A source exceeded the byte allowance.')
259
+ const bytes = Buffer.from(observation.bytes)
260
+ remaining -= bytes.byteLength
261
+ const document: unknown = JSON.parse(
262
+ new TextDecoder('utf-8', { fatal: true }).decode(bytes),
263
+ )
264
+ for (const item of requirements.filter((item) => item.source === source)) {
265
+ const actual = select(document, item.parts)
266
+ if (!scalar(actual) || actual !== values[item.id])
267
+ return reject(`Claim ${item.id} does not match the selected source field.`)
268
+ if (Object.hasOwn(item, 'expected') && actual !== item.expected)
269
+ return reject(`Claim ${item.id} does not satisfy the configured postcondition.`)
270
+ }
271
+ observations.push({
272
+ source,
273
+ requestId: request.requestId,
274
+ observedAt: observation.observedAt,
275
+ bytes: bytes.byteLength,
276
+ sha256: createHash('sha256').update(bytes).digest('hex'),
277
+ })
278
+ }
279
+ ensureActive()
280
+ return {
281
+ accept: true,
282
+ receipt: { scope, runId, iteration: context.iteration, claims: values, observations },
283
+ }
284
+ } catch {
285
+ context.signal?.throwIfAborted()
286
+ return reject(
287
+ 'A current source could not be fully observed and parsed within the deadline.',
288
+ )
289
+ } finally {
290
+ clearTimeout(timer)
291
+ removeAbort?.()
292
+ context.signal?.removeEventListener('abort', onAbort)
293
+ controller.abort()
294
+ active = false
295
+ }
296
+ },
297
+ }
298
+ }
@@ -0,0 +1,16 @@
1
+ import { toErrorMessage } from '../utils/error.js'
2
+
3
+ /**
4
+ * Internal bridge for SDK preparation failures with a safe availability note
5
+ * and, when available, fully validated fallback evidence within the same budget.
6
+ * The cause remains diagnostic-only. Ordinary thrown errors never become context.
7
+ */
8
+ export class PreparationContextError extends Error {
9
+ constructor(
10
+ cause: unknown,
11
+ readonly context: string,
12
+ ) {
13
+ super(toErrorMessage(cause), { cause })
14
+ this.name = 'PreparationContextError'
15
+ }
16
+ }
@@ -62,7 +62,7 @@ export class RunTranscriptUnavailableError extends Error {
62
62
  /** What one compaction pass removed. */
63
63
  export interface ShedPass {
64
64
  readonly iteration: number
65
- readonly reason: 'threshold' | 'overflow'
65
+ readonly reason: Extract<PersistedRunEvent, { type: 'compaction_shed' }>['reason']
66
66
  readonly messages: readonly Message[]
67
67
  /** Where in the log the pass sits, for a caller correlating with events. */
68
68
  readonly seq: number
@@ -0,0 +1,271 @@
1
+ import type { BackgroundJob, BackgroundJobRegistry } from './registry.js'
2
+
3
+ /**
4
+ * What this adapter needs from a registry: the jobs' exits, and one job's
5
+ * current status. Structural rather than the class, for the reason
6
+ * `BackgroundJobRegistryRef` is: the kernel passes the real registry, and a
7
+ * test that needs two exits and nothing else should not have to spawn
8
+ * processes to produce them.
9
+ */
10
+ export type AwaitedJobSource = Pick<BackgroundJobRegistry, 'get' | 'onExit'>
11
+
12
+ /** Exits and the text that puts them in front of the model. See {@link AwaitedJobs.takeDelivery}. */
13
+ export interface DeliverableJobExits {
14
+ /** The notice text, already queued by the exit that produced it. */
15
+ readonly text: string
16
+ /** The exits that text accounts for, taken from the record. */
17
+ readonly exits: readonly BackgroundJob[]
18
+ }
19
+
20
+ /**
21
+ * Background jobs the model SAID it is waiting on.
22
+ *
23
+ * `CompletionInbox` gives a run a bounded, zero-token wait for a delegated
24
+ * task nobody is blocked on, and `holdForOutstandingWork` spends it: the
25
+ * model stops calling tools, the loop races the inbox against operator input,
26
+ * and the run only settles once the result is in the transcript or the grace
27
+ * is gone. Background shell jobs had none of it — so a model that started a
28
+ * job and then had nothing left to do improvised, and the recorded run
29
+ * (research/resident/results/2026-09-14-exploration-policy-terra-tui.json)
30
+ * shows what that costs: six `job read` polls, three `job list` polls and a
31
+ * `sleep 30`, each one a full context resend.
32
+ *
33
+ * This is the same three-method shape the hold already races —
34
+ * {@link hasPendingWork}, {@link waitForArrival}, {@link drain} — over the
35
+ * job registry instead of the task gateway.
36
+ *
37
+ * **Intent is stated, never inferred.** A job is only outstanding here once
38
+ * `wait_for_job` named it (see {@link expect}); job existence means nothing.
39
+ * That is the same distinction `CompletionInbox.expect` draws for a
40
+ * background task, and it is what keeps a dev server or a file watcher —
41
+ * started precisely so it would keep running — from holding every run of the
42
+ * session open for its grace period. The model that wants to wait says so.
43
+ */
44
+ export class AwaitedJobs {
45
+ /** Awaited and still running. Nothing else can hold a run open. */
46
+ private readonly outstanding = new Set<string>()
47
+ /** Exits since the last {@link drain}. */
48
+ private exits: BackgroundJob[] = []
49
+ private readonly arrivals = new Set<() => void>()
50
+ private detach?: () => void
51
+
52
+ constructor(
53
+ private readonly source: AwaitedJobSource,
54
+ /** Whose jobs these are — the run or the session the jobs are bound to. */
55
+ private readonly owner: string,
56
+ /**
57
+ * Whether the exit notice this run queues for the model is still
58
+ * unread. A second opinion on {@link noticesDelivered}, and it can
59
+ * only ever narrow what counts as pending.
60
+ *
61
+ * An exit is work only until the model has seen it, and this adapter is
62
+ * not what shows it: the text rides out on the next tool result
63
+ * (`attachNotice`), which is what normally happens, long before any
64
+ * hold opens. {@link noticesDelivered} is how that delivery says so,
65
+ * and it is the per-job record — the entry goes, so nothing can count
66
+ * it again.
67
+ *
68
+ * This stays because the two answer different questions. That one is
69
+ * reported BY a delivery site, so it is only as good as the sites that
70
+ * remember to call it; this reads the channel itself, and a channel
71
+ * with nothing queued cannot have news in it whatever the record says.
72
+ * It is also safe in one direction only: it can suppress a hold, never
73
+ * open one, so a stale `true` here is not a turn the model gets to
74
+ * spend — which is the failure this pair exists to prevent.
75
+ *
76
+ * `CompletionInbox.claim` draws the same line on the task side. It can
77
+ * name the task, because the call that delivers a completion knows
78
+ * which one it delivered; a notice is text by the time it reaches the
79
+ * tool result, so this asks the channel instead.
80
+ *
81
+ * Absent means nothing else consumes the notices, so a recorded exit is
82
+ * unread by definition.
83
+ */
84
+ private readonly unreadNotice?: () => boolean,
85
+ ) {}
86
+
87
+ /**
88
+ * Start listening.
89
+ *
90
+ * Returns the detach, and attaching twice is a no-op rather than a second
91
+ * subscription — the same rule `CompletionInbox.attach` follows, for the
92
+ * same reason: two subscriptions would record each exit twice.
93
+ */
94
+ attach(): () => void {
95
+ if (this.detach) return this.detach
96
+ this.detach = this.source.onExit((job) => {
97
+ // `onExit` is a broadcast over a registry a host may share between
98
+ // runs, and the filter is the same one the exit-notice channel
99
+ // applies in `runtime/query/index.ts`.
100
+ if (job.owner !== this.owner) return
101
+ // `outstanding` is the gate, so an id nobody awaited is ignored and
102
+ // a second announcement for the same job cannot queue twice.
103
+ if (!this.outstanding.delete(job.id)) return
104
+ this.exits.push(job)
105
+ for (const wake of [...this.arrivals]) wake()
106
+ })
107
+ return this.detach
108
+ }
109
+
110
+ /**
111
+ * Say that the model is waiting on this job's exit.
112
+ *
113
+ * Called by `wait_for_job`, and by nothing else: the wait is the whole
114
+ * signal. A job that has ALREADY stopped is not recorded, because the
115
+ * call that marks it is the same call that returns its output — holding
116
+ * the run open afterwards would buy a turn to read a result the model has
117
+ * just read. `CompletionInbox.expect` skips an already-claimed task for
118
+ * the same reason.
119
+ *
120
+ * An id the registry does not know is ignored rather than raised: the
121
+ * caller is about to fail on it anyway, and a marking call is not the
122
+ * place that decides what an unknown job means.
123
+ */
124
+ expect(id: string): void {
125
+ let job: BackgroundJob
126
+ try {
127
+ job = this.source.get(id)
128
+ } catch {
129
+ return
130
+ }
131
+ if (job.owner !== this.owner) return
132
+ if (job.status !== 'running') return
133
+ this.outstanding.add(id)
134
+ }
135
+
136
+ /**
137
+ * Recorded exits the model has not been shown yet.
138
+ *
139
+ * Both halves of the same question: {@link noticesDelivered} drops the
140
+ * entry when its notice goes out, and the `unreadNotice` constructor
141
+ * argument asks the channel whether anything is still queued. A queued
142
+ * exit whose notice has already been delivered is history, not pending
143
+ * work, and an exit nobody awaited is not this adapter's news to carry.
144
+ */
145
+ private get unreadExits(): boolean {
146
+ if (this.exits.length === 0) return false
147
+ return this.unreadNotice?.() ?? true
148
+ }
149
+
150
+ /** Whether an awaited job is still running, or one has exited unread. */
151
+ get hasPendingWork(): boolean {
152
+ return this.unreadExits || this.outstanding.size > 0
153
+ }
154
+
155
+ /**
156
+ * Wait for the next awaited job's exit, deadline or abort, whichever comes
157
+ * first. Aborting releases only this waiter; the jobs are untouched.
158
+ *
159
+ * Bounded by the caller, exactly as `CompletionInbox.waitForArrival` is: a
160
+ * job that never exits — a dev server someone did await — must not keep a
161
+ * run open, and only the run's own budget knows how long is long enough.
162
+ */
163
+ waitForArrival(timeoutMs: number, signal?: AbortSignal): Promise<void> {
164
+ if (signal?.aborted) return Promise.resolve()
165
+ if (this.unreadExits) return Promise.resolve()
166
+ if (this.outstanding.size === 0) return Promise.resolve()
167
+
168
+ return new Promise((resolve) => {
169
+ const finish = (): void => {
170
+ clearTimeout(timer)
171
+ this.arrivals.delete(finish)
172
+ signal?.removeEventListener('abort', finish)
173
+ resolve()
174
+ }
175
+ const timer = setTimeout(finish, timeoutMs)
176
+ // `unref` where the runtime has it, so a pending wait never keeps a
177
+ // process alive past the job it was waiting for.
178
+ ;(timer as { unref?: () => void }).unref?.()
179
+
180
+ this.arrivals.add(finish)
181
+ signal?.addEventListener('abort', finish, { once: true })
182
+ if (signal?.aborted) finish()
183
+ })
184
+ }
185
+
186
+ /**
187
+ * Say that the queued exit notices have been put in front of the model.
188
+ *
189
+ * Called by the tool-result delivery (`attachNotice`), which is where an
190
+ * exit normally reaches the model; {@link takeDelivery} does the same for
191
+ * the hold's own path by taking the entries as it delivers them.
192
+ *
193
+ * Every recorded exit goes, and that is per-job rather than a blunt
194
+ * clear: the channel hands over ALL its queued text at once, and an exit
195
+ * is recorded here in the same synchronous announcement that queues its
196
+ * notice, so the text just delivered is exactly the notices of the exits
197
+ * in hand. An exit recorded after this call keeps its entry, because its
198
+ * notice was queued after that text was taken.
199
+ *
200
+ * Without it the entry outlived the delivery, and the channel-level gate
201
+ * above was the only thing standing between a read exit and a model turn
202
+ * — a gate that reopens the moment ANY later job, awaited or not, queues
203
+ * a notice of its own.
204
+ */
205
+ noticesDelivered(): void {
206
+ this.exits = []
207
+ }
208
+
209
+ /**
210
+ * Take the recorded exits together with the text that delivers them, or
211
+ * take neither.
212
+ *
213
+ * The pairing is the whole method. Draining the exits first and then
214
+ * asking for the notice loses them on the branch that finds none: the
215
+ * records are gone, no text was written, and the exit the run held itself
216
+ * open for is delivered by nobody. So {@link drain} is not called until
217
+ * the delivery is certain, and an exit this could not deliver stays in
218
+ * hand for the next one.
219
+ */
220
+ takeDelivery(notice: () => string | undefined): DeliverableJobExits | undefined {
221
+ if (this.exits.length === 0) return undefined
222
+ const text = notice()
223
+ if (text === undefined) return undefined
224
+ return { text, exits: this.drain() }
225
+ }
226
+
227
+ /**
228
+ * Take every exit recorded since the last call, leaving none behind.
229
+ *
230
+ * Draining rather than peeking, for the reason `CompletionInbox.drain`
231
+ * gives: an exit that stays queued after being delivered is a duplicate
232
+ * waiting to happen. Callers that are delivering want
233
+ * {@link takeDelivery}, which will not take them without the notice that
234
+ * accounts for them.
235
+ */
236
+ drain(): readonly BackgroundJob[] {
237
+ if (this.exits.length === 0) return []
238
+ const exits = this.exits
239
+ this.exits = []
240
+ return exits
241
+ }
242
+
243
+ /**
244
+ * Awaited jobs still running.
245
+ *
246
+ * Read when a run ends, so it can say which wait it walked away from.
247
+ * Nothing here is stopped by being read — the ids are a statement, and a
248
+ * job's lifetime belongs to whoever owns it.
249
+ */
250
+ get outstandingJobIds(): readonly string[] {
251
+ return [...this.outstanding]
252
+ }
253
+
254
+ /**
255
+ * Stop listening. Safe to call more than once.
256
+ *
257
+ * A run that ends without this leaves its listener on a registry the host
258
+ * reuses across runs — the leak `CompletionInbox.close` exists to prevent,
259
+ * on the other subsystem.
260
+ */
261
+ close(): void {
262
+ this.detach?.()
263
+ this.detach = undefined
264
+ this.outstanding.clear()
265
+ this.exits = []
266
+ // Release anyone still waiting. A closed adapter would otherwise hold
267
+ // them to their own deadline for an exit that can no longer reach them.
268
+ for (const wake of [...this.arrivals]) wake()
269
+ this.arrivals.clear()
270
+ }
271
+ }
@@ -3,6 +3,7 @@ import { spawn } from 'node:child_process'
3
3
  import { SANDBOX_KILL_GRACE_MS } from '../../constants/sandbox/index.js'
4
4
  import { killTree } from '../../process/kill-tree.js'
5
5
  import { scrubInheritedEnv } from '../../tools/env-scrub.js'
6
+ import { awaitWithAbort } from '../../utils/await-with-abort.js'
6
7
 
7
8
  /**
8
9
  * Work that outlives a tool call, owned by whoever started it.
@@ -310,6 +311,32 @@ export class BackgroundJobRegistry {
310
311
  return entry.record
311
312
  }
312
313
 
314
+ /**
315
+ * Await one job's exit — the public counterpart to `onExit`, for a
316
+ * caller that wants a single result rather than a standing
317
+ * subscription. Resolves at once for a job that has already stopped, so
318
+ * a caller that lost the race against a fast-finishing job never blocks
319
+ * on a promise that would otherwise never settle.
320
+ *
321
+ * `signal` is honoured: an aborted wait rejects and detaches rather than
322
+ * holding the internal exit promise's continuation open for a job that
323
+ * may run for another hour. That only ends the WAIT — the job itself is
324
+ * untouched either way, exactly as a timed-out `kill`-less wait leaves
325
+ * it. See `wait-for-job-bounds.ts`, the first caller.
326
+ */
327
+ waitForExit(id: string, opts: { signal?: AbortSignal } = {}): Promise<BackgroundJob> {
328
+ const entry = this.jobs.get(id)
329
+ if (!entry) throw new UnknownBackgroundJobError({ id })
330
+ if (entry.record.status !== 'running') return Promise.resolve(entry.record)
331
+ // `entry` is the same object the `finalize` closure in `start()`
332
+ // mutates in place, so reading `entry.record` after `exit` settles
333
+ // sees the final status — the same trick `kill()` already relies on.
334
+ return awaitWithAbort(
335
+ entry.exit.then(() => entry.record),
336
+ opts.signal,
337
+ )
338
+ }
339
+
313
340
  /**
314
341
  * Output since `fromOffset`, with what the cap dropped stated.
315
342
  *
@@ -410,6 +437,17 @@ export function bindOwner(
410
437
  readonly workingDirectory: string
411
438
  readonly env?: Record<string, string>
412
439
  }) => JobProcess
440
+ /**
441
+ * Be told that the model said it is waiting on a job's exit.
442
+ *
443
+ * The registry does not keep this: wait-intent belongs to the RUN that
444
+ * expressed it, not to a registry a host may share across runs and
445
+ * sessions. The run passes its own recorder here — `AwaitedJobs`, which
446
+ * is what the iteration loop holds open for. Absent means nobody is
447
+ * listening, and `markAwaited` is then absent from the bound ref rather
448
+ * than present and silently doing nothing.
449
+ */
450
+ readonly onAwaited?: (id: string) => void
413
451
  } = {},
414
452
  ) {
415
453
  const mine = (id: string): BackgroundJob => {
@@ -443,6 +481,18 @@ export function bindOwner(
443
481
  mine(id)
444
482
  return registry.read(id, opts ?? {})
445
483
  },
484
+ waitForExit: (id: string, opts?: { signal?: AbortSignal }) => {
485
+ mine(id)
486
+ return registry.waitForExit(id, opts ?? {})
487
+ },
488
+ ...(defaults.onAwaited
489
+ ? {
490
+ markAwaited: (id: string) => {
491
+ mine(id)
492
+ defaults.onAwaited?.(id)
493
+ },
494
+ }
495
+ : {}),
446
496
  kill: async (id: string) => {
447
497
  mine(id)
448
498
  return await registry.kill(id)