@namzu/sdk 38.2.1 → 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 (493) hide show
  1. package/CHANGELOG.md +700 -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 +13 -1
  47. package/dist/manager/resident/agenda.d.ts.map +1 -1
  48. package/dist/manager/resident/agenda.js +40 -5
  49. package/dist/manager/resident/agenda.js.map +1 -1
  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/evidence-recall.d.ts +24 -0
  55. package/dist/manager/resident/evidence-recall.d.ts.map +1 -0
  56. package/dist/manager/resident/evidence-recall.js +295 -0
  57. package/dist/manager/resident/evidence-recall.js.map +1 -0
  58. package/dist/manager/resident/history-disk.d.ts +10 -0
  59. package/dist/manager/resident/history-disk.d.ts.map +1 -0
  60. package/dist/manager/resident/history-disk.js +50 -0
  61. package/dist/manager/resident/history-disk.js.map +1 -0
  62. package/dist/manager/resident/history.d.ts +79 -0
  63. package/dist/manager/resident/history.d.ts.map +1 -0
  64. package/dist/manager/resident/history.js +203 -0
  65. package/dist/manager/resident/history.js.map +1 -0
  66. package/dist/manager/resident/initiative.d.ts.map +1 -1
  67. package/dist/manager/resident/initiative.js +11 -3
  68. package/dist/manager/resident/initiative.js.map +1 -1
  69. package/dist/manager/resident/learning-cycle.d.ts +131 -0
  70. package/dist/manager/resident/learning-cycle.d.ts.map +1 -0
  71. package/dist/manager/resident/learning-cycle.js +306 -0
  72. package/dist/manager/resident/learning-cycle.js.map +1 -0
  73. package/dist/manager/resident/learning-observation.d.ts +80 -0
  74. package/dist/manager/resident/learning-observation.d.ts.map +1 -0
  75. package/dist/manager/resident/learning-observation.js +22 -0
  76. package/dist/manager/resident/learning-observation.js.map +1 -0
  77. package/dist/manager/resident/learning-store.d.ts +106 -0
  78. package/dist/manager/resident/learning-store.d.ts.map +1 -0
  79. package/dist/manager/resident/learning-store.js +598 -0
  80. package/dist/manager/resident/learning-store.js.map +1 -0
  81. package/dist/manager/resident/learning.d.ts +246 -3
  82. package/dist/manager/resident/learning.d.ts.map +1 -1
  83. package/dist/manager/resident/learning.js +96 -6
  84. package/dist/manager/resident/learning.js.map +1 -1
  85. package/dist/manager/resident/outbox.d.ts +4 -4
  86. package/dist/manager/resident/store.d.ts +37 -4
  87. package/dist/manager/resident/store.d.ts.map +1 -1
  88. package/dist/manager/resident/store.js +27 -3
  89. package/dist/manager/resident/store.js.map +1 -1
  90. package/dist/manager/resident/tool-evidence.d.ts +71 -0
  91. package/dist/manager/resident/tool-evidence.d.ts.map +1 -0
  92. package/dist/manager/resident/tool-evidence.js +285 -0
  93. package/dist/manager/resident/tool-evidence.js.map +1 -0
  94. package/dist/manager/run/persistence.d.ts.map +1 -1
  95. package/dist/manager/run/persistence.js +6 -0
  96. package/dist/manager/run/persistence.js.map +1 -1
  97. package/dist/plugin/loader.d.ts.map +1 -1
  98. package/dist/plugin/loader.js +5 -3
  99. package/dist/plugin/loader.js.map +1 -1
  100. package/dist/prompt/coding-agent-doctrine.d.ts +1 -1
  101. package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
  102. package/dist/prompt/coding-agent-doctrine.js +2 -0
  103. package/dist/prompt/coding-agent-doctrine.js.map +1 -1
  104. package/dist/prompt/index.d.ts +2 -0
  105. package/dist/prompt/index.d.ts.map +1 -1
  106. package/dist/prompt/index.js +1 -0
  107. package/dist/prompt/index.js.map +1 -1
  108. package/dist/prompt/resident-learning.d.ts +19 -0
  109. package/dist/prompt/resident-learning.d.ts.map +1 -0
  110. package/dist/prompt/resident-learning.js +125 -0
  111. package/dist/prompt/resident-learning.js.map +1 -0
  112. package/dist/prompt/resident-step.d.ts +8 -1
  113. package/dist/prompt/resident-step.d.ts.map +1 -1
  114. package/dist/prompt/resident-step.js +65 -4
  115. package/dist/prompt/resident-step.js.map +1 -1
  116. package/dist/provider/collect-chat-completion.d.ts +2 -1
  117. package/dist/provider/collect-chat-completion.d.ts.map +1 -1
  118. package/dist/provider/collect-chat-completion.js +7 -6
  119. package/dist/provider/collect-chat-completion.js.map +1 -1
  120. package/dist/provider/fallback.d.ts.map +1 -1
  121. package/dist/provider/fallback.js +2 -1
  122. package/dist/provider/fallback.js.map +1 -1
  123. package/dist/provider/stream-text.d.ts +16 -0
  124. package/dist/provider/stream-text.d.ts.map +1 -0
  125. package/dist/provider/stream-text.js +51 -0
  126. package/dist/provider/stream-text.js.map +1 -0
  127. package/dist/public-runtime.d.ts +13 -3
  128. package/dist/public-runtime.d.ts.map +1 -1
  129. package/dist/public-runtime.js +12 -3
  130. package/dist/public-runtime.js.map +1 -1
  131. package/dist/public-tools.d.ts +2 -0
  132. package/dist/public-tools.d.ts.map +1 -1
  133. package/dist/public-tools.js +2 -0
  134. package/dist/public-tools.js.map +1 -1
  135. package/dist/public-types.d.ts +15 -3
  136. package/dist/public-types.d.ts.map +1 -1
  137. package/dist/run/LimitChecker.js +3 -3
  138. package/dist/run/LimitChecker.js.map +1 -1
  139. package/dist/run/evidence-query.d.ts +41 -0
  140. package/dist/run/evidence-query.d.ts.map +1 -0
  141. package/dist/run/evidence-query.js +270 -0
  142. package/dist/run/evidence-query.js.map +1 -0
  143. package/dist/run/evidence-recall.d.ts +99 -0
  144. package/dist/run/evidence-recall.d.ts.map +1 -0
  145. package/dist/run/evidence-recall.js +633 -0
  146. package/dist/run/evidence-recall.js.map +1 -0
  147. package/dist/run/index.d.ts +2 -0
  148. package/dist/run/index.d.ts.map +1 -1
  149. package/dist/run/index.js +1 -0
  150. package/dist/run/index.js.map +1 -1
  151. package/dist/run/json-claim-verifier.d.ts +83 -0
  152. package/dist/run/json-claim-verifier.d.ts.map +1 -0
  153. package/dist/run/json-claim-verifier.js +200 -0
  154. package/dist/run/json-claim-verifier.js.map +1 -0
  155. package/dist/run/preparation-context-error.d.ts +10 -0
  156. package/dist/run/preparation-context-error.d.ts.map +1 -0
  157. package/dist/run/preparation-context-error.js +15 -0
  158. package/dist/run/preparation-context-error.js.map +1 -0
  159. package/dist/run-query/index.d.ts +3 -1
  160. package/dist/run-query/index.d.ts.map +1 -1
  161. package/dist/runtime/query/callback-inference.d.ts +8 -0
  162. package/dist/runtime/query/callback-inference.d.ts.map +1 -0
  163. package/dist/runtime/query/callback-inference.js +89 -0
  164. package/dist/runtime/query/callback-inference.js.map +1 -0
  165. package/dist/runtime/query/checkpoint.d.ts +4 -0
  166. package/dist/runtime/query/checkpoint.d.ts.map +1 -1
  167. package/dist/runtime/query/checkpoint.js +13 -0
  168. package/dist/runtime/query/checkpoint.js.map +1 -1
  169. package/dist/runtime/query/events.d.ts +1 -0
  170. package/dist/runtime/query/events.d.ts.map +1 -1
  171. package/dist/runtime/query/events.js +18 -0
  172. package/dist/runtime/query/events.js.map +1 -1
  173. package/dist/runtime/query/executor.d.ts +7 -1
  174. package/dist/runtime/query/executor.d.ts.map +1 -1
  175. package/dist/runtime/query/executor.js +38 -7
  176. package/dist/runtime/query/executor.js.map +1 -1
  177. package/dist/runtime/query/file-evidence-context.d.ts +5 -0
  178. package/dist/runtime/query/file-evidence-context.d.ts.map +1 -0
  179. package/dist/runtime/query/file-evidence-context.js +64 -0
  180. package/dist/runtime/query/file-evidence-context.js.map +1 -0
  181. package/dist/runtime/query/guard.d.ts.map +1 -1
  182. package/dist/runtime/query/guard.js +4 -0
  183. package/dist/runtime/query/guard.js.map +1 -1
  184. package/dist/runtime/query/index.d.ts +10 -1
  185. package/dist/runtime/query/index.d.ts.map +1 -1
  186. package/dist/runtime/query/index.js +39 -24
  187. package/dist/runtime/query/index.js.map +1 -1
  188. package/dist/runtime/query/iteration/index.d.ts +9 -31
  189. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  190. package/dist/runtime/query/iteration/index.js +231 -93
  191. package/dist/runtime/query/iteration/index.js.map +1 -1
  192. package/dist/runtime/query/iteration/phases/advisory.d.ts +2 -1
  193. package/dist/runtime/query/iteration/phases/advisory.d.ts.map +1 -1
  194. package/dist/runtime/query/iteration/phases/advisory.js +2 -1
  195. package/dist/runtime/query/iteration/phases/advisory.js.map +1 -1
  196. package/dist/runtime/query/iteration/phases/context.d.ts +2 -1
  197. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  198. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  199. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  200. package/dist/runtime/query/iteration/phases/tool-review.js +3 -0
  201. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  202. package/dist/runtime/query/iteration/provider-rejected-image.d.ts +2 -1
  203. package/dist/runtime/query/iteration/provider-rejected-image.d.ts.map +1 -1
  204. package/dist/runtime/query/iteration/provider-rejected-image.js +5 -2
  205. package/dist/runtime/query/iteration/provider-rejected-image.js.map +1 -1
  206. package/dist/runtime/query/iteration/stream-turn.d.ts +4 -1
  207. package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
  208. package/dist/runtime/query/iteration/stream-turn.js +22 -8
  209. package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
  210. package/dist/runtime/query/resume-pending.d.ts +18 -33
  211. package/dist/runtime/query/resume-pending.d.ts.map +1 -1
  212. package/dist/runtime/query/resume-pending.js +59 -42
  213. package/dist/runtime/query/resume-pending.js.map +1 -1
  214. package/dist/runtime/query/review-policy.d.ts +4 -4
  215. package/dist/runtime/query/review-policy.d.ts.map +1 -1
  216. package/dist/runtime/query/review-policy.js +10 -9
  217. package/dist/runtime/query/review-policy.js.map +1 -1
  218. package/dist/runtime/query/sandbox-lifecycle.d.ts.map +1 -1
  219. package/dist/runtime/query/sandbox-lifecycle.js +4 -0
  220. package/dist/runtime/query/sandbox-lifecycle.js.map +1 -1
  221. package/dist/runtime/query/tool-output-budget.d.ts +10 -6
  222. package/dist/runtime/query/tool-output-budget.d.ts.map +1 -1
  223. package/dist/runtime/query/tool-output-budget.js +54 -12
  224. package/dist/runtime/query/tool-output-budget.js.map +1 -1
  225. package/dist/runtime/query/tooling.d.ts +3 -1
  226. package/dist/runtime/query/tooling.d.ts.map +1 -1
  227. package/dist/runtime/query/tooling.js +4 -0
  228. package/dist/runtime/query/tooling.js.map +1 -1
  229. package/dist/scheduler/completion-inbox.d.ts +3 -0
  230. package/dist/scheduler/completion-inbox.d.ts.map +1 -1
  231. package/dist/scheduler/completion-inbox.js +28 -0
  232. package/dist/scheduler/completion-inbox.js.map +1 -1
  233. package/dist/store/evidence/compaction-archive.d.ts +109 -0
  234. package/dist/store/evidence/compaction-archive.d.ts.map +1 -0
  235. package/dist/store/evidence/compaction-archive.js +125 -0
  236. package/dist/store/evidence/compaction-archive.js.map +1 -0
  237. package/dist/store/evidence/compaction-provenance.d.ts +7 -0
  238. package/dist/store/evidence/compaction-provenance.d.ts.map +1 -0
  239. package/dist/store/evidence/compaction-provenance.js +49 -0
  240. package/dist/store/evidence/compaction-provenance.js.map +1 -0
  241. package/dist/store/evidence/compaction-text.d.ts +16 -0
  242. package/dist/store/evidence/compaction-text.d.ts.map +1 -0
  243. package/dist/store/evidence/compaction-text.js +51 -0
  244. package/dist/store/evidence/compaction-text.js.map +1 -0
  245. package/dist/store/evidence/disk.d.ts +11 -0
  246. package/dist/store/evidence/disk.d.ts.map +1 -0
  247. package/dist/store/evidence/disk.js +367 -0
  248. package/dist/store/evidence/disk.js.map +1 -0
  249. package/dist/store/evidence/format.d.ts +25 -0
  250. package/dist/store/evidence/format.d.ts.map +1 -0
  251. package/dist/store/evidence/format.js +115 -0
  252. package/dist/store/evidence/format.js.map +1 -0
  253. package/dist/store/evidence/index-page.d.ts +208 -0
  254. package/dist/store/evidence/index-page.d.ts.map +1 -0
  255. package/dist/store/evidence/index-page.js +262 -0
  256. package/dist/store/evidence/index-page.js.map +1 -0
  257. package/dist/store/evidence/io.d.ts +24 -0
  258. package/dist/store/evidence/io.d.ts.map +1 -0
  259. package/dist/store/evidence/io.js +69 -0
  260. package/dist/store/evidence/io.js.map +1 -0
  261. package/dist/store/evidence/linked.d.ts +9 -0
  262. package/dist/store/evidence/linked.d.ts.map +1 -0
  263. package/dist/store/evidence/linked.js +314 -0
  264. package/dist/store/evidence/linked.js.map +1 -0
  265. package/dist/store/evidence/passages.d.ts +15 -0
  266. package/dist/store/evidence/passages.d.ts.map +1 -0
  267. package/dist/store/evidence/passages.js +72 -0
  268. package/dist/store/evidence/passages.js.map +1 -0
  269. package/dist/store/evidence/record-chain.d.ts +42 -0
  270. package/dist/store/evidence/record-chain.d.ts.map +1 -0
  271. package/dist/store/evidence/record-chain.js +111 -0
  272. package/dist/store/evidence/record-chain.js.map +1 -0
  273. package/dist/store/evidence/search-input.d.ts +21 -0
  274. package/dist/store/evidence/search-input.d.ts.map +1 -0
  275. package/dist/store/evidence/search-input.js +44 -0
  276. package/dist/store/evidence/search-input.js.map +1 -0
  277. package/dist/store/evidence/selection.d.ts +9 -0
  278. package/dist/store/evidence/selection.d.ts.map +1 -0
  279. package/dist/store/evidence/selection.js +17 -0
  280. package/dist/store/evidence/selection.js.map +1 -0
  281. package/dist/store/evidence/source-kind.d.ts +11 -0
  282. package/dist/store/evidence/source-kind.d.ts.map +1 -0
  283. package/dist/store/evidence/source-kind.js +26 -0
  284. package/dist/store/evidence/source-kind.js.map +1 -0
  285. package/dist/store/evidence/source-text.d.ts +51 -0
  286. package/dist/store/evidence/source-text.d.ts.map +1 -0
  287. package/dist/store/evidence/source-text.js +213 -0
  288. package/dist/store/evidence/source-text.js.map +1 -0
  289. package/dist/store/evidence/types.d.ts +162 -0
  290. package/dist/store/evidence/types.d.ts.map +1 -0
  291. package/dist/store/evidence/types.js +2 -0
  292. package/dist/store/evidence/types.js.map +1 -0
  293. package/dist/store/memory/disk.d.ts +2 -0
  294. package/dist/store/memory/disk.d.ts.map +1 -1
  295. package/dist/store/memory/disk.js +2 -1
  296. package/dist/store/memory/disk.js.map +1 -1
  297. package/dist/store/run/disk.d.ts +10 -0
  298. package/dist/store/run/disk.d.ts.map +1 -1
  299. package/dist/store/run/disk.js +87 -7
  300. package/dist/store/run/disk.js.map +1 -1
  301. package/dist/store/run/memory.d.ts +1 -0
  302. package/dist/store/run/memory.d.ts.map +1 -1
  303. package/dist/store/run/memory.js +10 -0
  304. package/dist/store/run/memory.js.map +1 -1
  305. package/dist/store/run/tool-executions.d.ts +13 -0
  306. package/dist/store/run/tool-executions.d.ts.map +1 -0
  307. package/dist/store/run/tool-executions.js +99 -0
  308. package/dist/store/run/tool-executions.js.map +1 -0
  309. package/dist/store/session/index.d.ts +2 -0
  310. package/dist/store/session/index.d.ts.map +1 -1
  311. package/dist/store/session/index.js +1 -0
  312. package/dist/store/session/index.js.map +1 -1
  313. package/dist/store/session/sqlite.d.ts +57 -0
  314. package/dist/store/session/sqlite.d.ts.map +1 -0
  315. package/dist/store/session/sqlite.js +430 -0
  316. package/dist/store/session/sqlite.js.map +1 -0
  317. package/dist/tools/builtins/job.d.ts.map +1 -1
  318. package/dist/tools/builtins/job.js +4 -5
  319. package/dist/tools/builtins/job.js.map +1 -1
  320. package/dist/tools/builtins/write-file.js +2 -2
  321. package/dist/tools/builtins/write-file.js.map +1 -1
  322. package/dist/tools/defineTool.d.ts +2 -1
  323. package/dist/tools/defineTool.d.ts.map +1 -1
  324. package/dist/tools/defineTool.js +1 -1
  325. package/dist/tools/defineTool.js.map +1 -1
  326. package/dist/tools/file-read-tracker.d.ts.map +1 -1
  327. package/dist/tools/file-read-tracker.js +12 -3
  328. package/dist/tools/file-read-tracker.js.map +1 -1
  329. package/dist/tools/resident-history.d.ts +10 -0
  330. package/dist/tools/resident-history.d.ts.map +1 -0
  331. package/dist/tools/resident-history.js +80 -0
  332. package/dist/tools/resident-history.js.map +1 -0
  333. package/dist/tools/resident-tool-evidence.d.ts +5 -0
  334. package/dist/tools/resident-tool-evidence.d.ts.map +1 -0
  335. package/dist/tools/resident-tool-evidence.js +57 -0
  336. package/dist/tools/resident-tool-evidence.js.map +1 -0
  337. package/dist/types/advisory/config.d.ts +7 -0
  338. package/dist/types/advisory/config.d.ts.map +1 -1
  339. package/dist/types/agent/reactive.d.ts +1 -0
  340. package/dist/types/agent/reactive.d.ts.map +1 -1
  341. package/dist/types/authorization/index.d.ts +9 -9
  342. package/dist/types/authorization/index.d.ts.map +1 -1
  343. package/dist/types/authorization/index.js +1 -1
  344. package/dist/types/authorization/index.js.map +1 -1
  345. package/dist/types/hitl/index.d.ts +4 -0
  346. package/dist/types/hitl/index.d.ts.map +1 -1
  347. package/dist/types/hitl/index.js.map +1 -1
  348. package/dist/types/message/index.d.ts +16 -2
  349. package/dist/types/message/index.d.ts.map +1 -1
  350. package/dist/types/message/index.js +8 -1
  351. package/dist/types/message/index.js.map +1 -1
  352. package/dist/types/provider/chat.d.ts +2 -0
  353. package/dist/types/provider/chat.d.ts.map +1 -1
  354. package/dist/types/provider/stream.d.ts +4 -0
  355. package/dist/types/provider/stream.d.ts.map +1 -1
  356. package/dist/types/run/answer-review.d.ts +34 -3
  357. package/dist/types/run/answer-review.d.ts.map +1 -1
  358. package/dist/types/run/config.d.ts +3 -0
  359. package/dist/types/run/config.d.ts.map +1 -1
  360. package/dist/types/run/entity.d.ts +7 -0
  361. package/dist/types/run/entity.d.ts.map +1 -1
  362. package/dist/types/run/events.d.ts +31 -8
  363. package/dist/types/run/events.d.ts.map +1 -1
  364. package/dist/types/run/events.js.map +1 -1
  365. package/dist/types/run/prepare-step.d.ts +53 -8
  366. package/dist/types/run/prepare-step.d.ts.map +1 -1
  367. package/dist/types/run/store.d.ts +29 -4
  368. package/dist/types/run/store.d.ts.map +1 -1
  369. package/dist/types/run/store.js +0 -28
  370. package/dist/types/run/store.js.map +1 -1
  371. package/dist/types/tool/index.d.ts +15 -1
  372. package/dist/types/tool/index.d.ts.map +1 -1
  373. package/dist/types/tool/index.js.map +1 -1
  374. package/dist/utils/await-with-abort.d.ts +8 -0
  375. package/dist/utils/await-with-abort.d.ts.map +1 -0
  376. package/dist/utils/await-with-abort.js +28 -0
  377. package/dist/utils/await-with-abort.js.map +1 -0
  378. package/dist/utils/evidence-time.d.ts +3 -0
  379. package/dist/utils/evidence-time.d.ts.map +1 -0
  380. package/dist/utils/evidence-time.js +10 -0
  381. package/dist/utils/evidence-time.js.map +1 -0
  382. package/dist/utils/evidence-tokens.d.ts +13 -0
  383. package/dist/utils/evidence-tokens.d.ts.map +1 -0
  384. package/dist/utils/evidence-tokens.js +29 -0
  385. package/dist/utils/evidence-tokens.js.map +1 -0
  386. package/package.json +1 -1
  387. package/src/advisory/executor.ts +15 -30
  388. package/src/advisory/history.ts +126 -0
  389. package/src/advisory/index.ts +5 -1
  390. package/src/agents/ReactiveAgent.ts +3 -0
  391. package/src/agents/runAgent.ts +14 -1
  392. package/src/compaction/manual.ts +30 -2
  393. package/src/compaction/summary.ts +4 -1
  394. package/src/config/runtime.ts +2 -2
  395. package/src/contracts/schemas.ts +1 -1
  396. package/src/eval/harness-protection.ts +79 -0
  397. package/src/eval/harness-verification.ts +31 -1
  398. package/src/eval/index.ts +1 -0
  399. package/src/manager/resident/activity.ts +187 -0
  400. package/src/manager/resident/agenda.ts +59 -5
  401. package/src/manager/resident/consumption.ts +311 -0
  402. package/src/manager/resident/evidence-recall.ts +363 -0
  403. package/src/manager/resident/history-disk.ts +63 -0
  404. package/src/manager/resident/history.ts +312 -0
  405. package/src/manager/resident/initiative.ts +13 -3
  406. package/src/manager/resident/learning-cycle.ts +499 -0
  407. package/src/manager/resident/learning-observation.ts +39 -0
  408. package/src/manager/resident/learning-store.ts +813 -0
  409. package/src/manager/resident/learning.ts +132 -8
  410. package/src/manager/resident/store.ts +31 -3
  411. package/src/manager/resident/tool-evidence.ts +412 -0
  412. package/src/manager/run/persistence.ts +6 -0
  413. package/src/plugin/loader.ts +8 -3
  414. package/src/prompt/coding-agent-doctrine.ts +2 -0
  415. package/src/prompt/index.ts +2 -0
  416. package/src/prompt/resident-learning.ts +143 -0
  417. package/src/prompt/resident-step.ts +83 -3
  418. package/src/provider/collect-chat-completion.ts +7 -6
  419. package/src/provider/fallback.ts +2 -1
  420. package/src/provider/stream-text.ts +56 -0
  421. package/src/public-runtime.ts +30 -0
  422. package/src/public-tools.ts +3 -0
  423. package/src/public-types.ts +98 -0
  424. package/src/run/LimitChecker.ts +3 -3
  425. package/src/run/evidence-query.ts +333 -0
  426. package/src/run/evidence-recall.ts +854 -0
  427. package/src/run/index.ts +11 -0
  428. package/src/run/json-claim-verifier.ts +298 -0
  429. package/src/run/preparation-context-error.ts +16 -0
  430. package/src/run-query/index.ts +1 -1
  431. package/src/runtime/query/callback-inference.ts +94 -0
  432. package/src/runtime/query/checkpoint.ts +14 -0
  433. package/src/runtime/query/events.ts +22 -0
  434. package/src/runtime/query/executor.ts +51 -9
  435. package/src/runtime/query/file-evidence-context.ts +65 -0
  436. package/src/runtime/query/guard.ts +2 -0
  437. package/src/runtime/query/index.ts +49 -25
  438. package/src/runtime/query/iteration/index.ts +269 -86
  439. package/src/runtime/query/iteration/phases/advisory.ts +3 -0
  440. package/src/runtime/query/iteration/phases/context.ts +2 -0
  441. package/src/runtime/query/iteration/phases/tool-review.ts +3 -0
  442. package/src/runtime/query/iteration/provider-rejected-image.ts +6 -1
  443. package/src/runtime/query/iteration/stream-turn.ts +35 -8
  444. package/src/runtime/query/resume-pending.ts +65 -40
  445. package/src/runtime/query/review-policy.ts +13 -9
  446. package/src/runtime/query/sandbox-lifecycle.ts +3 -0
  447. package/src/runtime/query/tool-output-budget.ts +65 -13
  448. package/src/runtime/query/tooling.ts +7 -1
  449. package/src/scheduler/completion-inbox.ts +26 -0
  450. package/src/store/evidence/compaction-archive.ts +139 -0
  451. package/src/store/evidence/compaction-provenance.ts +52 -0
  452. package/src/store/evidence/compaction-text.ts +61 -0
  453. package/src/store/evidence/disk.ts +461 -0
  454. package/src/store/evidence/format.ts +126 -0
  455. package/src/store/evidence/index-page.ts +292 -0
  456. package/src/store/evidence/io.ts +95 -0
  457. package/src/store/evidence/linked.ts +365 -0
  458. package/src/store/evidence/passages.ts +88 -0
  459. package/src/store/evidence/record-chain.ts +108 -0
  460. package/src/store/evidence/search-input.ts +62 -0
  461. package/src/store/evidence/selection.ts +25 -0
  462. package/src/store/evidence/source-kind.ts +36 -0
  463. package/src/store/evidence/source-text.ts +285 -0
  464. package/src/store/evidence/types.ts +177 -0
  465. package/src/store/memory/disk.ts +4 -1
  466. package/src/store/run/disk.ts +110 -8
  467. package/src/store/run/memory.ts +10 -0
  468. package/src/store/run/tool-executions.ts +112 -0
  469. package/src/store/session/index.ts +2 -0
  470. package/src/store/session/sqlite.ts +584 -0
  471. package/src/tools/builtins/job.ts +4 -5
  472. package/src/tools/builtins/write-file.ts +2 -2
  473. package/src/tools/defineTool.ts +4 -2
  474. package/src/tools/file-read-tracker.ts +8 -2
  475. package/src/tools/resident-history.ts +86 -0
  476. package/src/tools/resident-tool-evidence.ts +68 -0
  477. package/src/types/advisory/config.ts +7 -0
  478. package/src/types/agent/reactive.ts +1 -0
  479. package/src/types/authorization/index.ts +2 -2
  480. package/src/types/hitl/index.ts +4 -0
  481. package/src/types/message/index.ts +20 -0
  482. package/src/types/provider/chat.ts +2 -0
  483. package/src/types/provider/stream.ts +4 -0
  484. package/src/types/run/answer-review.ts +34 -3
  485. package/src/types/run/config.ts +3 -0
  486. package/src/types/run/entity.ts +7 -0
  487. package/src/types/run/events.ts +31 -8
  488. package/src/types/run/prepare-step.ts +59 -8
  489. package/src/types/run/store.ts +35 -4
  490. package/src/types/tool/index.ts +19 -1
  491. package/src/utils/await-with-abort.ts +26 -0
  492. package/src/utils/evidence-time.ts +9 -0
  493. package/src/utils/evidence-tokens.ts +32 -0
@@ -0,0 +1,365 @@
1
+ import { lstat } from 'node:fs/promises'
2
+ import type { FileHandle } from 'node:fs/promises'
3
+ import { join } from 'node:path'
4
+ import { z } from 'zod'
5
+ import { EVIDENCE_CHUNK_BYTES, digest } from './format.js'
6
+ import { type EvidenceSeal, eventTexts, evidenceSeal } from './index-page.js'
7
+ import {
8
+ type EvidenceBudget,
9
+ EvidencePageLimit,
10
+ PAGE_BYTES,
11
+ decode,
12
+ openEvidence,
13
+ readBytes,
14
+ readSmall,
15
+ } from './io.js'
16
+ import { passageMatcher, passagesInWindow } from './passages.js'
17
+ import { type RecordPointer, recordPointerSchema, recordPredecessors } from './record-chain.js'
18
+ import { evidenceSearchInput, evidenceTermsSchema } from './search-input.js'
19
+ import {
20
+ evidenceExclusionsKey,
21
+ evidenceExclusionsSchema,
22
+ excludesSuccessfulTool,
23
+ } from './selection.js'
24
+ import { createTextSourceReader, readTextPage, textPointerSchema } from './source-text.js'
25
+ import type {
26
+ DiskRunEvidenceOptions,
27
+ RunEvidenceReadOptions,
28
+ RunTextEvidenceMatch,
29
+ RunTextEvidenceSearchOptions,
30
+ RunTextEvidenceSource,
31
+ } from './types.js'
32
+
33
+ const integer = z.number().int().nonnegative().safe()
34
+ const scopeSchema = z
35
+ .object({
36
+ tenantId: z.string().uuid(),
37
+ projectId: z.string().uuid(),
38
+ sessionId: z.string().uuid(),
39
+ runId: z.string().uuid(),
40
+ })
41
+ .strict()
42
+ const cursorSchema = z.object({
43
+ kind: z.enum(['linked-search', 'linked-search-terms', 'linked-search-tokens']),
44
+ query: z.string().max(256),
45
+ termsKey: z
46
+ .string()
47
+ .regex(/^[a-f0-9]{64}$/)
48
+ .optional(),
49
+ caseSensitive: z.boolean().default(true),
50
+ matchMode: z.enum(['literal', 'token']).default('literal'),
51
+ exclusionsKey: z
52
+ .string()
53
+ .regex(/^[a-f0-9]{64}$/)
54
+ .optional(),
55
+ seq: integer.optional(),
56
+ part: integer.optional(),
57
+ next: recordPointerSchema.nullable(),
58
+ textIndex: integer,
59
+ chunk: integer,
60
+ within: integer.default(0),
61
+ })
62
+ const addressSchema = z.object({ kind: z.literal('linked-text'), entry: textPointerSchema })
63
+
64
+ /** Internal: only the durable writer can supply this anchor. Never accept it from a tool input. */
65
+ export function createLinkedRunTextEvidenceSource(
66
+ options: DiskRunEvidenceOptions,
67
+ anchor: { tip: RecordPointer; identity: string; epoch: string },
68
+ ): RunTextEvidenceSource {
69
+ const scope = Object.freeze(scopeSchema.parse(options.scope))
70
+ const runDir = options.runDir
71
+ const tip = recordPointerSchema.parse(anchor.tip)
72
+ const ceiling = tip.offset + tip.length
73
+ const scopeKey = digest(JSON.stringify(scope))
74
+ const sourceKey = digest(`linked-v1:${scopeKey}:${anchor.identity}:${anchor.epoch}`)
75
+ const maxReadBytes = integer
76
+ .min(1024 * 1024)
77
+ .max(PAGE_BYTES)
78
+ .parse(options.maxReadBytes ?? PAGE_BYTES)
79
+ const inBoundary = (pointer: RecordPointer) => {
80
+ if (pointer.seq > tip.seq || pointer.offset + pointer.length > ceiling)
81
+ throw new Error('Evidence address exceeds the captured boundary.')
82
+ }
83
+ async function access<T extends { scannedBytes: number }>(
84
+ signal: AbortSignal | undefined,
85
+ requestedBytes: number | undefined,
86
+ action: (handle: FileHandle, seal: EvidenceSeal, budget: EvidenceBudget) => Promise<T>,
87
+ ): Promise<T> {
88
+ const limit = Math.min(maxReadBytes, requestedBytes ?? maxReadBytes)
89
+ const budget: EvidenceBudget = { bytes: 0, limit, signal }
90
+ signal?.throwIfAborted()
91
+ const verifyOwner = async () => {
92
+ const metadata = JSON.parse(
93
+ decode(await readSmall(join(runDir, 'run.json'), budget, 512 * 1024)),
94
+ )
95
+ if (
96
+ metadata.id !== scope.runId ||
97
+ JSON.stringify(scopeSchema.parse(metadata.metadata?.scope)) !== JSON.stringify(scope)
98
+ )
99
+ throw new Error('Evidence run does not belong to the authorized scope.')
100
+ }
101
+ await verifyOwner()
102
+ // Reserve a final ownership check; counters/status may change while this run works.
103
+ budget.limit = limit - 512 * 1024
104
+
105
+ const path = join(options.runDir, 'transcript.jsonl')
106
+ const handle = await openEvidence(path)
107
+ const check = (stat: { dev: number; ino: number; size: number }) => {
108
+ if (`${stat.dev}:${stat.ino}` !== anchor.identity || stat.size < ceiling)
109
+ throw new Error('Captured transcript was replaced or shortened.')
110
+ }
111
+ try {
112
+ check(await handle.stat())
113
+ const seal = await evidenceSeal(options.indexDir, scopeKey, sourceKey, budget)
114
+ const result = await action(handle, seal, budget)
115
+ signal?.throwIfAborted()
116
+ check(await handle.stat())
117
+ check(await lstat(path))
118
+ budget.limit = limit
119
+ await verifyOwner()
120
+ return { ...result, scannedBytes: budget.bytes }
121
+ } finally {
122
+ await handle.close()
123
+ }
124
+ }
125
+ return Object.freeze({
126
+ scope,
127
+ async search(options: RunTextEvidenceSearchOptions = {}, signal?: AbortSignal) {
128
+ const input = z
129
+ .object({
130
+ maxReadBytes: integer
131
+ .min(1024 * 1024)
132
+ .max(PAGE_BYTES)
133
+ .optional(),
134
+ query: z.string().max(256).optional(),
135
+ terms: evidenceTermsSchema,
136
+ caseSensitive: z.boolean().default(true),
137
+ matchMode: z.enum(['literal', 'token']).default('literal'),
138
+ excludeSuccessfulTools: evidenceExclusionsSchema,
139
+ excludeDerivedSummaries: z.boolean().default(false),
140
+ cursor: z.string().max(4096).optional(),
141
+ seq: integer.positive().optional(),
142
+ part: integer.optional(),
143
+ limit: integer.min(1).max(4).default(4),
144
+ })
145
+ .strict()
146
+ .parse(options)
147
+ if (input.part !== undefined && input.seq === undefined)
148
+ throw new Error('Part requires an event sequence.')
149
+ const { query, terms, termsKey, browse } = evidenceSearchInput(input)
150
+ const exclusionsKey = evidenceExclusionsKey(
151
+ input.excludeSuccessfulTools,
152
+ input.excludeDerivedSummaries,
153
+ )
154
+ const kind =
155
+ input.matchMode === 'token'
156
+ ? ('linked-search-tokens' as const)
157
+ : terms
158
+ ? ('linked-search-terms' as const)
159
+ : ('linked-search' as const)
160
+ return access(signal, input.maxReadBytes, async (handle, seal, budget) => {
161
+ const readSource = createTextSourceReader(handle, runDir, scope.runId, budget)
162
+ const cursor = input.cursor
163
+ ? cursorSchema.parse(seal.unpack(input.cursor))
164
+ : {
165
+ kind,
166
+ query,
167
+ termsKey,
168
+ exclusionsKey,
169
+ seq: input.seq,
170
+ part: input.part,
171
+ next: tip as RecordPointer | null,
172
+ textIndex: 0,
173
+ chunk: 0,
174
+ within: 0,
175
+ caseSensitive: input.caseSensitive,
176
+ matchMode: input.matchMode,
177
+ }
178
+ if (
179
+ cursor.kind !== kind ||
180
+ cursor.query !== query ||
181
+ cursor.termsKey !== termsKey ||
182
+ cursor.exclusionsKey !== exclusionsKey ||
183
+ cursor.caseSensitive !== input.caseSensitive ||
184
+ cursor.matchMode !== input.matchMode ||
185
+ cursor.seq !== input.seq ||
186
+ cursor.part !== input.part
187
+ )
188
+ throw new Error('Search cursor query changed.')
189
+ const matchPassage = passageMatcher(terms ?? query, input.caseSensitive, input.matchMode)
190
+ const matches: RunTextEvidenceMatch[] = []
191
+ const unavailable: string[] = []
192
+ let records = 0
193
+ let parts = 0
194
+ let chunks = 0
195
+ let incomplete = false
196
+ let excludedToolResults = 0
197
+ let excludedSummaries = 0
198
+ while (
199
+ cursor.next &&
200
+ records < 64 &&
201
+ parts < 64 &&
202
+ chunks < 64 &&
203
+ matches.length < input.limit
204
+ ) {
205
+ const pointer = cursor.next
206
+ inBoundary(pointer)
207
+ if (input.seq !== undefined && pointer.seq < input.seq) {
208
+ cursor.next = null
209
+ break
210
+ }
211
+ let raw: Buffer
212
+ try {
213
+ raw = await readBytes(handle, pointer.offset, pointer.length, budget)
214
+ } catch (error) {
215
+ if (error instanceof EvidencePageLimit) {
216
+ if (records === 0) throw new Error('Recorded text exceeds the available page budget.')
217
+ break
218
+ }
219
+ throw error
220
+ }
221
+ if (digest(raw) !== pointer.sha256)
222
+ throw new Error('Recorded text integrity chain changed.')
223
+ const event = JSON.parse(decode(raw))
224
+ if (event.runId !== scope.runId || event.seq !== pointer.seq)
225
+ throw new Error('Recorded text identity changed.')
226
+ records++
227
+ const links = recordPredecessors(event, pointer)
228
+ incomplete ||= links.incomplete
229
+ const texts =
230
+ input.seq === undefined || input.seq === pointer.seq ? eventTexts(event) : []
231
+ while (
232
+ cursor.textIndex < texts.length &&
233
+ parts < 64 &&
234
+ chunks < 64 &&
235
+ matches.length < input.limit
236
+ ) {
237
+ const part = cursor.textIndex
238
+ if (input.part !== undefined && part !== input.part) {
239
+ cursor.textIndex++
240
+ continue
241
+ }
242
+ parts++
243
+ try {
244
+ const derived =
245
+ input.excludeDerivedSummaries && texts[part]?.source === 'compaction_shed:summary'
246
+ if (
247
+ derived ||
248
+ excludesSuccessfulTool(
249
+ event.type === 'tool_completed' && typeof event.toolUseId === 'string'
250
+ ? event
251
+ : (texts[part] ?? {}),
252
+ input.excludeSuccessfulTools,
253
+ )
254
+ ) {
255
+ if (derived) excludedSummaries++
256
+ else excludedToolResults++
257
+ cursor.textIndex++
258
+ cursor.chunk = 0
259
+ cursor.within = 0
260
+ continue
261
+ }
262
+ const source = await readSource({ ...pointer, part }, raw)
263
+ if (source.retained === 'preview') incomplete = true
264
+ while (cursor.chunk < source.chunks && chunks < 64 && matches.length < input.limit) {
265
+ signal?.throwIfAborted()
266
+ chunks++
267
+ if (
268
+ (terms ?? [query]).some((term) =>
269
+ source.mayMatch(cursor.chunk, term, input.matchMode, input.caseSensitive),
270
+ )
271
+ ) {
272
+ const window = await source.window(cursor.chunk, input.matchMode === 'token')
273
+ const text = decode(window.bytes)
274
+ const page = passagesInWindow(
275
+ text,
276
+ Math.max(cursor.within, window.searchFrom ?? 0),
277
+ matchPassage,
278
+ input.limit - matches.length,
279
+ source.entry.spill
280
+ ? (cursor.chunk + 1) * EVIDENCE_CHUNK_BYTES - window.offset
281
+ : undefined,
282
+ )
283
+ cursor.within = page.next
284
+ for (const { start, end } of page.passages) {
285
+ const excerpt = text.slice(start, end)
286
+ const byteOffset = window.offset + Buffer.byteLength(text.slice(0, start))
287
+ matches.push({
288
+ address: seal.pack({ kind: 'linked-text', entry: { ...pointer, part } }),
289
+ seq: pointer.seq,
290
+ recordedAt: source.recordedAt,
291
+ source: source.entry.source,
292
+ part,
293
+ toolName: source.entry.toolName,
294
+ isError: source.entry.isError,
295
+ retained: source.retained,
296
+ excerpt,
297
+ excerptComplete:
298
+ source.retained === 'full' &&
299
+ byteOffset === 0 &&
300
+ Buffer.byteLength(excerpt) === source.bytes,
301
+ byteOffset,
302
+ characterOffset:
303
+ window.characterOffset === undefined
304
+ ? undefined
305
+ : window.characterOffset + start,
306
+ })
307
+ }
308
+ if (cursor.within < text.length) break
309
+ }
310
+ cursor.within = 0
311
+ cursor.chunk++
312
+ if (browse) cursor.chunk = source.chunks
313
+ }
314
+ if (cursor.chunk < source.chunks) break
315
+ } catch (error) {
316
+ signal?.throwIfAborted()
317
+ if (error instanceof EvidencePageLimit && (records > 1 || parts > 1 || chunks > 1))
318
+ break
319
+ unavailable.push(`Text record ${pointer.seq}/${part} is unavailable or changed.`)
320
+ }
321
+ cursor.textIndex++
322
+ cursor.chunk = 0
323
+ cursor.within = 0
324
+ }
325
+ if (cursor.textIndex < texts.length) break
326
+ cursor.next = links.next
327
+ cursor.textIndex = 0
328
+ cursor.chunk = 0
329
+ cursor.within = 0
330
+ }
331
+ return {
332
+ scope,
333
+ matches,
334
+ nextCursor: cursor.next ? seal.pack(cursor) : null,
335
+ scannedBytes: budget.bytes,
336
+ indexedRecords: records,
337
+ cacheHit: false,
338
+ incomplete: incomplete || unavailable.length > 0,
339
+ unavailable,
340
+ ...(excludedToolResults ? { excludedToolResults } : {}),
341
+ ...(excludedSummaries ? { excludedSummaries } : {}),
342
+ }
343
+ })
344
+ },
345
+ async read(options: RunEvidenceReadOptions, signal?: AbortSignal) {
346
+ const input = z
347
+ .object({
348
+ address: z.string().max(8192),
349
+ byteOffset: integer.default(0),
350
+ maxReadBytes: integer
351
+ .min(1024 * 1024)
352
+ .max(PAGE_BYTES)
353
+ .optional(),
354
+ })
355
+ .strict()
356
+ .parse(options)
357
+ return access(signal, input.maxReadBytes, async (handle, seal, budget) => {
358
+ const pointer = addressSchema.parse(seal.unpack(input.address)).entry
359
+ inBoundary(pointer)
360
+ const source = await createTextSourceReader(handle, runDir, scope.runId, budget)(pointer)
361
+ return readTextPage(source, scope, input.byteOffset, budget)
362
+ })
363
+ },
364
+ })
365
+ }
@@ -0,0 +1,88 @@
1
+ import { evidenceTokenMatcher } from '../../utils/evidence-tokens.js'
2
+
3
+ /** An exact excerpt; matching never rewrites the text or its UTF-16 positions. */
4
+ export interface EvidencePassage {
5
+ hit: number
6
+ start: number
7
+ end: number
8
+ next: number
9
+ }
10
+
11
+ /** Exact substring or token matching, without caller-selected regex operators. */
12
+ export function passageMatcher(
13
+ query: string | readonly string[],
14
+ caseSensitive: boolean,
15
+ matchMode: 'literal' | 'token' = 'literal',
16
+ ) {
17
+ const terms = typeof query === 'string' ? [query] : query
18
+ const tokenMatch = matchMode === 'token' ? evidenceTokenMatcher(terms, caseSensitive) : undefined
19
+ const expression =
20
+ caseSensitive && typeof query === 'string'
21
+ ? undefined
22
+ : new RegExp(
23
+ terms.map((term) => term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|'),
24
+ caseSensitive ? 'g' : 'giu',
25
+ )
26
+ const maxLength = Math.max(...terms.map((term) => term.length))
27
+ const find = (text: string, from: number) => {
28
+ if (tokenMatch) return tokenMatch(text, from)
29
+ if (expression) {
30
+ expression.lastIndex = from
31
+ const match = expression.exec(text)
32
+ return match ? { index: match.index, length: match[0].length } : undefined
33
+ }
34
+ const index = text.indexOf(terms[0] ?? '', from)
35
+ return index < 0 ? undefined : { index, length: terms[0]?.length ?? 0 }
36
+ }
37
+ return (text: string, from: number): EvidencePassage | undefined => {
38
+ const hit = find(text, from)?.index ?? -1
39
+ if (hit < 0 || (from >= text.length && query !== '')) return undefined
40
+ let start = Math.max(0, hit - 120)
41
+ if (start > 0 && /[\uDC00-\uDFFF]/.test(text[start] ?? '')) start--
42
+ let end = Math.min(text.length, start + 512)
43
+ if (end < text.length && /[\uDC00-\uDFFF]/.test(text[end] ?? '')) end--
44
+ // Nearby hits already fully shown by this excerpt need no second copy.
45
+ // A match crossing its end still deserves a complete later excerpt.
46
+ let next =
47
+ end === text.length || query === '' ? text.length : Math.max(hit + 1, end - maxLength + 1)
48
+ if (typeof query !== 'string' && end < text.length) {
49
+ // Different term lengths share one excerpt. Skip fully visible short
50
+ // matches, but keep the earliest long match that crosses its boundary.
51
+ let at = next
52
+ next = end
53
+ while (at < end) {
54
+ const crossing = find(text, at)
55
+ if (!crossing || crossing.index >= end) break
56
+ if (crossing.index + crossing.length > end) {
57
+ next = crossing.index
58
+ break
59
+ }
60
+ at = crossing.index + 1
61
+ if (/[\uDC00-\uDFFF]/.test(text[at] ?? '')) at++
62
+ }
63
+ }
64
+ if (/[\uDC00-\uDFFF]/.test(text[next] ?? '')) next++
65
+ return { hit, start, end, next }
66
+ }
67
+ }
68
+
69
+ /** Overlap bytes support boundary matches; starts in those bytes belong to the next window. */
70
+ export function passagesInWindow(
71
+ text: string,
72
+ from: number,
73
+ match: ReturnType<typeof passageMatcher>,
74
+ limit: number,
75
+ ownedBytes = Number.POSITIVE_INFINITY,
76
+ ): { passages: EvidencePassage[]; next: number } {
77
+ const passages: EvidencePassage[] = []
78
+ let next = from
79
+ while (passages.length < limit) {
80
+ const passage = match(text, next)
81
+ if (!passage || Buffer.byteLength(text.slice(0, passage.hit)) >= ownedBytes)
82
+ return { passages, next: text.length }
83
+ passages.push(passage)
84
+ next = passage.next
85
+ if (next >= text.length) break
86
+ }
87
+ return { passages, next }
88
+ }
@@ -0,0 +1,108 @@
1
+ import type { FileHandle } from 'node:fs/promises'
2
+ import { z } from 'zod'
3
+ import { digest } from './format.js'
4
+ import { eventTexts } from './index-page.js'
5
+ import { RECORD_BYTES, decode, openEvidence, readBytes } from './io.js'
6
+
7
+ const integer = z.number().int().nonnegative().safe()
8
+ export const recordPointerSchema = z.object({
9
+ offset: integer,
10
+ length: integer.positive().max(RECORD_BYTES),
11
+ sha256: z.string().regex(/^[a-f0-9]{64}$/),
12
+ seq: integer.positive(),
13
+ })
14
+ export type RecordPointer = z.infer<typeof recordPointerSchema>
15
+
16
+ /** Malformed content must still be visited and rejected by the reader. */
17
+ export function hasEvidenceText(event: Record<string, unknown>): boolean {
18
+ try {
19
+ return eventTexts(event).length > 0
20
+ } catch {
21
+ return true
22
+ }
23
+ }
24
+
25
+ /** Validate links even when a text-only traversal skips intervening operational records. */
26
+ export function recordPredecessors(event: Record<string, unknown>, pointer: RecordPointer) {
27
+ let previous: RecordPointer | null = null
28
+ let incomplete = false
29
+ if (event.previousRecord != null) {
30
+ previous = recordPointerSchema.parse(event.previousRecord)
31
+ if (previous.offset + previous.length !== pointer.offset || previous.seq + 1 !== pointer.seq)
32
+ throw new Error('Invalid text integrity chain.')
33
+ } else if (pointer.seq === 1) {
34
+ if (pointer.offset !== 0 || event.type !== 'run_started')
35
+ throw new Error('Invalid transcript start.')
36
+ } else {
37
+ incomplete = true
38
+ }
39
+ let next = previous
40
+ if (Object.hasOwn(event, 'previousTextRecord')) {
41
+ next = recordPointerSchema.nullable().parse(event.previousTextRecord)
42
+ if (
43
+ (next === null && previous !== null) ||
44
+ (next !== null &&
45
+ (previous === null ||
46
+ next.seq >= pointer.seq ||
47
+ next.offset + next.length > pointer.offset ||
48
+ (next.seq === previous.seq &&
49
+ (next.offset !== previous.offset ||
50
+ next.length !== previous.length ||
51
+ next.sha256 !== previous.sha256))))
52
+ )
53
+ throw new Error('Invalid text predecessor link.')
54
+ }
55
+ return { previous, next, incomplete }
56
+ }
57
+
58
+ /** Bootstrap only the last complete record, never load a growing log to capture a boundary. */
59
+ export async function transcriptTail(
60
+ path: string,
61
+ runId: string,
62
+ ): Promise<{ tip: RecordPointer; textTip?: RecordPointer | null } | undefined> {
63
+ let handle: FileHandle
64
+ try {
65
+ handle = await openEvidence(path)
66
+ } catch (error) {
67
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') return undefined
68
+ throw error
69
+ }
70
+ try {
71
+ const stat = await handle.stat()
72
+ if (!stat.size) return undefined
73
+ const offset = Math.max(0, stat.size - RECORD_BYTES)
74
+ const tail = await readBytes(handle, offset, stat.size - offset, { bytes: 0 })
75
+ if (tail.at(-1) !== 10) return undefined
76
+ const start = tail.lastIndexOf(10, tail.length - 2) + 1
77
+ if (start === 0 && offset !== 0) return undefined
78
+ const raw = tail.subarray(start)
79
+ let event: Record<string, unknown> | null
80
+ try {
81
+ event = JSON.parse(decode(raw))
82
+ } catch {
83
+ return undefined
84
+ }
85
+ if (event?.runId !== runId) return undefined
86
+ const pointer = recordPointerSchema.safeParse({
87
+ offset: offset + start,
88
+ length: raw.length,
89
+ sha256: digest(raw),
90
+ seq: event.seq,
91
+ })
92
+ if (!pointer.success) return undefined
93
+ const tip = pointer.data
94
+ // Starts, gaps and malformed records remain traversal barriers. They may
95
+ // never disappear behind a later text link after reopening the writer.
96
+ let textTip: RecordPointer | null | undefined = tip
97
+ try {
98
+ const links = recordPredecessors(event, tip)
99
+ if (!hasEvidenceText(event) && links.previous !== null)
100
+ textTip = Object.hasOwn(event, 'previousTextRecord') ? links.next : undefined
101
+ } catch {
102
+ // Keep the tail itself; retrieval will reject its malformed links.
103
+ }
104
+ return { tip, textTip }
105
+ } finally {
106
+ await handle.close()
107
+ }
108
+ }
@@ -0,0 +1,62 @@
1
+ import { z } from 'zod'
2
+ import { evidenceTokenKey, isEvidenceToken } from '../../utils/evidence-tokens.js'
3
+ import { digest } from './format.js'
4
+
5
+ export const evidenceTermsSchema = z
6
+ .array(
7
+ z
8
+ .string()
9
+ .min(1)
10
+ .max(256)
11
+ .refine((text) => text.trim().length > 0),
12
+ )
13
+ .min(1)
14
+ .max(16)
15
+ .optional()
16
+
17
+ /** Canonical membership binds continuations without putting long term lists in cursors. */
18
+ export function evidenceSearchInput(input: {
19
+ query?: string
20
+ terms?: string[]
21
+ matchMode?: 'literal' | 'token'
22
+ }) {
23
+ if (input.terms && input.query !== undefined)
24
+ throw new Error('Supply either a literal query or literal terms, not both.')
25
+ const terms = input.terms
26
+ ? [...new Set(input.terms)].sort((a, b) => b.length - a.length || (a < b ? -1 : a > b ? 1 : 0))
27
+ : undefined
28
+ if (input.matchMode === 'token' && !(terms ?? [input.query ?? '']).every(isEvidenceToken))
29
+ throw new Error('Token search requires nonempty letter/number/underscore tokens.')
30
+ return {
31
+ query: input.query ?? '',
32
+ terms,
33
+ termsKey: terms ? digest(JSON.stringify(terms)) : undefined,
34
+ browse: !terms && !input.query,
35
+ }
36
+ }
37
+
38
+ /** Refinement only narrows matching; it never resets scope, filters or position. */
39
+ export function evidenceTermRefinement(
40
+ input: {
41
+ terms?: readonly string[]
42
+ cursor?: string
43
+ matchMode?: string
44
+ caseSensitive?: boolean
45
+ },
46
+ refined: readonly string[],
47
+ ): string[] {
48
+ const terms = evidenceTermsSchema.parse(refined)
49
+ if (
50
+ !input.cursor ||
51
+ input.matchMode !== 'token' ||
52
+ !input.terms ||
53
+ !terms?.every(isEvidenceToken)
54
+ )
55
+ throw new Error('Term refinement requires a token cursor and its original terms.')
56
+ const key = (term: string) => evidenceTokenKey(term, input.caseSensitive ?? true)
57
+ const original = new Set(input.terms.map(key))
58
+ const subset = new Set(terms.map(key))
59
+ if (subset.size >= original.size || [...subset].some((term) => !original.has(term)))
60
+ throw new Error('Term refinement must be a strict nonempty subset of the original terms.')
61
+ return terms
62
+ }
@@ -0,0 +1,25 @@
1
+ import { z } from 'zod'
2
+ import { digest } from './format.js'
3
+
4
+ /** Host-selected search exclusion, never an authorization rule or inferred provenance. */
5
+ export const evidenceExclusionsSchema = z
6
+ .array(z.string().min(1).max(256))
7
+ .max(16)
8
+ .default([])
9
+ .transform((names) => [...new Set(names)].sort())
10
+
11
+ export function evidenceExclusionsKey(
12
+ names: readonly string[],
13
+ excludeDerivedSummaries = false,
14
+ ): string | undefined {
15
+ if (excludeDerivedSummaries)
16
+ return digest(JSON.stringify({ tools: names, derivedSummaries: true }))
17
+ return names.length ? digest(JSON.stringify(names)) : undefined
18
+ }
19
+
20
+ export function excludesSuccessfulTool(
21
+ entry: { toolName?: string; isError?: boolean },
22
+ names: readonly string[],
23
+ ): boolean {
24
+ return entry.isError === false && entry.toolName !== undefined && names.includes(entry.toolName)
25
+ }
@@ -0,0 +1,36 @@
1
+ /** Producer category derived from an evidence source tag, never from its prose. */
2
+ export type EvidenceRecordKind =
3
+ | 'assistant_message'
4
+ | 'tool_result'
5
+ | 'user_message'
6
+ | 'derived_summary'
7
+ | 'system_message'
8
+ | 'unknown'
9
+
10
+ /**
11
+ * Classify an already authenticated host source tag. This function performs no
12
+ * authentication and grants no authority, freshness or factual correctness.
13
+ * Custom labels stay unknown; do not pass labels parsed from quoted content.
14
+ */
15
+ export function classifyEvidenceSource(source: string): EvidenceRecordKind {
16
+ switch (source) {
17
+ case 'message_completed':
18
+ case 'compaction_shed:assistant':
19
+ return 'assistant_message'
20
+ case 'tool_completed':
21
+ case 'compaction_shed:tool':
22
+ return 'tool_result'
23
+ case 'compaction_shed:user':
24
+ return 'user_message'
25
+ case 'compaction_shed:summary':
26
+ return 'derived_summary'
27
+ case 'compaction_shed:system':
28
+ return 'system_message'
29
+ default:
30
+ return 'unknown'
31
+ }
32
+ }
33
+
34
+ /** Shared model-facing interpretation for hosts projecting recorded evidence. */
35
+ export const EVIDENCE_RECORD_GUIDANCE =
36
+ 'Producer kinds do not establish truth or independence. assistant_message is a prior model claim, not proof of observed state or successful action. Attribute it as a claim unless supported by the original observation; tool results may themselves quote claims.'