@namzu/sdk 38.1.0 → 39.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 (534) hide show
  1. package/CHANGELOG.md +758 -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/contracts/schemas.js +1 -1
  30. package/dist/contracts/schemas.js.map +1 -1
  31. package/dist/eval/harness-protection.d.ts +18 -0
  32. package/dist/eval/harness-protection.d.ts.map +1 -0
  33. package/dist/eval/harness-protection.js +58 -0
  34. package/dist/eval/harness-protection.js.map +1 -0
  35. package/dist/eval/harness-verification.d.ts +6 -1
  36. package/dist/eval/harness-verification.d.ts.map +1 -1
  37. package/dist/eval/harness-verification.js +19 -2
  38. package/dist/eval/harness-verification.js.map +1 -1
  39. package/dist/eval/index.d.ts +1 -0
  40. package/dist/eval/index.d.ts.map +1 -1
  41. package/dist/eval/index.js.map +1 -1
  42. package/dist/manager/resident/activity.d.ts +50 -0
  43. package/dist/manager/resident/activity.d.ts.map +1 -0
  44. package/dist/manager/resident/activity.js +125 -0
  45. package/dist/manager/resident/activity.js.map +1 -0
  46. package/dist/manager/resident/agenda.d.ts +137 -0
  47. package/dist/manager/resident/agenda.d.ts.map +1 -0
  48. package/dist/manager/resident/agenda.js +586 -0
  49. package/dist/manager/resident/agenda.js.map +1 -0
  50. package/dist/manager/resident/consumption.d.ts +104 -0
  51. package/dist/manager/resident/consumption.d.ts.map +1 -0
  52. package/dist/manager/resident/consumption.js +233 -0
  53. package/dist/manager/resident/consumption.js.map +1 -0
  54. package/dist/manager/resident/delivery-window.d.ts +22 -0
  55. package/dist/manager/resident/delivery-window.d.ts.map +1 -0
  56. package/dist/manager/resident/delivery-window.js +78 -0
  57. package/dist/manager/resident/delivery-window.js.map +1 -0
  58. package/dist/manager/resident/evidence-recall.d.ts +24 -0
  59. package/dist/manager/resident/evidence-recall.d.ts.map +1 -0
  60. package/dist/manager/resident/evidence-recall.js +295 -0
  61. package/dist/manager/resident/evidence-recall.js.map +1 -0
  62. package/dist/manager/resident/history-disk.d.ts +10 -0
  63. package/dist/manager/resident/history-disk.d.ts.map +1 -0
  64. package/dist/manager/resident/history-disk.js +50 -0
  65. package/dist/manager/resident/history-disk.js.map +1 -0
  66. package/dist/manager/resident/history.d.ts +79 -0
  67. package/dist/manager/resident/history.d.ts.map +1 -0
  68. package/dist/manager/resident/history.js +203 -0
  69. package/dist/manager/resident/history.js.map +1 -0
  70. package/dist/manager/resident/host.d.ts +78 -0
  71. package/dist/manager/resident/host.d.ts.map +1 -0
  72. package/dist/manager/resident/host.js +252 -0
  73. package/dist/manager/resident/host.js.map +1 -0
  74. package/dist/manager/resident/initiative.d.ts +111 -0
  75. package/dist/manager/resident/initiative.d.ts.map +1 -0
  76. package/dist/manager/resident/initiative.js +129 -0
  77. package/dist/manager/resident/initiative.js.map +1 -0
  78. package/dist/manager/resident/learning-cycle.d.ts +131 -0
  79. package/dist/manager/resident/learning-cycle.d.ts.map +1 -0
  80. package/dist/manager/resident/learning-cycle.js +306 -0
  81. package/dist/manager/resident/learning-cycle.js.map +1 -0
  82. package/dist/manager/resident/learning-observation.d.ts +80 -0
  83. package/dist/manager/resident/learning-observation.d.ts.map +1 -0
  84. package/dist/manager/resident/learning-observation.js +22 -0
  85. package/dist/manager/resident/learning-observation.js.map +1 -0
  86. package/dist/manager/resident/learning-store.d.ts +106 -0
  87. package/dist/manager/resident/learning-store.d.ts.map +1 -0
  88. package/dist/manager/resident/learning-store.js +598 -0
  89. package/dist/manager/resident/learning-store.js.map +1 -0
  90. package/dist/manager/resident/learning.d.ts +726 -0
  91. package/dist/manager/resident/learning.d.ts.map +1 -0
  92. package/dist/manager/resident/learning.js +353 -0
  93. package/dist/manager/resident/learning.js.map +1 -0
  94. package/dist/manager/resident/loop.d.ts +31 -0
  95. package/dist/manager/resident/loop.d.ts.map +1 -0
  96. package/dist/manager/resident/loop.js +69 -0
  97. package/dist/manager/resident/loop.js.map +1 -0
  98. package/dist/manager/resident/outbox.d.ts +180 -0
  99. package/dist/manager/resident/outbox.d.ts.map +1 -0
  100. package/dist/manager/resident/outbox.js +214 -0
  101. package/dist/manager/resident/outbox.js.map +1 -0
  102. package/dist/manager/resident/proposal.d.ts +91 -0
  103. package/dist/manager/resident/proposal.d.ts.map +1 -0
  104. package/dist/manager/resident/proposal.js +75 -0
  105. package/dist/manager/resident/proposal.js.map +1 -0
  106. package/dist/manager/resident/store.d.ts +182 -0
  107. package/dist/manager/resident/store.d.ts.map +1 -0
  108. package/dist/manager/resident/store.js +199 -0
  109. package/dist/manager/resident/store.js.map +1 -0
  110. package/dist/manager/resident/tool-evidence.d.ts +71 -0
  111. package/dist/manager/resident/tool-evidence.d.ts.map +1 -0
  112. package/dist/manager/resident/tool-evidence.js +285 -0
  113. package/dist/manager/resident/tool-evidence.js.map +1 -0
  114. package/dist/manager/run/persistence.d.ts.map +1 -1
  115. package/dist/manager/run/persistence.js +6 -0
  116. package/dist/manager/run/persistence.js.map +1 -1
  117. package/dist/plugin/loader.d.ts.map +1 -1
  118. package/dist/plugin/loader.js +5 -3
  119. package/dist/plugin/loader.js.map +1 -1
  120. package/dist/prompt/coding-agent-doctrine.d.ts +1 -1
  121. package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
  122. package/dist/prompt/coding-agent-doctrine.js +2 -0
  123. package/dist/prompt/coding-agent-doctrine.js.map +1 -1
  124. package/dist/prompt/contributions.d.ts +5 -2
  125. package/dist/prompt/contributions.d.ts.map +1 -1
  126. package/dist/prompt/contributions.js.map +1 -1
  127. package/dist/prompt/index.d.ts +4 -0
  128. package/dist/prompt/index.d.ts.map +1 -1
  129. package/dist/prompt/index.js +2 -0
  130. package/dist/prompt/index.js.map +1 -1
  131. package/dist/prompt/resident-learning.d.ts +19 -0
  132. package/dist/prompt/resident-learning.d.ts.map +1 -0
  133. package/dist/prompt/resident-learning.js +125 -0
  134. package/dist/prompt/resident-learning.js.map +1 -0
  135. package/dist/prompt/resident-step.d.ts +36 -0
  136. package/dist/prompt/resident-step.d.ts.map +1 -0
  137. package/dist/prompt/resident-step.js +135 -0
  138. package/dist/prompt/resident-step.js.map +1 -0
  139. package/dist/provider/collect-chat-completion.d.ts +2 -1
  140. package/dist/provider/collect-chat-completion.d.ts.map +1 -1
  141. package/dist/provider/collect-chat-completion.js +7 -6
  142. package/dist/provider/collect-chat-completion.js.map +1 -1
  143. package/dist/provider/fallback.d.ts.map +1 -1
  144. package/dist/provider/fallback.js +2 -1
  145. package/dist/provider/fallback.js.map +1 -1
  146. package/dist/provider/stream-text.d.ts +16 -0
  147. package/dist/provider/stream-text.d.ts.map +1 -0
  148. package/dist/provider/stream-text.js +51 -0
  149. package/dist/provider/stream-text.js.map +1 -0
  150. package/dist/public-runtime.d.ts +22 -3
  151. package/dist/public-runtime.d.ts.map +1 -1
  152. package/dist/public-runtime.js +21 -3
  153. package/dist/public-runtime.js.map +1 -1
  154. package/dist/public-tools.d.ts +2 -0
  155. package/dist/public-tools.d.ts.map +1 -1
  156. package/dist/public-tools.js +2 -0
  157. package/dist/public-tools.js.map +1 -1
  158. package/dist/public-types.d.ts +29 -3
  159. package/dist/public-types.d.ts.map +1 -1
  160. package/dist/registry/index.d.ts +1 -1
  161. package/dist/registry/index.d.ts.map +1 -1
  162. package/dist/registry/tool/execute.d.ts +18 -0
  163. package/dist/registry/tool/execute.d.ts.map +1 -1
  164. package/dist/registry/tool/execute.js +43 -6
  165. package/dist/registry/tool/execute.js.map +1 -1
  166. package/dist/run/LimitChecker.js +3 -3
  167. package/dist/run/LimitChecker.js.map +1 -1
  168. package/dist/run/evidence-query.d.ts +41 -0
  169. package/dist/run/evidence-query.d.ts.map +1 -0
  170. package/dist/run/evidence-query.js +270 -0
  171. package/dist/run/evidence-query.js.map +1 -0
  172. package/dist/run/evidence-recall.d.ts +99 -0
  173. package/dist/run/evidence-recall.d.ts.map +1 -0
  174. package/dist/run/evidence-recall.js +633 -0
  175. package/dist/run/evidence-recall.js.map +1 -0
  176. package/dist/run/index.d.ts +2 -0
  177. package/dist/run/index.d.ts.map +1 -1
  178. package/dist/run/index.js +1 -0
  179. package/dist/run/index.js.map +1 -1
  180. package/dist/run/json-claim-verifier.d.ts +83 -0
  181. package/dist/run/json-claim-verifier.d.ts.map +1 -0
  182. package/dist/run/json-claim-verifier.js +200 -0
  183. package/dist/run/json-claim-verifier.js.map +1 -0
  184. package/dist/run/preparation-context-error.d.ts +10 -0
  185. package/dist/run/preparation-context-error.d.ts.map +1 -0
  186. package/dist/run/preparation-context-error.js +15 -0
  187. package/dist/run/preparation-context-error.js.map +1 -0
  188. package/dist/run-query/index.d.ts +3 -1
  189. package/dist/run-query/index.d.ts.map +1 -1
  190. package/dist/runtime/query/callback-inference.d.ts +8 -0
  191. package/dist/runtime/query/callback-inference.d.ts.map +1 -0
  192. package/dist/runtime/query/callback-inference.js +89 -0
  193. package/dist/runtime/query/callback-inference.js.map +1 -0
  194. package/dist/runtime/query/checkpoint.d.ts +4 -0
  195. package/dist/runtime/query/checkpoint.d.ts.map +1 -1
  196. package/dist/runtime/query/checkpoint.js +13 -0
  197. package/dist/runtime/query/checkpoint.js.map +1 -1
  198. package/dist/runtime/query/events.d.ts +7 -1
  199. package/dist/runtime/query/events.d.ts.map +1 -1
  200. package/dist/runtime/query/events.js +39 -12
  201. package/dist/runtime/query/events.js.map +1 -1
  202. package/dist/runtime/query/executor.d.ts +7 -1
  203. package/dist/runtime/query/executor.d.ts.map +1 -1
  204. package/dist/runtime/query/executor.js +38 -7
  205. package/dist/runtime/query/executor.js.map +1 -1
  206. package/dist/runtime/query/file-evidence-context.d.ts +5 -0
  207. package/dist/runtime/query/file-evidence-context.d.ts.map +1 -0
  208. package/dist/runtime/query/file-evidence-context.js +64 -0
  209. package/dist/runtime/query/file-evidence-context.js.map +1 -0
  210. package/dist/runtime/query/guard.d.ts.map +1 -1
  211. package/dist/runtime/query/guard.js +4 -0
  212. package/dist/runtime/query/guard.js.map +1 -1
  213. package/dist/runtime/query/index.d.ts +10 -1
  214. package/dist/runtime/query/index.d.ts.map +1 -1
  215. package/dist/runtime/query/index.js +40 -25
  216. package/dist/runtime/query/index.js.map +1 -1
  217. package/dist/runtime/query/iteration/index.d.ts +9 -31
  218. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  219. package/dist/runtime/query/iteration/index.js +231 -93
  220. package/dist/runtime/query/iteration/index.js.map +1 -1
  221. package/dist/runtime/query/iteration/phases/advisory.d.ts +2 -1
  222. package/dist/runtime/query/iteration/phases/advisory.d.ts.map +1 -1
  223. package/dist/runtime/query/iteration/phases/advisory.js +2 -1
  224. package/dist/runtime/query/iteration/phases/advisory.js.map +1 -1
  225. package/dist/runtime/query/iteration/phases/context.d.ts +2 -1
  226. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  227. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  228. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  229. package/dist/runtime/query/iteration/phases/tool-review.js +3 -0
  230. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  231. package/dist/runtime/query/iteration/provider-rejected-image.d.ts +2 -1
  232. package/dist/runtime/query/iteration/provider-rejected-image.d.ts.map +1 -1
  233. package/dist/runtime/query/iteration/provider-rejected-image.js +5 -2
  234. package/dist/runtime/query/iteration/provider-rejected-image.js.map +1 -1
  235. package/dist/runtime/query/iteration/stream-turn.d.ts +4 -1
  236. package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
  237. package/dist/runtime/query/iteration/stream-turn.js +22 -8
  238. package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
  239. package/dist/runtime/query/prompt-cache.d.ts.map +1 -1
  240. package/dist/runtime/query/prompt-cache.js +21 -42
  241. package/dist/runtime/query/prompt-cache.js.map +1 -1
  242. package/dist/runtime/query/resume-pending.d.ts +18 -33
  243. package/dist/runtime/query/resume-pending.d.ts.map +1 -1
  244. package/dist/runtime/query/resume-pending.js +59 -42
  245. package/dist/runtime/query/resume-pending.js.map +1 -1
  246. package/dist/runtime/query/review-policy.d.ts +4 -4
  247. package/dist/runtime/query/review-policy.d.ts.map +1 -1
  248. package/dist/runtime/query/review-policy.js +10 -9
  249. package/dist/runtime/query/review-policy.js.map +1 -1
  250. package/dist/runtime/query/sandbox-lifecycle.d.ts.map +1 -1
  251. package/dist/runtime/query/sandbox-lifecycle.js +4 -0
  252. package/dist/runtime/query/sandbox-lifecycle.js.map +1 -1
  253. package/dist/runtime/query/tool-output-budget.d.ts +10 -6
  254. package/dist/runtime/query/tool-output-budget.d.ts.map +1 -1
  255. package/dist/runtime/query/tool-output-budget.js +54 -12
  256. package/dist/runtime/query/tool-output-budget.js.map +1 -1
  257. package/dist/runtime/query/tooling.d.ts +3 -1
  258. package/dist/runtime/query/tooling.d.ts.map +1 -1
  259. package/dist/runtime/query/tooling.js +4 -0
  260. package/dist/runtime/query/tooling.js.map +1 -1
  261. package/dist/scheduler/completion-inbox.d.ts +3 -0
  262. package/dist/scheduler/completion-inbox.d.ts.map +1 -1
  263. package/dist/scheduler/completion-inbox.js +28 -0
  264. package/dist/scheduler/completion-inbox.js.map +1 -1
  265. package/dist/store/evidence/compaction-archive.d.ts +109 -0
  266. package/dist/store/evidence/compaction-archive.d.ts.map +1 -0
  267. package/dist/store/evidence/compaction-archive.js +125 -0
  268. package/dist/store/evidence/compaction-archive.js.map +1 -0
  269. package/dist/store/evidence/compaction-provenance.d.ts +7 -0
  270. package/dist/store/evidence/compaction-provenance.d.ts.map +1 -0
  271. package/dist/store/evidence/compaction-provenance.js +49 -0
  272. package/dist/store/evidence/compaction-provenance.js.map +1 -0
  273. package/dist/store/evidence/compaction-text.d.ts +16 -0
  274. package/dist/store/evidence/compaction-text.d.ts.map +1 -0
  275. package/dist/store/evidence/compaction-text.js +51 -0
  276. package/dist/store/evidence/compaction-text.js.map +1 -0
  277. package/dist/store/evidence/disk.d.ts +11 -0
  278. package/dist/store/evidence/disk.d.ts.map +1 -0
  279. package/dist/store/evidence/disk.js +367 -0
  280. package/dist/store/evidence/disk.js.map +1 -0
  281. package/dist/store/evidence/format.d.ts +25 -0
  282. package/dist/store/evidence/format.d.ts.map +1 -0
  283. package/dist/store/evidence/format.js +115 -0
  284. package/dist/store/evidence/format.js.map +1 -0
  285. package/dist/store/evidence/index-page.d.ts +208 -0
  286. package/dist/store/evidence/index-page.d.ts.map +1 -0
  287. package/dist/store/evidence/index-page.js +262 -0
  288. package/dist/store/evidence/index-page.js.map +1 -0
  289. package/dist/store/evidence/io.d.ts +24 -0
  290. package/dist/store/evidence/io.d.ts.map +1 -0
  291. package/dist/store/evidence/io.js +69 -0
  292. package/dist/store/evidence/io.js.map +1 -0
  293. package/dist/store/evidence/linked.d.ts +9 -0
  294. package/dist/store/evidence/linked.d.ts.map +1 -0
  295. package/dist/store/evidence/linked.js +314 -0
  296. package/dist/store/evidence/linked.js.map +1 -0
  297. package/dist/store/evidence/passages.d.ts +15 -0
  298. package/dist/store/evidence/passages.d.ts.map +1 -0
  299. package/dist/store/evidence/passages.js +72 -0
  300. package/dist/store/evidence/passages.js.map +1 -0
  301. package/dist/store/evidence/record-chain.d.ts +42 -0
  302. package/dist/store/evidence/record-chain.d.ts.map +1 -0
  303. package/dist/store/evidence/record-chain.js +111 -0
  304. package/dist/store/evidence/record-chain.js.map +1 -0
  305. package/dist/store/evidence/search-input.d.ts +21 -0
  306. package/dist/store/evidence/search-input.d.ts.map +1 -0
  307. package/dist/store/evidence/search-input.js +44 -0
  308. package/dist/store/evidence/search-input.js.map +1 -0
  309. package/dist/store/evidence/selection.d.ts +9 -0
  310. package/dist/store/evidence/selection.d.ts.map +1 -0
  311. package/dist/store/evidence/selection.js +17 -0
  312. package/dist/store/evidence/selection.js.map +1 -0
  313. package/dist/store/evidence/source-kind.d.ts +11 -0
  314. package/dist/store/evidence/source-kind.d.ts.map +1 -0
  315. package/dist/store/evidence/source-kind.js +26 -0
  316. package/dist/store/evidence/source-kind.js.map +1 -0
  317. package/dist/store/evidence/source-text.d.ts +51 -0
  318. package/dist/store/evidence/source-text.d.ts.map +1 -0
  319. package/dist/store/evidence/source-text.js +213 -0
  320. package/dist/store/evidence/source-text.js.map +1 -0
  321. package/dist/store/evidence/types.d.ts +162 -0
  322. package/dist/store/evidence/types.d.ts.map +1 -0
  323. package/dist/store/evidence/types.js +2 -0
  324. package/dist/store/evidence/types.js.map +1 -0
  325. package/dist/store/memory/disk.d.ts +2 -0
  326. package/dist/store/memory/disk.d.ts.map +1 -1
  327. package/dist/store/memory/disk.js +2 -1
  328. package/dist/store/memory/disk.js.map +1 -1
  329. package/dist/store/run/disk.d.ts +10 -0
  330. package/dist/store/run/disk.d.ts.map +1 -1
  331. package/dist/store/run/disk.js +87 -7
  332. package/dist/store/run/disk.js.map +1 -1
  333. package/dist/store/run/memory.d.ts +1 -0
  334. package/dist/store/run/memory.d.ts.map +1 -1
  335. package/dist/store/run/memory.js +10 -0
  336. package/dist/store/run/memory.js.map +1 -1
  337. package/dist/store/run/tool-executions.d.ts +13 -0
  338. package/dist/store/run/tool-executions.d.ts.map +1 -0
  339. package/dist/store/run/tool-executions.js +99 -0
  340. package/dist/store/run/tool-executions.js.map +1 -0
  341. package/dist/store/session/index.d.ts +2 -0
  342. package/dist/store/session/index.d.ts.map +1 -1
  343. package/dist/store/session/index.js +1 -0
  344. package/dist/store/session/index.js.map +1 -1
  345. package/dist/store/session/sqlite.d.ts +57 -0
  346. package/dist/store/session/sqlite.d.ts.map +1 -0
  347. package/dist/store/session/sqlite.js +430 -0
  348. package/dist/store/session/sqlite.js.map +1 -0
  349. package/dist/tools/builtins/job.d.ts.map +1 -1
  350. package/dist/tools/builtins/job.js +4 -5
  351. package/dist/tools/builtins/job.js.map +1 -1
  352. package/dist/tools/builtins/write-file.js +2 -2
  353. package/dist/tools/builtins/write-file.js.map +1 -1
  354. package/dist/tools/defineTool.d.ts +2 -1
  355. package/dist/tools/defineTool.d.ts.map +1 -1
  356. package/dist/tools/defineTool.js +1 -1
  357. package/dist/tools/defineTool.js.map +1 -1
  358. package/dist/tools/file-read-tracker.d.ts.map +1 -1
  359. package/dist/tools/file-read-tracker.js +12 -3
  360. package/dist/tools/file-read-tracker.js.map +1 -1
  361. package/dist/tools/resident-history.d.ts +10 -0
  362. package/dist/tools/resident-history.d.ts.map +1 -0
  363. package/dist/tools/resident-history.js +80 -0
  364. package/dist/tools/resident-history.js.map +1 -0
  365. package/dist/tools/resident-tool-evidence.d.ts +5 -0
  366. package/dist/tools/resident-tool-evidence.d.ts.map +1 -0
  367. package/dist/tools/resident-tool-evidence.js +57 -0
  368. package/dist/tools/resident-tool-evidence.js.map +1 -0
  369. package/dist/types/advisory/config.d.ts +7 -0
  370. package/dist/types/advisory/config.d.ts.map +1 -1
  371. package/dist/types/agent/reactive.d.ts +1 -0
  372. package/dist/types/agent/reactive.d.ts.map +1 -1
  373. package/dist/types/authorization/index.d.ts +9 -9
  374. package/dist/types/authorization/index.d.ts.map +1 -1
  375. package/dist/types/authorization/index.js +1 -1
  376. package/dist/types/authorization/index.js.map +1 -1
  377. package/dist/types/hitl/index.d.ts +4 -0
  378. package/dist/types/hitl/index.d.ts.map +1 -1
  379. package/dist/types/hitl/index.js.map +1 -1
  380. package/dist/types/message/index.d.ts +16 -2
  381. package/dist/types/message/index.d.ts.map +1 -1
  382. package/dist/types/message/index.js +8 -1
  383. package/dist/types/message/index.js.map +1 -1
  384. package/dist/types/provider/chat.d.ts +2 -0
  385. package/dist/types/provider/chat.d.ts.map +1 -1
  386. package/dist/types/provider/stream.d.ts +4 -0
  387. package/dist/types/provider/stream.d.ts.map +1 -1
  388. package/dist/types/run/answer-review.d.ts +34 -3
  389. package/dist/types/run/answer-review.d.ts.map +1 -1
  390. package/dist/types/run/config.d.ts +3 -0
  391. package/dist/types/run/config.d.ts.map +1 -1
  392. package/dist/types/run/entity.d.ts +7 -0
  393. package/dist/types/run/entity.d.ts.map +1 -1
  394. package/dist/types/run/events.d.ts +31 -8
  395. package/dist/types/run/events.d.ts.map +1 -1
  396. package/dist/types/run/events.js.map +1 -1
  397. package/dist/types/run/prepare-step.d.ts +53 -8
  398. package/dist/types/run/prepare-step.d.ts.map +1 -1
  399. package/dist/types/run/store.d.ts +29 -4
  400. package/dist/types/run/store.d.ts.map +1 -1
  401. package/dist/types/run/store.js +0 -28
  402. package/dist/types/run/store.js.map +1 -1
  403. package/dist/types/tool/index.d.ts +15 -1
  404. package/dist/types/tool/index.d.ts.map +1 -1
  405. package/dist/types/tool/index.js.map +1 -1
  406. package/dist/utils/await-with-abort.d.ts +8 -0
  407. package/dist/utils/await-with-abort.d.ts.map +1 -0
  408. package/dist/utils/await-with-abort.js +28 -0
  409. package/dist/utils/await-with-abort.js.map +1 -0
  410. package/dist/utils/evidence-time.d.ts +3 -0
  411. package/dist/utils/evidence-time.d.ts.map +1 -0
  412. package/dist/utils/evidence-time.js +10 -0
  413. package/dist/utils/evidence-time.js.map +1 -0
  414. package/dist/utils/evidence-tokens.d.ts +13 -0
  415. package/dist/utils/evidence-tokens.d.ts.map +1 -0
  416. package/dist/utils/evidence-tokens.js +29 -0
  417. package/dist/utils/evidence-tokens.js.map +1 -0
  418. package/package.json +1 -1
  419. package/src/advisory/executor.ts +15 -30
  420. package/src/advisory/history.ts +126 -0
  421. package/src/advisory/index.ts +5 -1
  422. package/src/agents/ReactiveAgent.ts +3 -0
  423. package/src/agents/runAgent.ts +14 -1
  424. package/src/compaction/manual.ts +30 -2
  425. package/src/compaction/summary.ts +4 -1
  426. package/src/config/runtime.ts +2 -2
  427. package/src/contracts/schemas.ts +1 -1
  428. package/src/eval/harness-protection.ts +79 -0
  429. package/src/eval/harness-verification.ts +31 -1
  430. package/src/eval/index.ts +1 -0
  431. package/src/manager/resident/activity.ts +187 -0
  432. package/src/manager/resident/agenda.ts +907 -0
  433. package/src/manager/resident/consumption.ts +311 -0
  434. package/src/manager/resident/delivery-window.ts +93 -0
  435. package/src/manager/resident/evidence-recall.ts +363 -0
  436. package/src/manager/resident/history-disk.ts +63 -0
  437. package/src/manager/resident/history.ts +312 -0
  438. package/src/manager/resident/host.ts +356 -0
  439. package/src/manager/resident/initiative.ts +205 -0
  440. package/src/manager/resident/learning-cycle.ts +499 -0
  441. package/src/manager/resident/learning-observation.ts +39 -0
  442. package/src/manager/resident/learning-store.ts +813 -0
  443. package/src/manager/resident/learning.ts +493 -0
  444. package/src/manager/resident/loop.ts +101 -0
  445. package/src/manager/resident/outbox.ts +307 -0
  446. package/src/manager/resident/proposal.ts +105 -0
  447. package/src/manager/resident/store.ts +257 -0
  448. package/src/manager/resident/tool-evidence.ts +412 -0
  449. package/src/manager/run/persistence.ts +6 -0
  450. package/src/plugin/loader.ts +8 -3
  451. package/src/prompt/coding-agent-doctrine.ts +2 -0
  452. package/src/prompt/contributions.ts +5 -2
  453. package/src/prompt/index.ts +4 -0
  454. package/src/prompt/resident-learning.ts +143 -0
  455. package/src/prompt/resident-step.ts +176 -0
  456. package/src/provider/collect-chat-completion.ts +7 -6
  457. package/src/provider/fallback.ts +2 -1
  458. package/src/provider/stream-text.ts +56 -0
  459. package/src/public-runtime.ts +44 -0
  460. package/src/public-tools.ts +3 -0
  461. package/src/public-types.ts +165 -0
  462. package/src/registry/index.ts +1 -1
  463. package/src/registry/tool/execute.ts +56 -9
  464. package/src/run/LimitChecker.ts +3 -3
  465. package/src/run/evidence-query.ts +333 -0
  466. package/src/run/evidence-recall.ts +854 -0
  467. package/src/run/index.ts +11 -0
  468. package/src/run/json-claim-verifier.ts +298 -0
  469. package/src/run/preparation-context-error.ts +16 -0
  470. package/src/run-query/index.ts +1 -1
  471. package/src/runtime/query/callback-inference.ts +94 -0
  472. package/src/runtime/query/checkpoint.ts +14 -0
  473. package/src/runtime/query/events.ts +46 -14
  474. package/src/runtime/query/executor.ts +51 -9
  475. package/src/runtime/query/file-evidence-context.ts +65 -0
  476. package/src/runtime/query/guard.ts +2 -0
  477. package/src/runtime/query/index.ts +50 -27
  478. package/src/runtime/query/iteration/index.ts +269 -86
  479. package/src/runtime/query/iteration/phases/advisory.ts +3 -0
  480. package/src/runtime/query/iteration/phases/context.ts +2 -0
  481. package/src/runtime/query/iteration/phases/tool-review.ts +3 -0
  482. package/src/runtime/query/iteration/provider-rejected-image.ts +6 -1
  483. package/src/runtime/query/iteration/stream-turn.ts +35 -8
  484. package/src/runtime/query/prompt-cache.ts +24 -47
  485. package/src/runtime/query/resume-pending.ts +65 -40
  486. package/src/runtime/query/review-policy.ts +13 -9
  487. package/src/runtime/query/sandbox-lifecycle.ts +3 -0
  488. package/src/runtime/query/tool-output-budget.ts +65 -13
  489. package/src/runtime/query/tooling.ts +7 -1
  490. package/src/scheduler/completion-inbox.ts +26 -0
  491. package/src/store/evidence/compaction-archive.ts +139 -0
  492. package/src/store/evidence/compaction-provenance.ts +52 -0
  493. package/src/store/evidence/compaction-text.ts +61 -0
  494. package/src/store/evidence/disk.ts +461 -0
  495. package/src/store/evidence/format.ts +126 -0
  496. package/src/store/evidence/index-page.ts +292 -0
  497. package/src/store/evidence/io.ts +95 -0
  498. package/src/store/evidence/linked.ts +365 -0
  499. package/src/store/evidence/passages.ts +88 -0
  500. package/src/store/evidence/record-chain.ts +108 -0
  501. package/src/store/evidence/search-input.ts +62 -0
  502. package/src/store/evidence/selection.ts +25 -0
  503. package/src/store/evidence/source-kind.ts +36 -0
  504. package/src/store/evidence/source-text.ts +285 -0
  505. package/src/store/evidence/types.ts +177 -0
  506. package/src/store/memory/disk.ts +4 -1
  507. package/src/store/run/disk.ts +110 -8
  508. package/src/store/run/memory.ts +10 -0
  509. package/src/store/run/tool-executions.ts +112 -0
  510. package/src/store/session/index.ts +2 -0
  511. package/src/store/session/sqlite.ts +584 -0
  512. package/src/tools/builtins/job.ts +4 -5
  513. package/src/tools/builtins/write-file.ts +2 -2
  514. package/src/tools/defineTool.ts +4 -2
  515. package/src/tools/file-read-tracker.ts +8 -2
  516. package/src/tools/resident-history.ts +86 -0
  517. package/src/tools/resident-tool-evidence.ts +68 -0
  518. package/src/types/advisory/config.ts +7 -0
  519. package/src/types/agent/reactive.ts +1 -0
  520. package/src/types/authorization/index.ts +2 -2
  521. package/src/types/hitl/index.ts +4 -0
  522. package/src/types/message/index.ts +20 -0
  523. package/src/types/provider/chat.ts +2 -0
  524. package/src/types/provider/stream.ts +4 -0
  525. package/src/types/run/answer-review.ts +34 -3
  526. package/src/types/run/config.ts +3 -0
  527. package/src/types/run/entity.ts +7 -0
  528. package/src/types/run/events.ts +31 -8
  529. package/src/types/run/prepare-step.ts +59 -8
  530. package/src/types/run/store.ts +35 -4
  531. package/src/types/tool/index.ts +19 -1
  532. package/src/utils/await-with-abort.ts +26 -0
  533. package/src/utils/evidence-time.ts +9 -0
  534. package/src/utils/evidence-tokens.ts +32 -0
@@ -0,0 +1,813 @@
1
+ import { createHash, randomUUID } from 'node:crypto'
2
+ import {
3
+ closeSync,
4
+ existsSync,
5
+ fsyncSync,
6
+ linkSync,
7
+ lstatSync,
8
+ mkdirSync,
9
+ openSync,
10
+ readFileSync,
11
+ unlinkSync,
12
+ writeFileSync,
13
+ } from 'node:fs'
14
+ import { createRequire } from 'node:module'
15
+ import { dirname, join, resolve } from 'node:path'
16
+ import type { DatabaseSync } from 'node:sqlite'
17
+ import { z } from 'zod'
18
+ import type { ProjectId, TenantId } from '../../types/ids/index.js'
19
+ import { asProjectId, asTenantId } from '../../utils/id.js'
20
+ import {
21
+ type ResidentLearningCycleEvent,
22
+ type ResidentLearningCycleOptions,
23
+ type ResidentLearningCycleResult,
24
+ runResidentLearningCycle,
25
+ } from './learning-cycle.js'
26
+ import {
27
+ type ResidentLearningObservation,
28
+ type ResidentLearningObservationRecord,
29
+ type ResidentLearningTarget,
30
+ learningObservationSchema,
31
+ learningTargetSchema,
32
+ } from './learning-observation.js'
33
+ import { hashResidentSkill } from './learning.js'
34
+
35
+ const uuid = z
36
+ .string()
37
+ .uuid()
38
+ .transform((id) => id.toLowerCase())
39
+ const digest = (text: string | Buffer) => createHash('sha256').update(text).digest('hex')
40
+ const MAX_EVENT_BYTES = 256 * 1024
41
+ const MAX_ARTIFACT_BYTES = 8 * 1024 * 1024
42
+ const MAX_EVENTS = 4096
43
+ const MAX_ARTIFACTS = 256
44
+ const NO_LATER_PASS = `NOT EXISTS (
45
+ SELECT 1 FROM observations newer WHERE newer.tenant_id=o.tenant_id
46
+ AND newer.project_id=o.project_id AND newer.agent_key=o.agent_key
47
+ AND newer.skill_name=o.skill_name AND newer.evaluator_revision=o.evaluator_revision
48
+ AND newer.baseline_revision=o.baseline_revision AND newer.task_key=o.task_key
49
+ AND newer.ordinal>o.ordinal AND json_extract(newer.body, '$.outcome')='passed'
50
+ )`
51
+ const OBSERVATIONS_SCHEMA = `
52
+ CREATE TABLE observations (
53
+ ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
54
+ tenant_id TEXT NOT NULL, project_id TEXT NOT NULL, agent_key TEXT NOT NULL,
55
+ run_id TEXT NOT NULL, evaluator_revision TEXT NOT NULL, skill_name TEXT NOT NULL,
56
+ baseline_revision TEXT NOT NULL, task_key TEXT NOT NULL,
57
+ eligible INTEGER NOT NULL, body TEXT NOT NULL,
58
+ UNIQUE(tenant_id, project_id, agent_key, run_id, evaluator_revision, skill_name)
59
+ );
60
+ CREATE INDEX observations_select ON observations(
61
+ tenant_id, project_id, agent_key, skill_name, evaluator_revision, baseline_revision, eligible, ordinal
62
+ );
63
+ CREATE INDEX observations_task ON observations(
64
+ tenant_id, project_id, agent_key, skill_name, evaluator_revision, baseline_revision, task_key, ordinal
65
+ );
66
+ CREATE TABLE observation_attempts (
67
+ tenant_id TEXT NOT NULL, project_id TEXT NOT NULL, agent_key TEXT NOT NULL,
68
+ skill_name TEXT NOT NULL, evaluator_revision TEXT NOT NULL,
69
+ baseline_revision TEXT NOT NULL, task_key TEXT NOT NULL,
70
+ cycle_id TEXT NOT NULL REFERENCES cycles(id),
71
+ PRIMARY KEY(tenant_id, project_id, agent_key, skill_name, evaluator_revision, baseline_revision, task_key)
72
+ );
73
+ `
74
+ const SCHEMA = `
75
+ CREATE TABLE cycles (
76
+ ordinal INTEGER PRIMARY KEY AUTOINCREMENT, id TEXT NOT NULL UNIQUE,
77
+ tenant_id TEXT NOT NULL, project_id TEXT NOT NULL, agent_key TEXT NOT NULL,
78
+ parent_id TEXT, skill_name TEXT, status TEXT NOT NULL,
79
+ sequence INTEGER NOT NULL, started_at INTEGER NOT NULL, updated_at INTEGER NOT NULL,
80
+ candidate_hash TEXT, result TEXT,
81
+ tokens INTEGER NOT NULL DEFAULT 0, cost_usd REAL NOT NULL DEFAULT 0,
82
+ receipts INTEGER NOT NULL DEFAULT 0, unknown_tokens INTEGER NOT NULL DEFAULT 0,
83
+ unknown_costs INTEGER NOT NULL DEFAULT 0
84
+ );
85
+ CREATE INDEX cycles_scope ON cycles(tenant_id, project_id, agent_key, ordinal);
86
+ CREATE TABLE events (
87
+ cycle_id TEXT NOT NULL REFERENCES cycles(id), sequence INTEGER NOT NULL,
88
+ body TEXT NOT NULL, PRIMARY KEY(cycle_id, sequence)
89
+ );
90
+ CREATE TABLE artifacts (
91
+ cycle_id TEXT NOT NULL REFERENCES cycles(id), name TEXT NOT NULL, hash TEXT NOT NULL,
92
+ bytes INTEGER NOT NULL, PRIMARY KEY(cycle_id, name)
93
+ );
94
+ CREATE TABLE usage_receipts (
95
+ cycle_id TEXT NOT NULL REFERENCES cycles(id), run_id TEXT NOT NULL,
96
+ PRIMARY KEY(cycle_id, run_id)
97
+ );
98
+ `
99
+
100
+ /** @experimental Private parent directories and backup policy remain host responsibilities. */
101
+ export interface SqliteResidentLearningStoreOptions {
102
+ readonly databasePath: string
103
+ readonly artifactsPath: string
104
+ readonly scope: {
105
+ readonly tenantId: TenantId
106
+ readonly projectId: ProjectId
107
+ readonly agentKey: string
108
+ }
109
+ readonly readOnly?: boolean
110
+ }
111
+
112
+ /** @experimental A content-addressed immutable JSON artifact, scoped through its owning cycle. */
113
+ export interface ResidentLearningArtifact {
114
+ readonly name: string
115
+ readonly hash: string
116
+ readonly bytes: number
117
+ }
118
+
119
+ /** @experimental Recorded lower bounds; absence of a final result means completeness is unknown. */
120
+ export interface ResidentLearningRecordedUsage {
121
+ readonly tokens: number
122
+ readonly costUsd: number
123
+ readonly receipts: number
124
+ readonly unknownTokens: number
125
+ readonly unknownCosts: number
126
+ }
127
+
128
+ /** @experimental Running/pending records require inspection; neither implies a live executor. */
129
+ export interface ResidentLearningCycleSummary {
130
+ readonly cycleId: string
131
+ readonly ordinal: number
132
+ readonly parentCycleId: string | null
133
+ readonly skillName: string | null
134
+ readonly status: ResidentLearningCycleResult['status'] | 'running' | 'activation-pending'
135
+ readonly sequence: number
136
+ readonly startedAt: number
137
+ readonly updatedAt: number
138
+ readonly candidateRevision: string | null
139
+ readonly result: ResidentLearningCycleResult | null
140
+ readonly recordedUsage: ResidentLearningRecordedUsage
141
+ }
142
+
143
+ type CycleRow = {
144
+ id: string
145
+ ordinal: number
146
+ tenant_id: string
147
+ project_id: string
148
+ agent_key: string
149
+ parent_id: string | null
150
+ skill_name: string | null
151
+ status: ResidentLearningCycleSummary['status']
152
+ sequence: number
153
+ started_at: number
154
+ updated_at: number
155
+ candidate_hash: string | null
156
+ result: string | null
157
+ tokens: number
158
+ cost_usd: number
159
+ receipts: number
160
+ unknown_tokens: number
161
+ unknown_costs: number
162
+ }
163
+
164
+ const summary = (row: CycleRow): ResidentLearningCycleSummary => ({
165
+ cycleId: row.id,
166
+ ordinal: row.ordinal,
167
+ parentCycleId: row.parent_id,
168
+ skillName: row.skill_name,
169
+ status: row.status,
170
+ sequence: row.sequence,
171
+ startedAt: row.started_at,
172
+ updatedAt: row.updated_at,
173
+ candidateRevision: row.candidate_hash,
174
+ result: row.result === null ? null : JSON.parse(row.result),
175
+ recordedUsage: {
176
+ tokens: row.tokens,
177
+ costUsd: row.cost_usd,
178
+ receipts: row.receipts,
179
+ unknownTokens: row.unknown_tokens,
180
+ unknownCosts: row.unknown_costs,
181
+ },
182
+ })
183
+
184
+ /**
185
+ * @experimental Authoritative experiment journal and query index in one transaction.
186
+ * Large JSON artifacts are published completely before their SQLite references.
187
+ * No database transaction spans an await, model request or artifact write. JSONL
188
+ * exports are observations, never a second writable authority or a replay queue.
189
+ */
190
+ export class SqliteResidentLearningStore {
191
+ readonly databasePath: string
192
+ readonly artifactsPath: string
193
+ private readonly scope: SqliteResidentLearningStoreOptions['scope']
194
+ private readonly readOnly: boolean
195
+
196
+ constructor(options: SqliteResidentLearningStoreOptions) {
197
+ this.databasePath = resolve(options.databasePath)
198
+ this.artifactsPath = resolve(options.artifactsPath)
199
+ this.scope = Object.freeze({
200
+ tenantId: asTenantId(options.scope.tenantId.toLowerCase()),
201
+ projectId: asProjectId(options.scope.projectId.toLowerCase()),
202
+ agentKey: z
203
+ .string()
204
+ .regex(/^[a-z0-9][a-z0-9_-]{0,63}$/)
205
+ .parse(options.scope.agentKey),
206
+ })
207
+ this.readOnly = options.readOnly === true
208
+ }
209
+
210
+ private use<T>(write: boolean, operation: (db: DatabaseSync) => T): T {
211
+ if (write && this.readOnly) throw new Error('Learning database is read-only.')
212
+ let Database: typeof DatabaseSync
213
+ try {
214
+ Database = (createRequire(import.meta.url)('node:sqlite') as typeof import('node:sqlite'))
215
+ .DatabaseSync
216
+ } catch (error) {
217
+ throw new Error('SqliteResidentLearningStore requires Node.js 22.13 or newer.', {
218
+ cause: error,
219
+ })
220
+ }
221
+ if (!this.readOnly) mkdirSync(dirname(this.databasePath), { recursive: true, mode: 0o700 })
222
+ const db = new Database(this.databasePath, { readOnly: this.readOnly })
223
+ try {
224
+ db.exec('PRAGMA busy_timeout = 5000; PRAGMA foreign_keys = ON;')
225
+ if (!this.readOnly) db.exec('PRAGMA journal_mode = DELETE; PRAGMA synchronous = FULL;')
226
+ db.exec(write ? 'BEGIN IMMEDIATE' : 'BEGIN')
227
+ try {
228
+ const version = Number(db.prepare('PRAGMA user_version').get()?.user_version)
229
+ if (version === 0 && write) {
230
+ if (
231
+ db
232
+ .prepare(
233
+ "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' LIMIT 1",
234
+ )
235
+ .get()
236
+ )
237
+ throw new Error('Refusing to initialize a nonempty learning database.')
238
+ db.exec(`${SCHEMA} ${OBSERVATIONS_SCHEMA} PRAGMA user_version = 2;`)
239
+ } else if (version === 1 && write) {
240
+ db.exec(`${OBSERVATIONS_SCHEMA} PRAGMA user_version = 2;`)
241
+ } else if (version !== 1 && version !== 2)
242
+ throw new Error(`Unsupported learning database version ${version}.`)
243
+ const value = operation(db)
244
+ db.exec('COMMIT')
245
+ return value
246
+ } catch (error) {
247
+ db.exec('ROLLBACK')
248
+ throw error
249
+ }
250
+ } finally {
251
+ db.close()
252
+ }
253
+ }
254
+
255
+ private owned(db: DatabaseSync, id: string): CycleRow | null {
256
+ const row = db.prepare('SELECT * FROM cycles WHERE id = ?').get(id) as CycleRow | undefined
257
+ if (!row) return null
258
+ if (
259
+ row.tenant_id !== this.scope.tenantId ||
260
+ row.project_id !== this.scope.projectId ||
261
+ row.agent_key !== this.scope.agentKey
262
+ )
263
+ throw new Error('Learning cycle does not belong to this tenant, project and resident.')
264
+ return row
265
+ }
266
+
267
+ /** Immutable, idempotent observations. Regrading requires a different evaluator revision. */
268
+ async observe(input: ResidentLearningObservation): Promise<void> {
269
+ const value = learningObservationSchema.parse(input)
270
+ const body = JSON.stringify(value)
271
+ this.use(true, (db) => {
272
+ const scope = [this.scope.tenantId, this.scope.projectId, this.scope.agentKey]
273
+ const previous = db
274
+ .prepare(
275
+ 'SELECT body FROM observations WHERE tenant_id=? AND project_id=? AND agent_key=? AND run_id=? AND evaluator_revision=? AND skill_name=?',
276
+ )
277
+ .get(...scope, value.runId, value.evaluatorRevision, value.skillName)
278
+ if (previous) {
279
+ if (previous.body !== body)
280
+ throw new Error('Learning observation already has different content.')
281
+ return
282
+ }
283
+ db.prepare(`INSERT INTO observations
284
+ (tenant_id, project_id, agent_key, run_id, evaluator_revision, skill_name, baseline_revision, task_key, eligible, body)
285
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(
286
+ ...scope,
287
+ value.runId,
288
+ value.evaluatorRevision,
289
+ value.skillName,
290
+ value.baselineRevision,
291
+ value.taskKey,
292
+ Number(value.outcome === 'failed' && value.usageComplete),
293
+ body,
294
+ )
295
+ })
296
+ }
297
+
298
+ private observationsQuery() {
299
+ return `SELECT o.ordinal, o.body, a.cycle_id AS attemptedCycleId FROM observations o
300
+ LEFT JOIN observation_attempts a ON
301
+ a.tenant_id=o.tenant_id AND a.project_id=o.project_id AND a.agent_key=o.agent_key
302
+ AND a.skill_name=o.skill_name AND a.evaluator_revision=o.evaluator_revision
303
+ AND a.baseline_revision=o.baseline_revision AND a.task_key=o.task_key
304
+ WHERE o.tenant_id=? AND o.project_id=? AND o.agent_key=?`
305
+ }
306
+
307
+ private observationRecord(row: {
308
+ ordinal: number
309
+ body: string
310
+ attemptedCycleId: string | null
311
+ }): ResidentLearningObservationRecord {
312
+ const value = learningObservationSchema.parse(JSON.parse(row.body))
313
+ return Object.freeze({
314
+ ...value,
315
+ evidence: Object.freeze(value.evidence),
316
+ ordinal: row.ordinal,
317
+ attemptedCycleId: row.attemptedCycleId,
318
+ })
319
+ }
320
+
321
+ /** Ordered inspection; summaries are host observations, not inferred task completion. */
322
+ async observations(
323
+ options: { readonly after?: number; readonly limit?: number } = {},
324
+ ): Promise<readonly ResidentLearningObservationRecord[]> {
325
+ const after = z
326
+ .number()
327
+ .int()
328
+ .nonnegative()
329
+ .safe()
330
+ .parse(options.after ?? 0)
331
+ const limit = z
332
+ .number()
333
+ .int()
334
+ .min(1)
335
+ .max(100)
336
+ .parse(options.limit ?? 20)
337
+ if (!existsSync(this.databasePath)) return []
338
+ return this.use(false, (db) => {
339
+ if (Number(db.prepare('PRAGMA user_version').get()?.user_version) === 1) return []
340
+ const rows = db
341
+ .prepare(`${this.observationsQuery()} AND o.ordinal>? ORDER BY o.ordinal LIMIT ?`)
342
+ .all(this.scope.tenantId, this.scope.projectId, this.scope.agentKey, after, limit)
343
+ return rows.map((row) =>
344
+ this.observationRecord(
345
+ row as { ordinal: number; body: string; attemptedCycleId: string | null },
346
+ ),
347
+ )
348
+ })
349
+ }
350
+
351
+ /** Oldest eligible unattempted task across current targets; no model call or claim is made. */
352
+ async selectObservation(
353
+ input: readonly ResidentLearningTarget[],
354
+ ): Promise<ResidentLearningObservationRecord | null> {
355
+ const targets = z.array(learningTargetSchema).min(1).max(16).parse(input)
356
+ if (new Set(targets.map((t) => t.skillName)).size !== targets.length)
357
+ throw new Error('Learning selection requires one current evaluator per skill.')
358
+ if (!existsSync(this.databasePath)) return null
359
+ return this.use(false, (db) => {
360
+ if (Number(db.prepare('PRAGMA user_version').get()?.user_version) === 1) return null
361
+ const rows = targets.flatMap((target) => {
362
+ const row = db
363
+ .prepare(`${this.observationsQuery()} AND o.skill_name=?
364
+ AND o.evaluator_revision=? AND o.baseline_revision=? AND o.eligible=1
365
+ AND a.cycle_id IS NULL AND ${NO_LATER_PASS} ORDER BY o.ordinal LIMIT 1`)
366
+ .get(
367
+ this.scope.tenantId,
368
+ this.scope.projectId,
369
+ this.scope.agentKey,
370
+ target.skillName,
371
+ target.evaluatorRevision,
372
+ target.baselineRevision,
373
+ )
374
+ return row
375
+ ? [
376
+ this.observationRecord(
377
+ row as { ordinal: number; body: string; attemptedCycleId: string | null },
378
+ ),
379
+ ]
380
+ : []
381
+ })
382
+ return rows.sort((a, b) => a.ordinal - b.ordinal)[0] ?? null
383
+ })
384
+ }
385
+
386
+ private claimObservation(db: DatabaseSync, event: ResidentLearningCycleEvent): void {
387
+ if (event.kind !== 'started' || event.data.observation === undefined) return
388
+ const selected = z
389
+ .object({ ordinal: z.number().int().positive().safe() })
390
+ .parse(event.data.observation)
391
+ const row = db
392
+ .prepare(`${this.observationsQuery()} AND o.ordinal=? AND ${NO_LATER_PASS}`)
393
+ .get(this.scope.tenantId, this.scope.projectId, this.scope.agentKey, selected.ordinal)
394
+ if (!row) throw new Error('Selected learning observation is not retained in this scope.')
395
+ const value = this.observationRecord(
396
+ row as { ordinal: number; body: string; attemptedCycleId: string | null },
397
+ )
398
+ if (value.outcome !== 'failed' || !value.usageComplete || value.attemptedCycleId)
399
+ throw new Error('Selected learning observation is ineligible or already attempted.')
400
+ if (
401
+ event.data.skillName !== value.skillName ||
402
+ event.data.baselineRevision !== value.baselineRevision ||
403
+ JSON.stringify(event.data.failure) !==
404
+ JSON.stringify({ evidence: value.evidence, trace: value.trace })
405
+ )
406
+ throw new Error('Selected observation differs from the current learning baseline or failure.')
407
+ db.prepare('INSERT INTO observation_attempts VALUES (?, ?, ?, ?, ?, ?, ?, ?)').run(
408
+ this.scope.tenantId,
409
+ this.scope.projectId,
410
+ this.scope.agentKey,
411
+ value.skillName,
412
+ value.evaluatorRevision,
413
+ value.baselineRevision,
414
+ value.taskKey,
415
+ event.cycleId,
416
+ )
417
+ }
418
+
419
+ /** Identical event retries are idempotent. Different content at the same sequence is refused. */
420
+ async append(input: ResidentLearningCycleEvent): Promise<void> {
421
+ const event = z
422
+ .object({
423
+ cycleId: uuid,
424
+ sequence: z.number().int().min(1).max(MAX_EVENTS),
425
+ kind: z.enum([
426
+ 'started',
427
+ 'stage-started',
428
+ 'stage-finished',
429
+ 'usage',
430
+ 'exploration',
431
+ 'candidate',
432
+ 'evaluation',
433
+ 'activation-requested',
434
+ 'finished',
435
+ ]),
436
+ stage: z.enum(['explore', 'generate', 'verification', 'confirmation']).optional(),
437
+ data: z.record(z.unknown()),
438
+ })
439
+ .parse(input)
440
+ const body = JSON.stringify(event)
441
+ if (Buffer.byteLength(body) > MAX_EVENT_BYTES)
442
+ throw new Error('Learning event exceeds 256 KiB; retain large content as an artifact.')
443
+ this.use(true, (db) => {
444
+ let row = this.owned(db, event.cycleId)
445
+ if (row) {
446
+ const previous = db
447
+ .prepare('SELECT body FROM events WHERE cycle_id = ? AND sequence = ?')
448
+ .get(event.cycleId, event.sequence)
449
+ if (previous) {
450
+ if (previous.body !== body)
451
+ throw new Error('Learning event sequence already has different content.')
452
+ return
453
+ }
454
+ if (row.result !== null || event.sequence !== row.sequence + 1)
455
+ throw new Error('Learning journal is finished or its sequence has a gap.')
456
+ } else {
457
+ if (event.sequence !== 1 || !['started', 'finished'].includes(event.kind))
458
+ throw new Error(
459
+ 'Learning journal must begin with a start or a terminal preflight failure.',
460
+ )
461
+ if (
462
+ event.kind === 'started' &&
463
+ (event.data.tenantId !== this.scope.tenantId ||
464
+ event.data.agentKey !== this.scope.agentKey)
465
+ )
466
+ throw new Error('Learning start does not match the bound resident.')
467
+ const parent =
468
+ event.data.parentCycleId === undefined ? null : uuid.parse(event.data.parentCycleId)
469
+ if (parent && !this.owned(db, parent))
470
+ throw new Error('Parent learning cycle is not retained in this scope.')
471
+ const skillName =
472
+ event.data.skillName === undefined
473
+ ? null
474
+ : z
475
+ .string()
476
+ .regex(/^[a-z0-9][a-z0-9_-]{0,63}$/)
477
+ .parse(event.data.skillName)
478
+ const now = Date.now()
479
+ db.prepare(
480
+ 'INSERT INTO cycles (id, tenant_id, project_id, agent_key, parent_id, skill_name, status, sequence, started_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, 0, ?, ?)',
481
+ ).run(
482
+ event.cycleId,
483
+ this.scope.tenantId,
484
+ this.scope.projectId,
485
+ this.scope.agentKey,
486
+ parent,
487
+ skillName,
488
+ 'running',
489
+ now,
490
+ now,
491
+ )
492
+ row = this.owned(db, event.cycleId) as CycleRow
493
+ }
494
+ this.claimObservation(db, event)
495
+ let status = row.status
496
+ let result: string | null = null
497
+ let hash = row.candidate_hash
498
+ if (event.kind === 'usage') {
499
+ const receipt = z
500
+ .object({
501
+ runId: uuid,
502
+ tokens: z.number().int().nonnegative().safe().nullable(),
503
+ costUsd: z.number().nonnegative().finite().nullable(),
504
+ })
505
+ .parse(event.data.receipt)
506
+ if (row.receipts >= 1024) throw new Error('Learning receipt bound exceeded.')
507
+ if (
508
+ !Number.isSafeInteger(row.tokens + (receipt.tokens ?? 0)) ||
509
+ !Number.isFinite(row.cost_usd + (receipt.costUsd ?? 0))
510
+ )
511
+ throw new Error('Learning consumption overflow.')
512
+ db.prepare('INSERT INTO usage_receipts VALUES (?, ?)').run(event.cycleId, receipt.runId)
513
+ db.prepare(
514
+ 'UPDATE cycles SET tokens = tokens + ?, cost_usd = cost_usd + ?, receipts = receipts + 1, unknown_tokens = unknown_tokens + ?, unknown_costs = unknown_costs + ? WHERE id = ?',
515
+ ).run(
516
+ receipt.tokens ?? 0,
517
+ receipt.costUsd ?? 0,
518
+ Number(receipt.tokens === null),
519
+ Number(receipt.costUsd === null),
520
+ event.cycleId,
521
+ )
522
+ }
523
+ if (event.kind === 'candidate')
524
+ hash = z
525
+ .string()
526
+ .regex(/^[0-9a-f]{64}$/)
527
+ .parse(event.data.candidateRevision)
528
+ if (event.kind === 'activation-requested') status = 'activation-pending'
529
+ if (event.kind === 'finished') {
530
+ const value = event.data.result as ResidentLearningCycleResult
531
+ if (!value || uuid.parse(value.cycleId) !== event.cycleId)
532
+ throw new Error('Learning result identity differs from its journal.')
533
+ status = z
534
+ .enum([
535
+ 'activated',
536
+ 'rejected',
537
+ 'inconclusive',
538
+ 'conflict',
539
+ 'cancelled',
540
+ 'failed',
541
+ 'activation-unknown',
542
+ ])
543
+ .parse(value.status)
544
+ if (row.sequence === 0 && !['failed', 'cancelled'].includes(status))
545
+ throw new Error('A successful cycle requires a recorded start.')
546
+ const recorded = summary(row).recordedUsage
547
+ for (const key of [
548
+ 'tokens',
549
+ 'costUsd',
550
+ 'receipts',
551
+ 'unknownTokens',
552
+ 'unknownCosts',
553
+ ] as const) {
554
+ if (value.consumption?.[key] !== recorded[key])
555
+ throw new Error('Final learning consumption differs from its recorded receipts.')
556
+ }
557
+ result = JSON.stringify(value)
558
+ }
559
+ db.prepare('INSERT INTO events VALUES (?, ?, ?)').run(event.cycleId, event.sequence, body)
560
+ db.prepare(
561
+ 'UPDATE cycles SET sequence = ?, status = ?, updated_at = ?, candidate_hash = ?, result = ? WHERE id = ?',
562
+ ).run(event.sequence, status, Date.now(), hash, result, event.cycleId)
563
+ })
564
+ }
565
+
566
+ async get(cycleId: string): Promise<ResidentLearningCycleSummary | null> {
567
+ const id = uuid.parse(cycleId)
568
+ return this.use(false, (db) => {
569
+ const row = this.owned(db, id)
570
+ return row ? summary(row) : null
571
+ })
572
+ }
573
+
574
+ async list(
575
+ options: { readonly before?: number; readonly limit?: number } = {},
576
+ ): Promise<readonly ResidentLearningCycleSummary[]> {
577
+ const limit = z
578
+ .number()
579
+ .int()
580
+ .min(1)
581
+ .max(100)
582
+ .parse(options.limit ?? 20)
583
+ const before = z
584
+ .number()
585
+ .int()
586
+ .positive()
587
+ .safe()
588
+ .parse(options.before ?? Number.MAX_SAFE_INTEGER)
589
+ return this.use(false, (db) =>
590
+ (
591
+ db
592
+ .prepare(
593
+ 'SELECT * FROM cycles WHERE tenant_id = ? AND project_id = ? AND agent_key = ? AND ordinal < ? ORDER BY ordinal DESC LIMIT ?',
594
+ )
595
+ .all(
596
+ this.scope.tenantId,
597
+ this.scope.projectId,
598
+ this.scope.agentKey,
599
+ before,
600
+ limit,
601
+ ) as CycleRow[]
602
+ ).map(summary),
603
+ )
604
+ }
605
+
606
+ async events(
607
+ cycleId: string,
608
+ options: { readonly after?: number; readonly limit?: number } = {},
609
+ ): Promise<readonly ResidentLearningCycleEvent[]> {
610
+ const id = uuid.parse(cycleId)
611
+ const after = z
612
+ .number()
613
+ .int()
614
+ .nonnegative()
615
+ .max(MAX_EVENTS)
616
+ .parse(options.after ?? 0)
617
+ const limit = z
618
+ .number()
619
+ .int()
620
+ .positive()
621
+ .max(256)
622
+ .parse(options.limit ?? 100)
623
+ return this.use(false, (db) => {
624
+ if (!this.owned(db, id)) return []
625
+ return db
626
+ .prepare(
627
+ 'SELECT body FROM events WHERE cycle_id = ? AND sequence > ? ORDER BY sequence LIMIT ?',
628
+ )
629
+ .all(id, after, limit)
630
+ .map((row) => JSON.parse(String(row.body)))
631
+ })
632
+ }
633
+
634
+ async artifacts(cycleId: string): Promise<readonly ResidentLearningArtifact[]> {
635
+ const id = uuid.parse(cycleId)
636
+ return this.use(false, (db) => {
637
+ if (!this.owned(db, id)) return []
638
+ return db
639
+ .prepare('SELECT name, hash, bytes FROM artifacts WHERE cycle_id = ? ORDER BY name')
640
+ .all(id) as unknown as ResidentLearningArtifact[]
641
+ })
642
+ }
643
+
644
+ /** Complete immutable bytes precede the reference; an interrupted publication may leave an unreferenced blob. */
645
+ async putArtifact(
646
+ cycleId: string,
647
+ name: string,
648
+ value: unknown,
649
+ ): Promise<ResidentLearningArtifact> {
650
+ if (this.readOnly) throw new Error('Learning database is read-only.')
651
+ const id = uuid.parse(cycleId)
652
+ z.string()
653
+ .regex(/^[a-z0-9][a-z0-9_.-]{0,119}$/)
654
+ .parse(name)
655
+ if (!(await this.get(id))) throw new Error('Learning artifact requires a recorded cycle.')
656
+ const body = JSON.stringify(value)
657
+ if (body === undefined || Buffer.byteLength(body) > MAX_ARTIFACT_BYTES)
658
+ throw new Error('Learning artifact must be JSON within 8 MiB.')
659
+ const artifact = {
660
+ name,
661
+ hash: digest(body),
662
+ bytes: Buffer.byteLength(body),
663
+ }
664
+ mkdirSync(this.artifactsPath, { recursive: true, mode: 0o700 })
665
+ const target = join(this.artifactsPath, `${artifact.hash}.json`)
666
+ const temporary = join(this.artifactsPath, `.candidate-${randomUUID()}`)
667
+ const fd = openSync(temporary, 'wx', 0o600)
668
+ try {
669
+ try {
670
+ writeFileSync(fd, body)
671
+ fsyncSync(fd)
672
+ } finally {
673
+ closeSync(fd)
674
+ }
675
+ try {
676
+ linkSync(temporary, target)
677
+ } catch (error) {
678
+ if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error
679
+ }
680
+ const entry = lstatSync(target)
681
+ if (
682
+ !entry.isFile() ||
683
+ entry.isSymbolicLink() ||
684
+ entry.size !== artifact.bytes ||
685
+ digest(readFileSync(target)) !== artifact.hash
686
+ )
687
+ throw new Error('Learning artifact content does not match its hash.')
688
+ } finally {
689
+ unlinkSync(temporary)
690
+ }
691
+ // Directory sync makes the filename durable before the database reference.
692
+ if (process.platform !== 'win32') {
693
+ const directory = openSync(this.artifactsPath, 'r')
694
+ try {
695
+ fsyncSync(directory)
696
+ } finally {
697
+ closeSync(directory)
698
+ }
699
+ }
700
+ this.use(true, (db) => {
701
+ if (!this.owned(db, id)) throw new Error('Learning cycle disappeared.')
702
+ const previous = db
703
+ .prepare('SELECT hash FROM artifacts WHERE cycle_id = ? AND name = ?')
704
+ .get(id, name)
705
+ if (previous) {
706
+ if (previous.hash !== artifact.hash)
707
+ throw new Error('Learning artifact name already identifies different content.')
708
+ return
709
+ }
710
+ if (
711
+ Number(
712
+ db.prepare('SELECT COUNT(*) AS count FROM artifacts WHERE cycle_id = ?').get(id)?.count,
713
+ ) >= MAX_ARTIFACTS
714
+ )
715
+ throw new Error('Learning cycle artifact bound exceeded.')
716
+ db.prepare('INSERT INTO artifacts VALUES (?, ?, ?, ?)').run(
717
+ id,
718
+ name,
719
+ artifact.hash,
720
+ artifact.bytes,
721
+ )
722
+ })
723
+ return artifact
724
+ }
725
+
726
+ async readArtifact(cycleId: string, name: string): Promise<unknown> {
727
+ const artifact = (await this.artifacts(cycleId)).find((item) => item.name === name)
728
+ if (!artifact) throw new Error('Learning artifact is not retained in this scope.')
729
+ z.string()
730
+ .regex(/^[0-9a-f]{64}$/)
731
+ .parse(artifact.hash)
732
+ const path = join(this.artifactsPath, `${artifact.hash}.json`)
733
+ const entry = lstatSync(path)
734
+ if (
735
+ !entry.isFile() ||
736
+ entry.isSymbolicLink() ||
737
+ entry.size !== artifact.bytes ||
738
+ entry.size > MAX_ARTIFACT_BYTES
739
+ )
740
+ throw new Error('Learning artifact is not a regular file of the recorded size.')
741
+ const body = readFileSync(path)
742
+ if (digest(body) !== artifact.hash) throw new Error('Learning artifact hash mismatch.')
743
+ return JSON.parse(body.toString('utf8'))
744
+ }
745
+ }
746
+
747
+ /** @experimental Supply normal host callbacks; the store retains journal events and full paired batches. */
748
+ export async function runStoredResidentLearningCycle(
749
+ store: SqliteResidentLearningStore,
750
+ options: Omit<ResidentLearningCycleOptions, 'record'>,
751
+ ): Promise<ResidentLearningCycleResult> {
752
+ return runResidentLearningCycle({
753
+ ...options,
754
+ record: (event) => store.append(event),
755
+ evaluate: async (context) => {
756
+ const value = await options.evaluate(context)
757
+ await store.putArtifact(context.cycleId, context.stage, value.batch)
758
+ return value
759
+ },
760
+ })
761
+ }
762
+
763
+ /** @experimental Host authorizes evaluators; the SDK selects a retained failure against the active skill. */
764
+ export interface ResidentLearningDiscoveryOptions
765
+ extends Omit<ResidentLearningCycleOptions, 'record' | 'failure' | 'skillName'> {
766
+ readonly evaluators: readonly { readonly skillName: string; readonly evaluatorRevision: string }[]
767
+ }
768
+
769
+ /** @experimental Null cycle means no eligible work. A failed claimed cycle is never silently replayed. */
770
+ export interface ResidentLearningDiscoveryResult {
771
+ readonly observation: ResidentLearningObservationRecord | null
772
+ readonly cycle: ResidentLearningCycleResult | null
773
+ }
774
+
775
+ /**
776
+ * @experimental Admit at most one experiment from host-scored observations.
777
+ * Selection is local FIFO fairness, not an estimated probability of improvement.
778
+ * Claim and start are one SQLite transaction; concurrent selectors cannot run
779
+ * the same task/evaluator/baseline twice, even after a crash or reopened process.
780
+ */
781
+ export async function runStoredResidentLearningFromObservations(
782
+ store: SqliteResidentLearningStore,
783
+ options: ResidentLearningDiscoveryOptions,
784
+ ): Promise<ResidentLearningDiscoveryResult> {
785
+ options.signal.throwIfAborted()
786
+ const agenda = await options.agenda.read()
787
+ if (!agenda || agenda.paused || agenda.pursuits.some((p) => p.state.phase === 'running'))
788
+ throw new Error('Learning discovery requires an unpaused agenda without running pursuits.')
789
+ const targets = options.evaluators.map((target) => {
790
+ const skill = agenda.learning?.skills.find((s) => s.name === target.skillName)
791
+ return { ...target, baselineRevision: skill ? hashResidentSkill(skill) : 'none' }
792
+ })
793
+ const observation = await store.selectObservation(targets)
794
+ options.signal.throwIfAborted()
795
+ if (!observation) return { observation: null, cycle: null }
796
+ const cycle = await runResidentLearningCycle({
797
+ ...options,
798
+ skillName: observation.skillName,
799
+ failure: { evidence: observation.evidence, trace: observation.trace },
800
+ record: (event) =>
801
+ store.append(
802
+ event.kind === 'started'
803
+ ? { ...event, data: { ...event.data, observation: { ordinal: observation.ordinal } } }
804
+ : event,
805
+ ),
806
+ evaluate: async (context) => {
807
+ const value = await options.evaluate(context)
808
+ await store.putArtifact(context.cycleId, context.stage, value.batch)
809
+ return value
810
+ },
811
+ })
812
+ return { observation, cycle }
813
+ }