@tangle-network/agent-eval 0.129.0 → 0.130.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 (427) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +1 -0
  3. package/dist/active-curriculum-C4mk67HP.js +214 -0
  4. package/dist/active-curriculum-C4mk67HP.js.map +1 -0
  5. package/dist/adversarial-smnADNFS.d.ts +21 -0
  6. package/dist/adversarial-smnADNFS.d.ts.map +1 -0
  7. package/dist/analyst/index.d.ts +81 -2872
  8. package/dist/analyst/index.d.ts.map +1 -0
  9. package/dist/analyst/index.js +319 -360
  10. package/dist/analyst/index.js.map +1 -1
  11. package/dist/analyst-BkTS3C58.d.ts +89 -0
  12. package/dist/analyst-BkTS3C58.d.ts.map +1 -0
  13. package/dist/analyst-LsnNpSkm.js +152 -0
  14. package/dist/analyst-LsnNpSkm.js.map +1 -0
  15. package/dist/analyze-runs-C1CavBMk.js +1067 -0
  16. package/dist/analyze-runs-C1CavBMk.js.map +1 -0
  17. package/dist/analyze-runs-FsgYCinh.d.ts +72 -0
  18. package/dist/analyze-runs-FsgYCinh.d.ts.map +1 -0
  19. package/dist/attribute-vocabulary-DLJ6303h.d.ts +54 -0
  20. package/dist/attribute-vocabulary-DLJ6303h.d.ts.map +1 -0
  21. package/dist/authenticity/index.d.ts +81 -79
  22. package/dist/authenticity/index.d.ts.map +1 -0
  23. package/dist/authenticity/index.js +209 -193
  24. package/dist/authenticity/index.js.map +1 -1
  25. package/dist/baseline-HsBvw_dk.js +550 -0
  26. package/dist/baseline-HsBvw_dk.js.map +1 -0
  27. package/dist/baseline-hG3K85h4.d.ts +125 -0
  28. package/dist/baseline-hG3K85h4.d.ts.map +1 -0
  29. package/dist/belief-state/index.d.ts +448 -1188
  30. package/dist/belief-state/index.d.ts.map +1 -0
  31. package/dist/belief-state/index.js +1617 -1709
  32. package/dist/belief-state/index.js.map +1 -1
  33. package/dist/benchmarks/index.d.ts +2 -891
  34. package/dist/benchmarks/index.js +2 -60
  35. package/dist/benchmarks-DviOvUNr.js +754 -0
  36. package/dist/benchmarks-DviOvUNr.js.map +1 -0
  37. package/dist/builder-eval/index.d.ts +150 -662
  38. package/dist/builder-eval/index.d.ts.map +1 -0
  39. package/dist/builder-eval/index.js +356 -345
  40. package/dist/builder-eval/index.js.map +1 -1
  41. package/dist/calibration-CNWWA6K8.js +94 -0
  42. package/dist/calibration-CNWWA6K8.js.map +1 -0
  43. package/dist/campaign/index.d.ts +5 -6381
  44. package/dist/campaign/index.js +3 -213
  45. package/dist/campaign-CBKZvQ1H.js +3885 -0
  46. package/dist/campaign-CBKZvQ1H.js.map +1 -0
  47. package/dist/cli.d.ts +1 -1
  48. package/dist/cli.js +164 -175
  49. package/dist/cli.js.map +1 -1
  50. package/dist/client-C97NMzqi.d.ts +581 -0
  51. package/dist/client-C97NMzqi.d.ts.map +1 -0
  52. package/dist/client-CYzbdJOZ.js +637 -0
  53. package/dist/client-CYzbdJOZ.js.map +1 -0
  54. package/dist/code-agent-session-BjkMTQ7H.js +1390 -0
  55. package/dist/code-agent-session-BjkMTQ7H.js.map +1 -0
  56. package/dist/code-agent-session-DqqgOJaz.d.ts +143 -0
  57. package/dist/code-agent-session-DqqgOJaz.d.ts.map +1 -0
  58. package/dist/concurrency-DIxRZF_J.js +85 -0
  59. package/dist/concurrency-DIxRZF_J.js.map +1 -0
  60. package/dist/contract/index.d.ts +645 -5565
  61. package/dist/contract/index.d.ts.map +1 -0
  62. package/dist/contract/index.js +1730 -1938
  63. package/dist/contract/index.js.map +1 -1
  64. package/dist/control.d.ts +3 -1030
  65. package/dist/control.js +2 -33
  66. package/dist/cost-ledger-DIgQUFZZ.js +801 -0
  67. package/dist/cost-ledger-DIgQUFZZ.js.map +1 -0
  68. package/dist/cost-ledger-Dye6jCgg.d.ts +236 -0
  69. package/dist/cost-ledger-Dye6jCgg.d.ts.map +1 -0
  70. package/dist/dataset-BvtnC8Dc.d.ts +115 -0
  71. package/dist/dataset-BvtnC8Dc.d.ts.map +1 -0
  72. package/dist/default-registry-C-vFCSEc.js +2579 -0
  73. package/dist/default-registry-C-vFCSEc.js.map +1 -0
  74. package/dist/default-registry-CNPo-Vsb.d.ts +540 -0
  75. package/dist/default-registry-CNPo-Vsb.d.ts.map +1 -0
  76. package/dist/emitter-CPBAhxum.js +266 -0
  77. package/dist/emitter-CPBAhxum.js.map +1 -0
  78. package/dist/emitter-DGQGoLyj.d.ts +113 -0
  79. package/dist/emitter-DGQGoLyj.d.ts.map +1 -0
  80. package/dist/errors-8YnH8WlF.js +64 -0
  81. package/dist/errors-8YnH8WlF.js.map +1 -0
  82. package/dist/errors-CEk209JS.d.ts +76 -0
  83. package/dist/errors-CEk209JS.d.ts.map +1 -0
  84. package/dist/eval-campaign-DEm6c8ru.js +349 -0
  85. package/dist/eval-campaign-DEm6c8ru.js.map +1 -0
  86. package/dist/execution-tracks-CpgFPpS5.js +93 -0
  87. package/dist/execution-tracks-CpgFPpS5.js.map +1 -0
  88. package/dist/exporters-q9iL-2Jf.js +148 -0
  89. package/dist/exporters-q9iL-2Jf.js.map +1 -0
  90. package/dist/extract-usage-BrQ8mCLX.js +155 -0
  91. package/dist/extract-usage-BrQ8mCLX.js.map +1 -0
  92. package/dist/failure-cluster-CqcvCcdR.d.ts +59 -0
  93. package/dist/failure-cluster-CqcvCcdR.d.ts.map +1 -0
  94. package/dist/feedback-trajectory-CVaeREXV.d.ts +340 -0
  95. package/dist/feedback-trajectory-CVaeREXV.d.ts.map +1 -0
  96. package/dist/fuzz.d.ts +320 -646
  97. package/dist/fuzz.d.ts.map +1 -0
  98. package/dist/fuzz.js +670 -618
  99. package/dist/fuzz.js.map +1 -1
  100. package/dist/hf-dataset-DBJXXoY1.js +763 -0
  101. package/dist/hf-dataset-DBJXXoY1.js.map +1 -0
  102. package/dist/hosted/index.d.ts +11 -831
  103. package/dist/hosted/index.d.ts.map +1 -0
  104. package/dist/hosted/index.js +2 -37
  105. package/dist/index-2JJSA6-r2.d.ts +926 -0
  106. package/dist/index-2JJSA6-r2.d.ts.map +1 -0
  107. package/dist/index-6N0aYmpW.d.ts +217 -0
  108. package/dist/index-6N0aYmpW.d.ts.map +1 -0
  109. package/dist/index-BAvgST_9.d.ts +131 -0
  110. package/dist/index-BAvgST_9.d.ts.map +1 -0
  111. package/dist/index-BvnJuTGD.d.ts +68 -0
  112. package/dist/index-BvnJuTGD.d.ts.map +1 -0
  113. package/dist/index-C61Wi7yg.d.ts +547 -0
  114. package/dist/index-C61Wi7yg.d.ts.map +1 -0
  115. package/dist/index-CAPUUKaM.d.ts +335 -0
  116. package/dist/index-CAPUUKaM.d.ts.map +1 -0
  117. package/dist/index-DE5fb3EC.d.ts +2244 -0
  118. package/dist/index-DE5fb3EC.d.ts.map +1 -0
  119. package/dist/index-DSC51roc.d.ts +102 -0
  120. package/dist/index-DSC51roc.d.ts.map +1 -0
  121. package/dist/index.d.ts +3755 -15555
  122. package/dist/index.d.ts.map +1 -0
  123. package/dist/index.js +11182 -11216
  124. package/dist/index.js.map +1 -1
  125. package/dist/integrity-BzRbCHzi.js +424 -0
  126. package/dist/integrity-BzRbCHzi.js.map +1 -0
  127. package/dist/integrity-rmVhXWA7.d.ts +61 -0
  128. package/dist/integrity-rmVhXWA7.d.ts.map +1 -0
  129. package/dist/judge-calibration-DFtEMlde.d.ts +146 -0
  130. package/dist/judge-calibration-DFtEMlde.d.ts.map +1 -0
  131. package/dist/ledger-core/index.d.ts +2 -0
  132. package/dist/ledger-core/index.js +2 -0
  133. package/dist/ledger-core-DtZz1RG0.js +388 -0
  134. package/dist/ledger-core-DtZz1RG0.js.map +1 -0
  135. package/dist/llm-client--GR4JbZE.js +687 -0
  136. package/dist/llm-client--GR4JbZE.js.map +1 -0
  137. package/dist/llm-client-B_nIBlYo.d.ts +290 -0
  138. package/dist/llm-client-B_nIBlYo.d.ts.map +1 -0
  139. package/dist/matrix/index.d.ts +3 -155
  140. package/dist/matrix/index.js +2 -8
  141. package/dist/matrix-BzQnu2S6.js +270 -0
  142. package/dist/matrix-BzQnu2S6.js.map +1 -0
  143. package/dist/meta-eval/index.d.ts +4 -1027
  144. package/dist/meta-eval/index.js +393 -390
  145. package/dist/meta-eval/index.js.map +1 -1
  146. package/dist/metrics-C9YY1OcL.js +239 -0
  147. package/dist/metrics-C9YY1OcL.js.map +1 -0
  148. package/dist/mint-yN2M2eh0.js +201 -0
  149. package/dist/mint-yN2M2eh0.js.map +1 -0
  150. package/dist/multi-layer-verifier-BHY1gWAc.d.ts +138 -0
  151. package/dist/multi-layer-verifier-BHY1gWAc.d.ts.map +1 -0
  152. package/dist/multishot/index.d.ts +273 -480
  153. package/dist/multishot/index.d.ts.map +1 -0
  154. package/dist/multishot/index.js +595 -548
  155. package/dist/multishot/index.js.map +1 -1
  156. package/dist/off-policy-DvgzvtIx.js +220 -0
  157. package/dist/off-policy-DvgzvtIx.js.map +1 -0
  158. package/dist/off-policy-mskQw8Mb.d.ts +153 -0
  159. package/dist/off-policy-mskQw8Mb.d.ts.map +1 -0
  160. package/dist/openapi.json +1 -1
  161. package/dist/opencode-sqlite-BGrHeDu3.js +318 -0
  162. package/dist/opencode-sqlite-BGrHeDu3.js.map +1 -0
  163. package/dist/outcome-store-BYHIuO0e.d.ts +65 -0
  164. package/dist/outcome-store-BYHIuO0e.d.ts.map +1 -0
  165. package/dist/outcome-store-ChBKlTd_.js +75 -0
  166. package/dist/outcome-store-ChBKlTd_.js.map +1 -0
  167. package/dist/paired-arms-D9D0wXj2.js +260 -0
  168. package/dist/paired-arms-D9D0wXj2.js.map +1 -0
  169. package/dist/pipelines/index.d.ts +95 -532
  170. package/dist/pipelines/index.d.ts.map +1 -0
  171. package/dist/pipelines/index.js +497 -478
  172. package/dist/pipelines/index.js.map +1 -1
  173. package/dist/pre-registration-DakwTRXk.js +96 -0
  174. package/dist/pre-registration-DakwTRXk.js.map +1 -0
  175. package/dist/propose-review-control-LhIWGzHl.js +1458 -0
  176. package/dist/propose-review-control-LhIWGzHl.js.map +1 -0
  177. package/dist/query-CJ_DX8vl.d.ts +28 -0
  178. package/dist/query-CJ_DX8vl.d.ts.map +1 -0
  179. package/dist/query-Di7eEQ79.js +83 -0
  180. package/dist/query-Di7eEQ79.js.map +1 -0
  181. package/dist/raw-provider-sink-BQd7mzyT.js +201 -0
  182. package/dist/raw-provider-sink-BQd7mzyT.js.map +1 -0
  183. package/dist/raw-provider-sink-BU29Sh8h.d.ts +134 -0
  184. package/dist/raw-provider-sink-BU29Sh8h.d.ts.map +1 -0
  185. package/dist/redact-7Aq1ukl-.js +107 -0
  186. package/dist/redact-7Aq1ukl-.js.map +1 -0
  187. package/dist/release-report-Cz9NKH39.js +603 -0
  188. package/dist/release-report-Cz9NKH39.js.map +1 -0
  189. package/dist/release-report-mvB2G4_J.d.ts +244 -0
  190. package/dist/release-report-mvB2G4_J.d.ts.map +1 -0
  191. package/dist/replay-GnyotH0J.js +1741 -0
  192. package/dist/replay-GnyotH0J.js.map +1 -0
  193. package/dist/replay-OoidtG1E.d.ts +749 -0
  194. package/dist/replay-OoidtG1E.d.ts.map +1 -0
  195. package/dist/reporting.d.ts +6 -1312
  196. package/dist/reporting.js +6 -51
  197. package/dist/researcher-CwTdwXG1.d.ts +314 -0
  198. package/dist/researcher-CwTdwXG1.d.ts.map +1 -0
  199. package/dist/reward-hacking-eAnOsynk.d.ts +224 -0
  200. package/dist/reward-hacking-eAnOsynk.d.ts.map +1 -0
  201. package/dist/reward-hacking-qipEpKvY.js +596 -0
  202. package/dist/reward-hacking-qipEpKvY.js.map +1 -0
  203. package/dist/reward-nw2xZGZG.js +137 -0
  204. package/dist/reward-nw2xZGZG.js.map +1 -0
  205. package/dist/rl.d.ts +760 -4010
  206. package/dist/rl.d.ts.map +1 -0
  207. package/dist/rl.js +2325 -1958
  208. package/dist/rl.js.map +1 -1
  209. package/dist/rolldown-runtime-8H4AJuhK.js +14 -0
  210. package/dist/rollout/index.d.ts +3 -2087
  211. package/dist/rollout/index.js +8 -168
  212. package/dist/rollout-BOYjemfR.js +624 -0
  213. package/dist/rollout-BOYjemfR.js.map +1 -0
  214. package/dist/rubric-predictive-validity-B3xmbmS1.js +141 -0
  215. package/dist/rubric-predictive-validity-B3xmbmS1.js.map +1 -0
  216. package/dist/rubric-predictive-validity-Ku_clp_1.d.ts +74 -0
  217. package/dist/rubric-predictive-validity-Ku_clp_1.d.ts.map +1 -0
  218. package/dist/run-evidence-ClRX_8A9.d.ts +225 -0
  219. package/dist/run-evidence-ClRX_8A9.d.ts.map +1 -0
  220. package/dist/run-record-BuoE80Dq.js +467 -0
  221. package/dist/{chunk-56TAVBOK.js.map → run-record-BuoE80Dq.js.map} +1 -1
  222. package/dist/run-record-CnZu_gjl.d.ts +357 -0
  223. package/dist/run-record-CnZu_gjl.d.ts.map +1 -0
  224. package/dist/run-score-iEEAWiBY.js +41 -0
  225. package/dist/run-score-iEEAWiBY.js.map +1 -0
  226. package/dist/runtime-trajectory-1gyaTOoC.js +93 -0
  227. package/dist/runtime-trajectory-1gyaTOoC.js.map +1 -0
  228. package/dist/runtime-trajectory-BvSZcCHD.d.ts +50 -0
  229. package/dist/runtime-trajectory-BvSZcCHD.d.ts.map +1 -0
  230. package/dist/schema-BtVldJ3T.d.ts +206 -0
  231. package/dist/schema-BtVldJ3T.d.ts.map +1 -0
  232. package/dist/schema-C6DW4ZHR.js +821 -0
  233. package/dist/schema-C6DW4ZHR.js.map +1 -0
  234. package/dist/schema-CRhEY1SO.js +69 -0
  235. package/dist/schema-CRhEY1SO.js.map +1 -0
  236. package/dist/schema-Cef2cFmb.d.ts +408 -0
  237. package/dist/schema-Cef2cFmb.d.ts.map +1 -0
  238. package/dist/semantic-concept-judge-B6cWNJ2K.js +725 -0
  239. package/dist/semantic-concept-judge-B6cWNJ2K.js.map +1 -0
  240. package/dist/sequential-Br0mAPHA.js +148 -0
  241. package/dist/sequential-Br0mAPHA.js.map +1 -0
  242. package/dist/sequential-CYwq6Ff_.d.ts +141 -0
  243. package/dist/sequential-CYwq6Ff_.d.ts.map +1 -0
  244. package/dist/series-convergence-CjO2QdRW.js +43 -0
  245. package/dist/series-convergence-CjO2QdRW.js.map +1 -0
  246. package/dist/series-convergence-ofsqPWhs.d.ts +35 -0
  247. package/dist/series-convergence-ofsqPWhs.d.ts.map +1 -0
  248. package/dist/server-m5D9cvnG.js +1040 -0
  249. package/dist/server-m5D9cvnG.js.map +1 -0
  250. package/dist/skill-usage-C_pXm7lP.d.ts +534 -0
  251. package/dist/skill-usage-C_pXm7lP.d.ts.map +1 -0
  252. package/dist/skillopt-optimization-method-B7wX7XkF.d.ts +1739 -0
  253. package/dist/skillopt-optimization-method-B7wX7XkF.d.ts.map +1 -0
  254. package/dist/skillopt-optimization-method-D4ODwFVV.js +7712 -0
  255. package/dist/skillopt-optimization-method-D4ODwFVV.js.map +1 -0
  256. package/dist/statistics-Cmj6nynr.d.ts +514 -0
  257. package/dist/statistics-Cmj6nynr.d.ts.map +1 -0
  258. package/dist/statistics-CnnxdpOg.js +1437 -0
  259. package/dist/statistics-CnnxdpOg.js.map +1 -0
  260. package/dist/store-CT9YIIve.d.ts +117 -0
  261. package/dist/store-CT9YIIve.d.ts.map +1 -0
  262. package/dist/store-CxJry_cs.d.ts +229 -0
  263. package/dist/store-CxJry_cs.d.ts.map +1 -0
  264. package/dist/storyboard/index.d.ts +84 -203
  265. package/dist/storyboard/index.d.ts.map +1 -0
  266. package/dist/storyboard/index.js +609 -542
  267. package/dist/storyboard/index.js.map +1 -1
  268. package/dist/summary-report-BNs5nmXI.js +862 -0
  269. package/dist/summary-report-BNs5nmXI.js.map +1 -0
  270. package/dist/summary-report-Cj9gdw4i.d.ts +407 -0
  271. package/dist/summary-report-Cj9gdw4i.d.ts.map +1 -0
  272. package/dist/supervisor-run/index.d.ts +2 -959
  273. package/dist/supervisor-run/index.js +2 -65
  274. package/dist/supervisor-run-_lnTLM3z.js +1679 -0
  275. package/dist/supervisor-run-_lnTLM3z.js.map +1 -0
  276. package/dist/task-failure-attributes-CQZlB3et.js +311 -0
  277. package/dist/task-failure-attributes-CQZlB3et.js.map +1 -0
  278. package/dist/test-graded-scenario-BsqWLmPt.js +318 -0
  279. package/dist/test-graded-scenario-BsqWLmPt.js.map +1 -0
  280. package/dist/test-graded-scenario-D1TaI2va.d.ts +141 -0
  281. package/dist/test-graded-scenario-D1TaI2va.d.ts.map +1 -0
  282. package/dist/tools-BmuN627J.js +1085 -0
  283. package/dist/tools-BmuN627J.js.map +1 -0
  284. package/dist/trace-attributes.d.ts +2 -52
  285. package/dist/trace-attributes.js +131 -61
  286. package/dist/trace-attributes.js.map +1 -1
  287. package/dist/traces.d.ts +12 -2365
  288. package/dist/traces.js +12 -252
  289. package/dist/trajectory-D_7rLrvE.js +56 -0
  290. package/dist/trajectory-D_7rLrvE.js.map +1 -0
  291. package/dist/types-DGsxbAEd.d.ts +387 -0
  292. package/dist/types-DGsxbAEd.d.ts.map +1 -0
  293. package/dist/types-k9tZGKUg.d.ts +640 -0
  294. package/dist/types-k9tZGKUg.d.ts.map +1 -0
  295. package/dist/verdict-Dps8_okt.d.ts +37 -0
  296. package/dist/verdict-Dps8_okt.d.ts.map +1 -0
  297. package/dist/wire/index.d.ts +702 -1173
  298. package/dist/wire/index.d.ts.map +1 -0
  299. package/dist/wire/index.js +2 -81
  300. package/package.json +17 -9
  301. package/dist/benchmarks/index.js.map +0 -1
  302. package/dist/campaign/index.js.map +0 -1
  303. package/dist/chunk-2QU3YOPR.js +0 -7374
  304. package/dist/chunk-2QU3YOPR.js.map +0 -1
  305. package/dist/chunk-3OCR4R5I.js +0 -728
  306. package/dist/chunk-3OCR4R5I.js.map +0 -1
  307. package/dist/chunk-3RF76KTD.js +0 -84
  308. package/dist/chunk-3RF76KTD.js.map +0 -1
  309. package/dist/chunk-56TAVBOK.js +0 -698
  310. package/dist/chunk-5DTSBUL2.js +0 -159
  311. package/dist/chunk-5DTSBUL2.js.map +0 -1
  312. package/dist/chunk-7FO3TNPI.js +0 -232
  313. package/dist/chunk-7FO3TNPI.js.map +0 -1
  314. package/dist/chunk-7ZZMD7UK.js +0 -386
  315. package/dist/chunk-7ZZMD7UK.js.map +0 -1
  316. package/dist/chunk-BOD4O7OF.js +0 -40
  317. package/dist/chunk-BOD4O7OF.js.map +0 -1
  318. package/dist/chunk-BSO5JDQH.js +0 -2335
  319. package/dist/chunk-BSO5JDQH.js.map +0 -1
  320. package/dist/chunk-C6LXANRU.js +0 -1550
  321. package/dist/chunk-C6LXANRU.js.map +0 -1
  322. package/dist/chunk-DODXQREJ.js +0 -752
  323. package/dist/chunk-DODXQREJ.js.map +0 -1
  324. package/dist/chunk-DRYIUNWY.js +0 -622
  325. package/dist/chunk-DRYIUNWY.js.map +0 -1
  326. package/dist/chunk-E7QXT7SX.js +0 -183
  327. package/dist/chunk-E7QXT7SX.js.map +0 -1
  328. package/dist/chunk-EG66UGL4.js +0 -341
  329. package/dist/chunk-EG66UGL4.js.map +0 -1
  330. package/dist/chunk-FXTVJPYD.js +0 -576
  331. package/dist/chunk-FXTVJPYD.js.map +0 -1
  332. package/dist/chunk-G7MGMCZD.js +0 -153
  333. package/dist/chunk-G7MGMCZD.js.map +0 -1
  334. package/dist/chunk-GGE4NNQT.js +0 -65
  335. package/dist/chunk-GGE4NNQT.js.map +0 -1
  336. package/dist/chunk-H23X7XKK.js +0 -181
  337. package/dist/chunk-H23X7XKK.js.map +0 -1
  338. package/dist/chunk-HHWE3POT.js +0 -94
  339. package/dist/chunk-HHWE3POT.js.map +0 -1
  340. package/dist/chunk-HPWUNB47.js +0 -289
  341. package/dist/chunk-HPWUNB47.js.map +0 -1
  342. package/dist/chunk-IYCLP2N2.js +0 -766
  343. package/dist/chunk-IYCLP2N2.js.map +0 -1
  344. package/dist/chunk-JHCHEVET.js +0 -274
  345. package/dist/chunk-JHCHEVET.js.map +0 -1
  346. package/dist/chunk-JQSF5DQT.js +0 -701
  347. package/dist/chunk-JQSF5DQT.js.map +0 -1
  348. package/dist/chunk-K4DBDHLK.js +0 -158
  349. package/dist/chunk-K4DBDHLK.js.map +0 -1
  350. package/dist/chunk-K6N6XJJX.js +0 -306
  351. package/dist/chunk-K6N6XJJX.js.map +0 -1
  352. package/dist/chunk-M4YBQKIJ.js +0 -1040
  353. package/dist/chunk-M4YBQKIJ.js.map +0 -1
  354. package/dist/chunk-MA6HLL3S.js +0 -65
  355. package/dist/chunk-MA6HLL3S.js.map +0 -1
  356. package/dist/chunk-MAZ26DC7.js +0 -99
  357. package/dist/chunk-MAZ26DC7.js.map +0 -1
  358. package/dist/chunk-NPCTHQIO.js +0 -91
  359. package/dist/chunk-NPCTHQIO.js.map +0 -1
  360. package/dist/chunk-NY44NC4A.js +0 -1056
  361. package/dist/chunk-NY44NC4A.js.map +0 -1
  362. package/dist/chunk-OIUOT4QD.js +0 -44
  363. package/dist/chunk-OIUOT4QD.js.map +0 -1
  364. package/dist/chunk-ONWEPEDO.js +0 -57
  365. package/dist/chunk-ONWEPEDO.js.map +0 -1
  366. package/dist/chunk-OWN5NPMC.js +0 -152
  367. package/dist/chunk-OWN5NPMC.js.map +0 -1
  368. package/dist/chunk-P6FYH6K4.js +0 -1161
  369. package/dist/chunk-P6FYH6K4.js.map +0 -1
  370. package/dist/chunk-PC4UYEBM.js +0 -166
  371. package/dist/chunk-PC4UYEBM.js.map +0 -1
  372. package/dist/chunk-PC5DOSM7.js +0 -579
  373. package/dist/chunk-PC5DOSM7.js.map +0 -1
  374. package/dist/chunk-PXE2VKMX.js +0 -140
  375. package/dist/chunk-PXE2VKMX.js.map +0 -1
  376. package/dist/chunk-PZ5AY32C.js +0 -10
  377. package/dist/chunk-PZ5AY32C.js.map +0 -1
  378. package/dist/chunk-QB6BDBP2.js +0 -4464
  379. package/dist/chunk-QB6BDBP2.js.map +0 -1
  380. package/dist/chunk-RXHCETDZ.js +0 -536
  381. package/dist/chunk-RXHCETDZ.js.map +0 -1
  382. package/dist/chunk-RZTMDUO7.js +0 -49
  383. package/dist/chunk-RZTMDUO7.js.map +0 -1
  384. package/dist/chunk-SFLLL76A.js +0 -669
  385. package/dist/chunk-SFLLL76A.js.map +0 -1
  386. package/dist/chunk-SZLVEKMJ.js +0 -1446
  387. package/dist/chunk-SZLVEKMJ.js.map +0 -1
  388. package/dist/chunk-T4SQEITX.js +0 -95
  389. package/dist/chunk-T4SQEITX.js.map +0 -1
  390. package/dist/chunk-T6RLYGAD.js +0 -158
  391. package/dist/chunk-T6RLYGAD.js.map +0 -1
  392. package/dist/chunk-TJVT4QFF.js +0 -911
  393. package/dist/chunk-TJVT4QFF.js.map +0 -1
  394. package/dist/chunk-TQ7LNKZ3.js +0 -136
  395. package/dist/chunk-TQ7LNKZ3.js.map +0 -1
  396. package/dist/chunk-U4L7JRPZ.js +0 -1706
  397. package/dist/chunk-U4L7JRPZ.js.map +0 -1
  398. package/dist/chunk-U4PHLT2N.js +0 -419
  399. package/dist/chunk-U4PHLT2N.js.map +0 -1
  400. package/dist/chunk-VCZ5FQYW.js +0 -928
  401. package/dist/chunk-VCZ5FQYW.js.map +0 -1
  402. package/dist/chunk-VI2UW6B6.js +0 -162
  403. package/dist/chunk-VI2UW6B6.js.map +0 -1
  404. package/dist/chunk-VQMK5FMP.js +0 -247
  405. package/dist/chunk-VQMK5FMP.js.map +0 -1
  406. package/dist/chunk-WGXIEX7P.js +0 -116
  407. package/dist/chunk-WGXIEX7P.js.map +0 -1
  408. package/dist/chunk-WVATSFCP.js +0 -1553
  409. package/dist/chunk-WVATSFCP.js.map +0 -1
  410. package/dist/chunk-X4YIBDER.js +0 -1662
  411. package/dist/chunk-X4YIBDER.js.map +0 -1
  412. package/dist/chunk-YQN4ICPP.js +0 -355
  413. package/dist/chunk-YQN4ICPP.js.map +0 -1
  414. package/dist/chunk-ZET2UAYW.js +0 -89
  415. package/dist/chunk-ZET2UAYW.js.map +0 -1
  416. package/dist/chunk-ZHTZ4EYI.js +0 -1212
  417. package/dist/chunk-ZHTZ4EYI.js.map +0 -1
  418. package/dist/control.js.map +0 -1
  419. package/dist/hosted/index.js.map +0 -1
  420. package/dist/matrix/index.js.map +0 -1
  421. package/dist/reporting.js.map +0 -1
  422. package/dist/rollout/index.js.map +0 -1
  423. package/dist/run-campaign-OJJ7CZF4.js +0 -18
  424. package/dist/run-campaign-OJJ7CZF4.js.map +0 -1
  425. package/dist/supervisor-run/index.js.map +0 -1
  426. package/dist/traces.js.map +0 -1
  427. package/dist/wire/index.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"propose-review-control-LhIWGzHl.js","names":["DEFAULT_FALLBACK_INSTRUCTION"],"sources":["../src/action-policy.ts","../src/detectors/index.ts","../src/control-runtime.ts","../src/run-evidence.ts","../src/propose-review.ts","../src/propose-review-control.ts"],"sourcesContent":["import type { FeedbackLabel, ProposedSideEffect } from './feedback-trajectory'\n\nexport interface ActionExecutionPolicy {\n allowedTypes?: string[]\n blockedTypes?: string[]\n alwaysRequireApprovalTypes?: string[]\n autoApproveTypes?: string[]\n requireApprovalForExternalSideEffects?: boolean\n requireApprovalAboveCostUsd?: number\n maxActionCostUsd?: number\n remainingBudgetUsd?: number\n expectedOutcomeRequired?: boolean\n killCriteriaRequired?: boolean\n}\n\nexport interface ActionPolicyDecision {\n allowed: boolean\n blocked: boolean\n requiresApproval: boolean\n reasons: string[]\n label?: FeedbackLabel\n}\n\nexport function evaluateActionPolicy(\n action: ProposedSideEffect,\n policy: ActionExecutionPolicy = {},\n options: { createdAt?: string } = {},\n): ActionPolicyDecision {\n const reasons: string[] = []\n let blocked = false\n let requiresApproval = Boolean(action.requiresApproval)\n\n if (policy.allowedTypes?.length && !policy.allowedTypes.includes(action.type)) {\n blocked = true\n reasons.push(`action type \"${action.type}\" is not allowed`)\n }\n if (policy.blockedTypes?.includes(action.type)) {\n blocked = true\n reasons.push(`action type \"${action.type}\" is blocked`)\n }\n if (policy.alwaysRequireApprovalTypes?.includes(action.type)) {\n requiresApproval = true\n reasons.push(`action type \"${action.type}\" requires approval`)\n }\n if (policy.requireApprovalForExternalSideEffects && action.externalSideEffect) {\n requiresApproval = true\n reasons.push('external side effect requires approval')\n }\n if (\n policy.requireApprovalAboveCostUsd !== undefined &&\n (action.costUsd ?? 0) > policy.requireApprovalAboveCostUsd\n ) {\n requiresApproval = true\n reasons.push(\n `cost ${action.costUsd} exceeds approval threshold ${policy.requireApprovalAboveCostUsd}`,\n )\n }\n if (policy.maxActionCostUsd !== undefined && (action.costUsd ?? 0) > policy.maxActionCostUsd) {\n blocked = true\n reasons.push(`cost ${action.costUsd} exceeds max action cost ${policy.maxActionCostUsd}`)\n }\n if (\n policy.remainingBudgetUsd !== undefined &&\n (action.costUsd ?? 0) > policy.remainingBudgetUsd\n ) {\n blocked = true\n reasons.push(`cost ${action.costUsd} exceeds remaining budget ${policy.remainingBudgetUsd}`)\n }\n if (policy.expectedOutcomeRequired && !action.metadata?.expectedOutcome) {\n blocked = true\n reasons.push('expected outcome is required')\n }\n if (policy.killCriteriaRequired && !action.metadata?.killCriteria) {\n blocked = true\n reasons.push('kill criteria are required')\n }\n if (policy.autoApproveTypes?.includes(action.type) && requiresApproval) {\n reasons.push(\n `action type \"${action.type}\" is auto-approved only when no approval policy applies`,\n )\n }\n\n if (!reasons.length) reasons.push(requiresApproval ? 'approval required' : 'action allowed')\n\n const label =\n blocked || requiresApproval\n ? {\n source: 'policy' as const,\n kind: blocked ? ('policy_block' as const) : ('comment' as const),\n value: { actionType: action.type, blocked, requiresApproval },\n reason: reasons.join('; '),\n severity: blocked ? ('critical' as const) : ('warning' as const),\n createdAt: options.createdAt ?? new Date().toISOString(),\n metadata: { action, policy },\n }\n : undefined\n\n return {\n allowed: !blocked,\n blocked,\n requiresApproval: !blocked && requiresApproval,\n reasons,\n label,\n }\n}\n","/**\n * Streaming detectors — the canonical, online failure-mode kernel.\n *\n * A `StreamingDetector` is a pure incremental reducer: fold one normalized step, get a signal the\n * moment a threshold trips (else null). The SAME kernel runs in two places, so the logic lives once:\n * - ONLINE, over a live agent pipe (a worker's tool-call stream) → raise a finding mid-run.\n * - INSIDE the control loop (`control-runtime`) → its `stopOn*` policies fold these detectors.\n *\n * Detectors are stateful but self-contained; `streak` is exposed for telemetry and `reset` clears it.\n * Fingerprinting is the CALLER's job — the control loop hashes state/action with `stableFingerprint`,\n * a tool-call pipe hashes args with `argHash` — so a detector stays agnostic to what it's watching.\n */\n\nimport type { FailureClass } from '../trace/schema'\n\nexport type DetectorSeverity = 'info' | 'warn' | 'critical'\n\n/** A normalized step a detector folds over. Fields are optional; each detector reads only what it\n * needs (repeated-action → `actionFingerprint`; no-progress → `stateFingerprint` + `score`;\n * error-streak → `status`). */\nexport interface DetectorEvent {\n /** Fingerprint of the action/tool-call this step took (caller pre-hashes). */\n readonly actionFingerprint?: string\n /** Fingerprint of observable state AFTER this step. */\n readonly stateFingerprint?: string\n /** Score after this step (the score-flat half of no-progress). */\n readonly score?: number\n /** Whether this step errored. */\n readonly status?: 'ok' | 'error'\n /** Free-form label carried into the signal evidence (e.g. the tool name). */\n readonly label?: string\n}\n\nexport interface DetectorSignal {\n readonly detector: string\n readonly severity: DetectorSeverity\n readonly failureClass?: FailureClass\n readonly reason: string\n /** Consecutive matching steps at the moment the signal fired. */\n readonly streak: number\n readonly evidence?: Record<string, unknown>\n}\n\nexport interface StreamingDetector {\n readonly id: string\n /** Current streak (consecutive matching steps) — for telemetry/introspection between observes. */\n readonly streak: number\n /** Fold one event; return a signal when the threshold trips, else null. */\n observe(event: DetectorEvent): DetectorSignal | null\n /** Clear all state. */\n reset(): void\n}\n\nexport interface RepeatedActionOptions {\n /** Signal once the same action fingerprint repeats this many CONSECUTIVE steps (default 3).\n * `<= 0` disables the signal (the streak is still tracked, for telemetry). */\n readonly maxRepeated?: number\n readonly severity?: DetectorSeverity\n /** Failure class to stamp on the signal (default `tool_recovery_failure`). */\n readonly failureClass?: FailureClass\n}\n\n/** Same action fingerprint N consecutive steps = a stuck loop (the #1 long-horizon failure mode). */\nexport function repeatedActionDetector(opts: RepeatedActionOptions = {}): StreamingDetector {\n const max = opts.maxRepeated ?? 3\n const severity = opts.severity ?? 'warn'\n const failureClass: FailureClass = opts.failureClass ?? 'tool_recovery_failure'\n let last: string | undefined\n let streak = 0\n return {\n id: 'repeated-action',\n get streak() {\n return streak\n },\n observe(event) {\n const fp = event.actionFingerprint\n if (fp === undefined) return null\n streak = fp === last ? streak + 1 : 1\n last = fp\n if (max <= 0 || streak < max) return null\n return {\n detector: 'repeated-action',\n severity,\n failureClass,\n reason: `stuck: repeated same action for ${streak} step(s)`,\n streak,\n ...(event.label ? { evidence: { action: event.label } } : {}),\n }\n },\n reset() {\n last = undefined\n streak = 0\n },\n }\n}\n\nexport interface NoProgressOptions {\n /** Signal once state is unchanged AND score is flat for this many CONSECUTIVE steps (default 3).\n * `<= 0` disables the signal. */\n readonly maxNoProgress?: number\n /** Minimum |score change| that counts as progress (default 0.001). */\n readonly minScoreDelta?: number\n readonly severity?: DetectorSeverity\n readonly failureClass?: FailureClass\n}\n\n/** State + score unchanged across N steps = spinning wheels. Compares each step to the previous one,\n * so prime with the initial state (observe it once before the first real step) to detect on step 1. */\nexport function noProgressDetector(opts: NoProgressOptions = {}): StreamingDetector {\n const max = opts.maxNoProgress ?? 3\n const minScoreDelta = opts.minScoreDelta ?? 0.001\n const severity = opts.severity ?? 'warn'\n const failureClass: FailureClass = opts.failureClass ?? 'tool_recovery_failure'\n let lastState: string | undefined\n let lastScore: number | undefined\n let streak = 0\n return {\n id: 'no-progress',\n get streak() {\n return streak\n },\n observe(event) {\n const stateUnchanged = lastState !== undefined && lastState === event.stateFingerprint\n const scoreFlat = Math.abs((event.score ?? 0) - (lastScore ?? 0)) < minScoreDelta\n streak = stateUnchanged && scoreFlat ? streak + 1 : 0\n lastState = event.stateFingerprint\n lastScore = event.score\n if (max <= 0 || streak < max) return null\n return {\n detector: 'no-progress',\n severity,\n failureClass,\n reason: `stuck: no state/score progress for ${streak} step(s)`,\n streak,\n ...(event.label ? { evidence: { state: event.label } } : {}),\n }\n },\n reset() {\n lastState = undefined\n lastScore = undefined\n streak = 0\n },\n }\n}\n\nexport interface ErrorStreakOptions {\n /** Signal once this many CONSECUTIVE steps errored (default 3). `<= 0` disables. */\n readonly maxErrors?: number\n readonly severity?: DetectorSeverity\n readonly failureClass?: FailureClass\n}\n\n/** N consecutive tool errors = the worker is hammering a broken approach. */\nexport function errorStreakDetector(opts: ErrorStreakOptions = {}): StreamingDetector {\n const max = opts.maxErrors ?? 3\n const severity = opts.severity ?? 'warn'\n const failureClass: FailureClass = opts.failureClass ?? 'tool_recovery_failure'\n let streak = 0\n return {\n id: 'error-streak',\n get streak() {\n return streak\n },\n observe(event) {\n if (event.status === undefined) return null\n streak = event.status === 'error' ? streak + 1 : 0\n if (max <= 0 || streak < max) return null\n return {\n detector: 'error-streak',\n severity,\n failureClass,\n reason: `stuck: ${streak} consecutive errored step(s)`,\n streak,\n ...(event.label ? { evidence: { lastError: event.label } } : {}),\n }\n },\n reset() {\n streak = 0\n },\n }\n}\n\n/** Fold one event through many detectors at once; returns every signal that fired this step. The\n * natural shape for an online pipe watching with a whole panel of detectors. */\nexport function observeAll(\n detectors: ReadonlyArray<StreamingDetector>,\n event: DetectorEvent,\n): DetectorSignal[] {\n const signals: DetectorSignal[] = []\n for (const d of detectors) {\n const s = d.observe(event)\n if (s) signals.push(s)\n }\n return signals\n}\n","/**\n * Policy-based agent control runtime.\n *\n * This is the minimal reusable loop behind driver-agent patterns:\n *\n * observe state -> validate -> decide next action -> act -> observe -> ...\n *\n * It deliberately does not model named \"topologies\". Direct execution,\n * critic/revise, driver intervention, specialist calls, and human escalation\n * are all just actions chosen by the control policy.\n */\n\nimport { noProgressDetector, repeatedActionDetector } from './detectors'\nimport { type SpanHandle, TraceEmitter } from './trace/emitter'\nimport type { FailureClass } from './trace/schema'\nimport type { TraceStore } from './trace/store'\n\nexport type ControlSeverity = 'info' | 'warning' | 'error' | 'critical'\nexport type ControlActionFailureMode = 'continue' | 'stop'\n\nexport interface ControlEvalResult {\n /** Stable validator or judge id. */\n id: string\n /** Whether this check passed. */\n passed: boolean\n /** Optional normalized score. 1 = best, 0 = worst. */\n score?: number\n /** Objective validators should usually be \"error\" or \"critical\" when failed. */\n severity?: ControlSeverity\n /** Human-readable result. */\n detail?: string\n /** Small evidence string or pointer. Avoid large payloads. */\n evidence?: string\n /** True when the result came from deterministic state, not LLM judgment. */\n objective?: boolean\n /** Structured details for downstream control policies and reports. */\n metadata?: Record<string, unknown>\n}\n\nexport interface ControlBudget {\n maxSteps: number\n maxWallMs?: number\n maxCostUsd?: number\n}\n\nexport interface ControlStopPolicies<TState, TAction> {\n /**\n * Stop after N consecutive steps with no state fingerprint change and\n * less than `minScoreDelta` score movement. Disabled when omitted.\n */\n maxNoProgressSteps?: number\n /**\n * Stop after the same action fingerprint is selected N consecutive\n * times. Disabled when omitted.\n */\n maxRepeatedActions?: number\n /** Minimum score movement that counts as progress. Default 0.001. */\n minScoreDelta?: number\n /** Override the default JSON/string fingerprint for state comparisons. */\n stateFingerprint?: (state: TState) => string\n /** Override the default JSON/string fingerprint for repeated-action checks. */\n actionFingerprint?: (action: TAction) => string\n}\n\nexport interface ControlContext<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n> {\n intent: string\n state: TState\n evals: TEval[]\n history: ControlStep<TState, TAction, TActionResult, TEval>[]\n budget: ControlBudget\n stepIndex: number\n wallMs: number\n spentCostUsd: number\n remainingCostUsd?: number\n abortSignal: AbortSignal\n emitter?: TraceEmitter\n}\n\nexport type ControlDecision<TAction> =\n | {\n type: 'continue'\n action: TAction\n reason?: string\n }\n | {\n type: 'stop'\n reason: string\n pass?: boolean\n score?: number\n /** Canonical task-failure class when this stop represents a failed task. */\n failureClass?: FailureClass\n }\n\nexport interface StopDecision {\n stop: boolean\n pass: boolean\n reason: string\n score?: number\n failureClass?: FailureClass\n}\n\nexport interface ControlActionOutcome<TActionResult> {\n ok: boolean\n result?: TActionResult\n error?: string\n costUsd?: number\n durationMs: number\n}\n\nexport interface ControlRuntimeError {\n phase: 'observe' | 'validate' | 'decide' | 'act' | 'stop-policy' | 'on-step' | 'trace'\n stepIndex: number\n message: string\n}\n\nexport interface ControlStep<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n> {\n index: number\n decision: ControlDecision<TAction>\n beforeState: TState\n afterState: TState\n evalsBefore: TEval[]\n evalsAfter: TEval[]\n actionOutcome?: ControlActionOutcome<TActionResult>\n startedAt: string\n endedAt: string\n}\n\nexport interface ControlRunResult<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n> {\n intent: string\n pass: boolean\n completed: boolean\n reason: string\n score?: number\n steps: ControlStep<TState, TAction, TActionResult, TEval>[]\n finalState: TState | undefined\n finalEvals: TEval[]\n wallMs: number\n spentCostUsd: number\n /** null when the run executed without a TraceEmitter wired (no run record was persisted). */\n runId: string | null\n failureClass?: FailureClass\n runtimeErrors: ControlRuntimeError[]\n stoppedBy: 'policy' | 'stop-policy' | 'budget' | 'abort' | 'runtime-error'\n}\n\nexport interface ControlRuntimeConfig<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n> {\n intent: string\n budget?: Partial<ControlBudget>\n signal?: AbortSignal\n /** Defaults to `continue`: action failures are recorded, then the policy gets another chance. */\n actionFailure?: ControlActionFailureMode\n /**\n * Extract cost from an action result. Used for `maxCostUsd` budget\n * enforcement and trace budget ledger emission.\n */\n getActionCostUsd?: (ctx: {\n action: TAction\n result: TActionResult\n state: TState\n evals: TEval[]\n history: ControlStep<TState, TAction, TActionResult, TEval>[]\n }) => number | undefined\n\n /** Read typed task/product state. Prefer structured state over transcript-only context. */\n observe: (ctx: {\n history: ControlStep<TState, TAction, TActionResult, TEval>[]\n abortSignal: AbortSignal\n }) => Promise<TState> | TState\n\n /** Objective validators first, subjective judges only where objective state is insufficient. */\n validate: (ctx: {\n intent: string\n state: TState\n history: ControlStep<TState, TAction, TActionResult, TEval>[]\n abortSignal: AbortSignal\n }) => Promise<TEval[]> | TEval[]\n\n /** Choose the next control action. Can call a worker, ask user, run critic, inspect state, or stop. */\n decide: (\n ctx: ControlContext<TState, TAction, TActionResult, TEval>,\n ) => Promise<ControlDecision<TAction>> | ControlDecision<TAction>\n\n /** Execute the action selected by the policy. */\n act: (\n action: TAction,\n ctx: ControlContext<TState, TAction, TActionResult, TEval>,\n ) => Promise<TActionResult> | TActionResult\n\n /** Final stopping policy. Called before decide and after each action. */\n shouldStop?: (\n ctx: ControlContext<TState, TAction, TActionResult, TEval>,\n ) => Promise<StopDecision> | StopDecision\n\n /** Optional hook for tracing or live progress updates. */\n onStep?: (step: ControlStep<TState, TAction, TActionResult, TEval>) => Promise<void> | void\n\n /** Optional generic stuck-loop policies. Custom `shouldStop` still runs first. */\n stopPolicies?: ControlStopPolicies<TState, TAction>\n\n /** Optional trace sink. Emits one run plus one span per control step. */\n store?: TraceStore\n scenarioId?: string\n projectId?: string\n variantId?: string\n}\n\nconst DEFAULT_BUDGET: ControlBudget = {\n maxSteps: 8,\n maxWallMs: 5 * 60 * 1000,\n}\n\nexport async function runAgentControlLoop<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n>(\n config: ControlRuntimeConfig<TState, TAction, TActionResult, TEval>,\n): Promise<ControlRunResult<TState, TAction, TActionResult, TEval>> {\n const budget = normalizeBudget(config.budget)\n const actionFailure = config.actionFailure ?? 'continue'\n const controller = new AbortController()\n const upstreamAbort = () => controller.abort(config.signal?.reason)\n if (config.signal) {\n if (config.signal.aborted) controller.abort(config.signal.reason)\n else config.signal.addEventListener('abort', upstreamAbort, { once: true })\n }\n\n const started = Date.now()\n const wallTimer = budget.maxWallMs\n ? setTimeout(\n () => controller.abort(new Error('control runtime wall timeout')),\n budget.maxWallMs,\n )\n : undefined\n const history: ControlStep<TState, TAction, TActionResult, TEval>[] = []\n const emitter = config.store ? new TraceEmitter(config.store) : undefined\n let spentCostUsd = 0\n const runtimeErrors: ControlRuntimeError[] = []\n // The stuck-detection kernels (shared with the online detectors). Thresholds 0 = disabled; the\n // streak is still tracked for telemetry. Both stops report `tool_recovery_failure`.\n const repeatedDetector = repeatedActionDetector({\n maxRepeated: config.stopPolicies?.maxRepeatedActions ?? 0,\n })\n const progressDetector = noProgressDetector({\n maxNoProgress: config.stopPolicies?.maxNoProgressSteps ?? 0,\n minScoreDelta: config.stopPolicies?.minScoreDelta ?? 0.001,\n })\n\n try {\n if (emitter) {\n await runTrace(runtimeErrors, 0, () =>\n emitter.startRun({\n scenarioId: config.scenarioId ?? 'agent-control-loop',\n projectId: config.projectId,\n variantId: config.variantId,\n layer: 'meta',\n tags: {\n intent: config.intent.slice(0, 120),\n maxSteps: String(budget.maxSteps),\n ...(budget.maxCostUsd !== undefined ? { maxCostUsd: String(budget.maxCostUsd) } : {}),\n },\n }),\n )\n }\n\n let state: TState\n let evals: TEval[]\n try {\n state = await config.observe({ history, abortSignal: controller.signal })\n } catch (err) {\n const error = runtimeError('observe', 0, err)\n runtimeErrors.push(error)\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: error.message,\n steps: history,\n finalState: undefined,\n finalEvals: [],\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n try {\n evals = await config.validate({\n intent: config.intent,\n state,\n history,\n abortSignal: controller.signal,\n })\n await recordEvalSpans(emitter, evals, 'initial', runtimeErrors, 0)\n } catch (err) {\n const error = runtimeError('validate', 0, err)\n runtimeErrors.push(error)\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: error.message,\n steps: history,\n finalState: state,\n finalEvals: [],\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n // Prime the no-progress detector with the initial state + score so step 0 can already detect a\n // no-op (mirrors the pre-loop fingerprint baseline). The priming observe never signals (streak 0).\n progressDetector.observe({\n stateFingerprint: fingerprintState(state, config.stopPolicies),\n score: averageScore(evals),\n })\n\n for (let stepIndex = 0; stepIndex < budget.maxSteps; stepIndex++) {\n if (controller.signal.aborted) {\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: abortReason(controller.signal),\n score: undefined,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'timeout',\n runtimeErrors,\n stoppedBy: 'abort',\n })\n }\n\n const budgetStop = budgetStopDecision(budget, spentCostUsd)\n if (budgetStop.stop) {\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: budgetStop.reason,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'budget_exceeded',\n runtimeErrors,\n stoppedBy: 'budget',\n })\n }\n\n const ctx = makeContext(\n config.intent,\n state,\n evals,\n history,\n budget,\n stepIndex,\n started,\n spentCostUsd,\n controller.signal,\n emitter,\n )\n let stop: StopDecision\n try {\n stop = config.shouldStop ? await config.shouldStop(ctx) : defaultStopDecision(evals)\n } catch (err) {\n runtimeErrors.push(runtimeError('stop-policy', stepIndex, err))\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n if (stop.stop) {\n return finish(emitter, {\n intent: config.intent,\n pass: stop.pass,\n completed: true,\n reason: stop.reason,\n score: stop.score,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: stop.failureClass,\n runtimeErrors,\n stoppedBy: 'stop-policy',\n })\n }\n\n let decision: ControlDecision<TAction>\n try {\n decision = await config.decide(ctx)\n } catch (err) {\n runtimeErrors.push(runtimeError('decide', stepIndex, err))\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n if (decision.type === 'stop') {\n const pass = decision.pass ?? false\n return finish(emitter, {\n intent: config.intent,\n pass,\n completed: true,\n reason: decision.reason,\n score: decision.score,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: pass ? undefined : (decision.failureClass ?? 'unknown'),\n runtimeErrors,\n stoppedBy: 'policy',\n })\n }\n\n const actionFingerprint = fingerprintAction(decision.action, config.stopPolicies)\n const repeatedActionSignal = repeatedDetector.observe({ actionFingerprint })\n const repeatedActionStreak = repeatedDetector.streak\n if (repeatedActionSignal) {\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: true,\n reason: repeatedActionSignal.reason,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'tool_recovery_failure',\n runtimeErrors,\n stoppedBy: 'stop-policy',\n })\n }\n\n const beforeState = state\n const evalsBefore = evals\n const scoreBefore = averageScore(evals)\n const actionStarted = Date.now()\n const stepHandle = emitter\n ? await runTrace(runtimeErrors, stepIndex, () =>\n emitter.tool({\n name: `control-step-${stepIndex}`,\n toolName: 'agent-control-action',\n args: decision.action,\n attributes: {\n decision: decision.reason ?? 'continue',\n repeatedActionStreak,\n },\n }),\n )\n : undefined\n let actionOutcome: ControlActionOutcome<TActionResult>\n try {\n const result = await config.act(decision.action, ctx)\n const rawCostUsd = config.getActionCostUsd?.({\n action: decision.action,\n result,\n state,\n evals,\n history,\n })\n const costUsd = normalizeActionCostUsd(rawCostUsd, runtimeErrors, stepIndex)\n if (costUsd !== undefined && Number.isFinite(costUsd) && costUsd > 0) {\n spentCostUsd += costUsd\n await recordCostBudget(\n emitter,\n budget,\n spentCostUsd,\n stepHandle,\n runtimeErrors,\n stepIndex,\n )\n }\n actionOutcome = {\n ok: true,\n result,\n ...(costUsd !== undefined ? { costUsd } : {}),\n durationMs: Date.now() - actionStarted,\n }\n } catch (err) {\n runtimeErrors.push(runtimeError('act', stepIndex, err))\n actionOutcome = {\n ok: false,\n error: runtimeErrors[runtimeErrors.length - 1]!.message,\n durationMs: Date.now() - actionStarted,\n }\n if (actionFailure === 'stop') {\n await runTrace(runtimeErrors, stepIndex, () =>\n stepHandle?.fail(actionOutcome.error ?? 'action failed'),\n )\n const step: ControlStep<TState, TAction, TActionResult, TEval> = {\n index: stepIndex,\n decision,\n beforeState,\n afterState: state,\n evalsBefore,\n evalsAfter: evals,\n actionOutcome,\n startedAt: new Date(actionStarted).toISOString(),\n endedAt: new Date().toISOString(),\n }\n history.push(step)\n await runOnStep(config.onStep, step, runtimeErrors)\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: actionOutcome.error ?? 'action failed',\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n }\n\n try {\n state = await config.observe({ history, abortSignal: controller.signal })\n } catch (err) {\n runtimeErrors.push(runtimeError('observe', stepIndex, err))\n const step: ControlStep<TState, TAction, TActionResult, TEval> = {\n index: stepIndex,\n decision,\n beforeState,\n afterState: beforeState,\n evalsBefore,\n evalsAfter: evals,\n actionOutcome,\n startedAt: new Date(actionStarted).toISOString(),\n endedAt: new Date().toISOString(),\n }\n history.push(step)\n await runTrace(runtimeErrors, stepIndex, () =>\n stepHandle?.fail(runtimeErrors[runtimeErrors.length - 1]!.message),\n )\n await runOnStep(config.onStep, step, runtimeErrors)\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n score: averageScore(evals),\n steps: history,\n finalState: beforeState,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n try {\n evals = await config.validate({\n intent: config.intent,\n state,\n history,\n abortSignal: controller.signal,\n })\n await recordEvalSpans(\n emitter,\n evals,\n `step-${stepIndex}`,\n runtimeErrors,\n stepIndex,\n stepHandle?.span.spanId,\n )\n } catch (err) {\n runtimeErrors.push(runtimeError('validate', stepIndex, err))\n const step: ControlStep<TState, TAction, TActionResult, TEval> = {\n index: stepIndex,\n decision,\n beforeState,\n afterState: state,\n evalsBefore,\n evalsAfter: evals,\n actionOutcome,\n startedAt: new Date(actionStarted).toISOString(),\n endedAt: new Date().toISOString(),\n }\n history.push(step)\n await runTrace(runtimeErrors, stepIndex, () =>\n stepHandle?.fail(runtimeErrors[runtimeErrors.length - 1]!.message),\n )\n await runOnStep(config.onStep, step, runtimeErrors)\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n const scoreAfter = averageScore(evals)\n const stateFingerprint = fingerprintState(state, config.stopPolicies)\n const noProgressSignal = progressDetector.observe({ stateFingerprint, score: scoreAfter })\n const noProgressStreak = progressDetector.streak\n\n const step: ControlStep<TState, TAction, TActionResult, TEval> = {\n index: stepIndex,\n decision,\n beforeState,\n afterState: state,\n evalsBefore,\n evalsAfter: evals,\n actionOutcome,\n startedAt: new Date(actionStarted).toISOString(),\n endedAt: new Date().toISOString(),\n }\n history.push(step)\n if (actionOutcome.ok) {\n await runTrace(runtimeErrors, stepIndex, () =>\n stepHandle?.end({\n attributes: {\n actionCostUsd: actionOutcome.costUsd ?? null,\n spentCostUsd,\n scoreBefore: scoreBefore ?? null,\n scoreAfter: scoreAfter ?? null,\n noProgressStreak,\n },\n }),\n )\n } else {\n await runTrace(runtimeErrors, stepIndex, () =>\n stepHandle?.fail(actionOutcome.error ?? 'action failed', {\n attributes: {\n spentCostUsd,\n noProgressStreak,\n },\n }),\n )\n }\n await runOnStep(config.onStep, step, runtimeErrors)\n\n if (noProgressSignal) {\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: true,\n reason: noProgressSignal.reason,\n score: scoreAfter,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'tool_recovery_failure',\n runtimeErrors,\n stoppedBy: 'stop-policy',\n })\n }\n\n const postStepBudgetStop = budgetStopDecision(budget, spentCostUsd)\n if (postStepBudgetStop.stop) {\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: postStepBudgetStop.reason,\n score: scoreAfter,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'budget_exceeded',\n runtimeErrors,\n stoppedBy: 'budget',\n })\n }\n\n const postStepCtx = makeContext(\n config.intent,\n state,\n evals,\n history,\n budget,\n stepIndex + 1,\n started,\n spentCostUsd,\n controller.signal,\n emitter,\n )\n let postStepStop: StopDecision\n try {\n postStepStop = config.shouldStop\n ? await config.shouldStop(postStepCtx)\n : defaultStopDecision(evals)\n } catch (err) {\n runtimeErrors.push(runtimeError('stop-policy', stepIndex + 1, err))\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n score: averageScore(evals),\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n }\n if (postStepStop.stop) {\n return finish(emitter, {\n intent: config.intent,\n pass: postStepStop.pass,\n completed: true,\n reason: postStepStop.reason,\n score: postStepStop.score,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: postStepStop.failureClass,\n runtimeErrors,\n stoppedBy: 'stop-policy',\n })\n }\n }\n\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: `budget exhausted: maxSteps=${budget.maxSteps}`,\n steps: history,\n finalState: state,\n finalEvals: evals,\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'budget_exceeded',\n runtimeErrors,\n stoppedBy: 'budget',\n })\n } catch (err) {\n runtimeErrors.push(runtimeError('act', history.length, err))\n return finish(emitter, {\n intent: config.intent,\n pass: false,\n completed: false,\n reason: runtimeErrors[runtimeErrors.length - 1]!.message,\n steps: history,\n finalState: undefined,\n finalEvals: [],\n wallMs: Date.now() - started,\n spentCostUsd,\n runId: emitter?.runId ?? null,\n failureClass: 'unknown',\n runtimeErrors,\n stoppedBy: 'runtime-error',\n })\n } finally {\n if (wallTimer) clearTimeout(wallTimer)\n if (config.signal) config.signal.removeEventListener('abort', upstreamAbort)\n }\n}\n\nexport function stopOnNoProgress<TState, TAction>(\n maxNoProgressSteps: number,\n options: Omit<ControlStopPolicies<TState, TAction>, 'maxNoProgressSteps'> = {},\n): ControlStopPolicies<TState, TAction> {\n return { ...options, maxNoProgressSteps }\n}\n\nexport function stopOnRepeatedAction<TState, TAction>(\n maxRepeatedActions: number,\n options: Omit<ControlStopPolicies<TState, TAction>, 'maxRepeatedActions'> = {},\n): ControlStopPolicies<TState, TAction> {\n return { ...options, maxRepeatedActions }\n}\n\nexport function objectiveEval(input: Omit<ControlEvalResult, 'objective'>): ControlEvalResult {\n return { ...input, objective: true }\n}\n\nexport function subjectiveEval(input: Omit<ControlEvalResult, 'objective'>): ControlEvalResult {\n return { ...input, objective: false }\n}\n\nfunction normalizeBudget(input: Partial<ControlBudget> | undefined): ControlBudget {\n const raw = { ...DEFAULT_BUDGET, ...input } as Record<string, unknown>\n if (!Number.isInteger(raw.maxSteps) || (raw.maxSteps as number) < 1) {\n throw new RangeError(\n `ControlRuntime budget.maxSteps must be an integer >= 1, got ${String(raw.maxSteps)}`,\n )\n }\n const budget: ControlBudget = { maxSteps: raw.maxSteps as number }\n if (raw.maxWallMs !== undefined) {\n if (\n typeof raw.maxWallMs !== 'number' ||\n !Number.isFinite(raw.maxWallMs) ||\n raw.maxWallMs <= 0\n ) {\n throw new RangeError(\n `ControlRuntime budget.maxWallMs must be a positive finite number, got ${String(raw.maxWallMs)}`,\n )\n }\n budget.maxWallMs = raw.maxWallMs\n }\n if (raw.maxCostUsd !== undefined) {\n if (\n typeof raw.maxCostUsd !== 'number' ||\n !Number.isFinite(raw.maxCostUsd) ||\n raw.maxCostUsd < 0\n ) {\n throw new RangeError(\n `ControlRuntime budget.maxCostUsd must be a nonnegative finite number, got ${String(raw.maxCostUsd)}`,\n )\n }\n budget.maxCostUsd = raw.maxCostUsd\n }\n return budget\n}\n\nfunction normalizeActionCostUsd(\n costUsd: number | undefined,\n runtimeErrors: ControlRuntimeError[],\n stepIndex: number,\n): number | undefined {\n if (costUsd === undefined) return undefined\n if (!Number.isFinite(costUsd) || costUsd < 0) {\n runtimeErrors.push(\n runtimeError('act', stepIndex, new Error(`invalid action costUsd: ${String(costUsd)}`)),\n )\n return undefined\n }\n return costUsd\n}\n\nexport function allCriticalPassed(evals: ControlEvalResult[]): boolean {\n return evals.every(\n (result) => result.passed || (result.severity !== 'critical' && result.severity !== 'error'),\n )\n}\n\nfunction makeContext<TState, TAction, TActionResult, TEval extends ControlEvalResult>(\n intent: string,\n state: TState,\n evals: TEval[],\n history: ControlStep<TState, TAction, TActionResult, TEval>[],\n budget: ControlBudget,\n stepIndex: number,\n started: number,\n spentCostUsd: number,\n abortSignal: AbortSignal,\n emitter?: TraceEmitter,\n): ControlContext<TState, TAction, TActionResult, TEval> {\n return {\n intent,\n state,\n evals,\n history,\n budget,\n stepIndex,\n wallMs: Date.now() - started,\n spentCostUsd,\n remainingCostUsd:\n budget.maxCostUsd === undefined ? undefined : Math.max(0, budget.maxCostUsd - spentCostUsd),\n abortSignal,\n emitter,\n }\n}\n\nfunction defaultStopDecision(evals: ControlEvalResult[]): StopDecision {\n if (!evals.length) return { stop: false, pass: false, reason: 'no evals yet' }\n const pass = allCriticalPassed(evals)\n return pass\n ? { stop: true, pass: true, reason: 'all critical evals passed', score: averageScore(evals) }\n : {\n stop: false,\n pass: false,\n reason: 'critical evals still failing',\n score: averageScore(evals),\n }\n}\n\nfunction averageScore(evals: ControlEvalResult[]): number | undefined {\n const scored = evals\n .map((result) => result.score)\n .filter((score): score is number => typeof score === 'number')\n if (!scored.length) return undefined\n return Math.round((scored.reduce((sum, score) => sum + score, 0) / scored.length) * 1000) / 1000\n}\n\nfunction budgetStopDecision(\n budget: ControlBudget,\n spentCostUsd: number,\n): { stop: boolean; reason: string } {\n if (budget.maxCostUsd !== undefined && spentCostUsd >= budget.maxCostUsd) {\n return {\n stop: true,\n reason: `budget exhausted: maxCostUsd=${budget.maxCostUsd}`,\n }\n }\n return { stop: false, reason: '' }\n}\n\nasync function recordCostBudget(\n emitter: TraceEmitter | undefined,\n budget: ControlBudget,\n spentCostUsd: number,\n handle: SpanHandle | undefined,\n runtimeErrors: ControlRuntimeError[],\n stepIndex: number,\n): Promise<void> {\n if (!emitter || budget.maxCostUsd === undefined) return\n const maxCostUsd = budget.maxCostUsd\n await runTrace(runtimeErrors, stepIndex, () =>\n emitter.recordBudget({\n dimension: 'usd',\n limit: maxCostUsd,\n consumed: spentCostUsd,\n remaining: Math.max(0, maxCostUsd - spentCostUsd),\n breached: spentCostUsd >= maxCostUsd,\n spanId: handle?.span.spanId,\n }),\n )\n}\n\nasync function recordEvalSpans(\n emitter: TraceEmitter | undefined,\n evals: ControlEvalResult[],\n phase: string,\n runtimeErrors: ControlRuntimeError[],\n stepIndex: number,\n targetSpanId?: string,\n): Promise<void> {\n if (!emitter) return\n for (const result of evals) {\n await runTrace(runtimeErrors, stepIndex, () =>\n emitter.recordJudge({\n judgeId: result.objective ? 'objective-validator' : 'subjective-judge',\n targetSpanId: targetSpanId ?? emitter.runId,\n name: `control-eval/${result.id}`,\n dimension: result.id,\n score: typeof result.score === 'number' ? result.score : result.passed ? 1 : 0,\n rationale: result.detail,\n evidence: result.evidence,\n attributes: {\n phase,\n passed: result.passed,\n severity: result.severity,\n objective: result.objective,\n },\n }),\n )\n }\n}\n\nasync function runOnStep<TState, TAction, TActionResult, TEval extends ControlEvalResult>(\n onStep: ControlRuntimeConfig<TState, TAction, TActionResult, TEval>['onStep'] | undefined,\n step: ControlStep<TState, TAction, TActionResult, TEval>,\n runtimeErrors: ControlRuntimeError[],\n): Promise<void> {\n if (!onStep) return\n try {\n await onStep(step)\n } catch (err) {\n runtimeErrors.push(runtimeError('on-step', step.index, err))\n }\n}\n\nasync function runTrace<T>(\n runtimeErrors: ControlRuntimeError[],\n stepIndex: number,\n write: () => Promise<T | undefined> | T | undefined,\n): Promise<T | undefined> {\n try {\n return await write()\n } catch (err) {\n runtimeErrors.push(runtimeError('trace', stepIndex, err))\n return undefined\n }\n}\n\nfunction fingerprintState<TState, TAction>(\n state: TState,\n policies?: ControlStopPolicies<TState, TAction>,\n): string {\n if (policies?.stateFingerprint) return policies.stateFingerprint(state)\n return stableFingerprint(state)\n}\n\nfunction fingerprintAction<TState, TAction>(\n action: TAction,\n policies?: ControlStopPolicies<TState, TAction>,\n): string {\n if (policies?.actionFingerprint) return policies.actionFingerprint(action)\n return stableFingerprint(action)\n}\n\nfunction stableFingerprint(value: unknown): string {\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'boolean' || value == null) return String(value)\n try {\n return JSON.stringify(sortForFingerprint(value))\n } catch {\n return String(value)\n }\n}\n\nfunction sortForFingerprint(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortForFingerprint)\n if (!value || typeof value !== 'object') return value\n const record = value as Record<string, unknown>\n const sorted: Record<string, unknown> = {}\n for (const key of Object.keys(record).sort()) {\n sorted[key] = sortForFingerprint(record[key])\n }\n return sorted\n}\n\nfunction abortReason(signal: AbortSignal): string {\n const reason = signal.reason\n if (reason instanceof Error) return reason.message\n return reason ? String(reason) : 'aborted'\n}\n\nfunction runtimeError(\n phase: ControlRuntimeError['phase'],\n stepIndex: number,\n err: unknown,\n): ControlRuntimeError {\n const message = err instanceof Error ? err.message : String(err)\n return { phase, stepIndex, message }\n}\n\nasync function finish<TState, TAction, TActionResult, TEval extends ControlEvalResult>(\n emitter: TraceEmitter | undefined,\n result: ControlRunResult<TState, TAction, TActionResult, TEval>,\n): Promise<ControlRunResult<TState, TAction, TActionResult, TEval>> {\n await runTrace(result.runtimeErrors, result.steps.length, () =>\n emitter?.endRun({\n pass: result.pass,\n score: result.score ?? averageScore(result.finalEvals),\n failureClass: result.failureClass,\n notes: result.reason,\n }),\n )\n return result\n}\n","import type { ControlEvalResult, ControlRunResult } from './control-runtime'\nimport {\n type RunRecord,\n type RunSplitTag,\n type RunTaskFailure,\n type RunTokenUsage,\n validateRunRecord,\n} from './run-record'\n\nexport interface RunEvidenceMetadata {\n experimentId: string\n scenarioId: string\n candidateId: string\n seed: number\n model: string\n promptHash: string\n configHash: string\n commitSha: string\n splitTag: RunSplitTag\n tokenUsage: RunTokenUsage\n costProvenance: RunRecord['costProvenance']\n queueMs?: number\n judgeMetadata?: RunRecord['judgeMetadata']\n raw?: Record<string, number>\n}\n\nexport type ControlRunToRunRecordOptions = RunEvidenceMetadata &\n RunTaskFailure & {\n runId?: string\n score?: number\n }\n\n/**\n * Project a completed control-loop run into the strict RunRecord shape used by\n * release gates, optimizer tables, and research reports.\n *\n * The control loop owns live execution evidence. The caller still supplies the\n * experiment-cell metadata because prompt/config hashes, split assignment,\n * model snapshot, and commit SHA are product/harness concerns.\n */\nexport function controlRunToRunRecord<\n TState,\n TAction,\n TActionResult,\n TEval extends ControlEvalResult = ControlEvalResult,\n>(\n run: ControlRunResult<TState, TAction, TActionResult, TEval>,\n options: ControlRunToRunRecordOptions,\n): RunRecord {\n const score =\n finiteScore(options.score) ?? finiteScore(run.score) ?? scoreFromEvals(run.finalEvals)\n const outcome =\n options.splitTag === 'holdout'\n ? {\n ...(score !== undefined ? { holdoutScore: score } : {}),\n raw: normalizeRawMetrics(options.raw, run, score),\n }\n : {\n ...(score !== undefined ? { searchScore: score } : {}),\n raw: normalizeRawMetrics(options.raw, run, score),\n }\n const terminalOutcome =\n run.stoppedBy === 'abort'\n ? 'cancelled'\n : run.stoppedBy === 'runtime-error'\n ? 'failed'\n : run.completed\n ? 'succeeded'\n : 'incomplete'\n const costUsd = options.costProvenance.kind === 'uncaptured' ? null : options.costProvenance.usd\n if (costUsd !== null && costUsd !== run.spentCostUsd) {\n throw new Error(\n `cost provenance amount ${costUsd} does not match control run spend ${run.spentCostUsd}`,\n )\n }\n\n return validateRunRecord({\n runId:\n options.runId ??\n run.runId ??\n `control:${options.experimentId}:${options.candidateId}:${options.seed}:${options.splitTag}`,\n experimentId: options.experimentId,\n candidateId: options.candidateId,\n seed: options.seed,\n model: options.model,\n promptHash: options.promptHash,\n configHash: options.configHash,\n commitSha: options.commitSha,\n wallMs: run.wallMs,\n ...(options.queueMs !== undefined ? { queueMs: options.queueMs } : {}),\n costUsd,\n costProvenance: options.costProvenance,\n tokenUsage: options.tokenUsage,\n terminalOutcome,\n ...(terminalOutcome !== 'succeeded' ? { terminalFailureReason: run.reason } : {}),\n ...(options.judgeMetadata ? { judgeMetadata: options.judgeMetadata } : {}),\n outcome,\n ...(options.failureClass !== undefined ? { failureClass: options.failureClass } : {}),\n ...(options.failureMode !== undefined ? { failureMode: options.failureMode } : {}),\n splitTag: options.splitTag,\n scenarioId: options.scenarioId,\n })\n}\n\nexport function scoreFromEvals(evals: readonly ControlEvalResult[]): number | undefined {\n const scores = evals\n .map((e) => e.score)\n .filter((score): score is number => typeof score === 'number' && Number.isFinite(score))\n if (scores.length === 0) return undefined\n return clampScore(scores.reduce((sum, score) => sum + score, 0) / scores.length)\n}\n\nfunction normalizeRawMetrics<TState, TAction, TActionResult, TEval extends ControlEvalResult>(\n raw: Record<string, number> | undefined,\n run: ControlRunResult<TState, TAction, TActionResult, TEval>,\n score: number | undefined,\n): Record<string, number> {\n const normalizedRaw = finiteOnly(raw ?? {})\n delete normalizedRaw.score\n return {\n ...normalizedRaw,\n ...(score !== undefined ? { score } : {}),\n pass: run.pass ? 1 : 0,\n completed: run.completed ? 1 : 0,\n steps: run.steps.length,\n runtimeErrors: run.runtimeErrors.length,\n execution_error_count: executionErrorCount(run),\n }\n}\n\nfunction executionErrorCount<TState, TAction, TActionResult, TEval extends ControlEvalResult>(\n run: ControlRunResult<TState, TAction, TActionResult, TEval>,\n): number {\n const thrownActionSteps = new Set(\n run.runtimeErrors.filter((error) => error.phase === 'act').map((error) => error.stepIndex),\n )\n const failedActionsWithoutRuntimeError = run.steps.filter(\n (step) => step.actionOutcome?.ok === false && !thrownActionSteps.has(step.index),\n ).length\n return run.runtimeErrors.length + failedActionsWithoutRuntimeError\n}\n\nfunction finiteOnly(values: Record<string, number>): Record<string, number> {\n const out: Record<string, number> = {}\n for (const [key, value] of Object.entries(values)) {\n if (Number.isFinite(value)) out[key] = value\n }\n return out\n}\n\nfunction finiteScore(value: number | undefined): number | undefined {\n return value !== undefined && Number.isFinite(value) ? clampScore(value) : undefined\n}\n\nfunction clampScore(value: number): number {\n return Math.max(0, Math.min(1, value))\n}\n","/**\n * Propose / Verify / Review — the core multi-shot primitive.\n *\n * shot N: propose(state, priorReview) → new state\n * verify(state) → pass/fail, optional layers\n * review(state, verification, memory) → observations + next-shot\n * instruction + shouldContinue\n * memory.append(entry)\n *\n * Roles are strictly separated:\n *\n * - The WORKER is whatever the caller wraps in `propose`. It is\n * stateful — caller owns its resume/session mechanism.\n * - The VERIFIER grades the state. It produces the ground truth.\n * The reviewer cannot overturn or downgrade a verification layer.\n * - The REVIEWER is stateless per call. Its continuity is the\n * `ReviewMemoryStore` — durable JSONL by default, or any store\n * implementing the interface. It reads memory + trace summary +\n * verification and directs the NEXT proposer shot.\n *\n * This shape is load-bearing. The reviewer never grades; the verifier\n * never directs. Two processes, two prompts, two concerns — which is\n * what keeps the loop from confirmation-biasing itself into \"all\n * passed\" when it didn't.\n *\n * Short-circuits and soft-fails are both first-class:\n * - verify.pass === true → reviewer LLM call is skipped, memory\n * records a success entry, loop exits.\n * - review throws → the shot still counts; the loop uses the\n * last-known instruction (or `fallbackInstruction`) for the next\n * propose call. A transient reviewer failure must NEVER abort a\n * valid arc.\n *\n * Composable: `propose` itself can be another `runProposeReview` call.\n * That's the dogfooding path — a harness built on this primitive is in\n * turn evaluable by it.\n */\n\nimport { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { type SpanHandle, TraceEmitter } from './trace/emitter'\nimport type { FailureClass } from './trace/schema'\nimport type { TraceStore } from './trace/store'\n\n// ── Types ────────────────────────────────────────────────────────────\n\nexport interface Verification {\n pass: boolean\n score?: number\n failingLayers?: string[]\n details?: unknown\n}\n\nexport interface Review {\n observations: string\n diagnosis: string\n nextShotInstruction: string\n shouldContinue: boolean\n confidence: number\n}\n\nexport interface ReviewMemoryEntry extends Review {\n shot: number\n timestamp: number\n verification: {\n pass: boolean\n score?: number\n failingLayers?: string[]\n }\n}\n\nexport interface ProposeInput<State> {\n shot: number\n goal: string\n state: State\n priorReview: Review | null\n abortSignal: AbortSignal\n emitter?: TraceEmitter\n}\n\nexport interface ProposeOutput<State, Summary = unknown> {\n state: State\n traceSummary?: Summary\n}\n\nexport interface ReviewInput<State, Summary = unknown> {\n shot: number\n goal: string\n state: State\n verification: Verification\n traceSummary: Summary | undefined\n memory: ReviewMemoryEntry[]\n}\n\nexport type ProposeFn<State, Summary = unknown> = (\n input: ProposeInput<State>,\n) => Promise<ProposeOutput<State, Summary>>\n\nexport type VerifyFn<State> = (state: State) => Promise<Verification>\n\nexport type ReviewFn<State, Summary = unknown> = (\n input: ReviewInput<State, Summary>,\n) => Promise<Review>\n\nexport interface ReviewMemoryStore {\n load(): Promise<ReviewMemoryEntry[]>\n append(entry: ReviewMemoryEntry): Promise<void>\n}\n\nexport interface ProposeReviewConfig<State, Summary = unknown> {\n goal: string\n initialState: State\n propose: ProposeFn<State, Summary>\n verify: VerifyFn<State>\n review: ReviewFn<State, Summary>\n /** Hard shot cap. Default 10. */\n maxShots?: number\n /** Wall-clock cap in ms. Default 10 min. */\n maxWallMs?: number\n /**\n * If the reviewer returns confidence ≤ floor on `confidenceFloorWindow`\n * consecutive shots, terminate early. Default floor 0.3, window 2.\n * Set window to 0 or floor to <0 to disable.\n */\n confidenceFloor?: number\n confidenceFloorWindow?: number\n /** Defaults to an in-memory store if omitted. */\n memory?: ReviewMemoryStore\n /** If provided, emit a Run + per-shot spans. */\n store?: TraceStore\n scenarioId?: string\n projectId?: string\n variantId?: string\n /**\n * Used when the reviewer soft-fails on shot 1 (no prior instruction to\n * fall back to). Default is a generic \"inspect failures and fix\".\n */\n fallbackInstruction?: string\n}\n\nexport interface ProposeReviewShot<State, Summary = unknown> {\n shot: number\n state: State\n verification: Verification\n traceSummary: Summary | undefined\n review: Review\n reviewAvailable: boolean\n reviewError?: string\n durationMs: number\n}\n\nexport interface ProposeReviewReport<State, Summary = unknown> {\n runId: string | null\n completed: boolean\n shots: ProposeReviewShot<State, Summary>[]\n finalState: State\n finalVerification: Verification\n failureClass?: FailureClass\n wallMs: number\n score: number\n}\n\n// ── Memory stores ────────────────────────────────────────────────────\n\nexport function inMemoryReviewStore(initial: ReviewMemoryEntry[] = []): ReviewMemoryStore {\n const entries: ReviewMemoryEntry[] = [...initial]\n return {\n async load() {\n return [...entries]\n },\n async append(entry) {\n entries.push(entry)\n },\n }\n}\n\nexport function jsonlReviewStore(path: string): ReviewMemoryStore {\n return {\n async load() {\n if (!existsSync(path)) return []\n const raw = readFileSync(path, 'utf8')\n const out: ReviewMemoryEntry[] = []\n for (const line of raw.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed) continue\n try {\n out.push(JSON.parse(trimmed) as ReviewMemoryEntry)\n } catch {\n // A corrupt line is an observability problem, not a correctness\n // one — skip it rather than aborting the loop.\n }\n }\n return out\n },\n async append(entry) {\n mkdirSync(dirname(path), { recursive: true })\n appendFileSync(path, `${JSON.stringify(entry)}\\n`)\n },\n }\n}\n\n// ── Core loop ────────────────────────────────────────────────────────\n\nconst DEFAULT_FALLBACK_INSTRUCTION =\n 'Inspect the verification failures above. Fix the critical issues first, then the major ones. Do not restate the failures — act on them.'\n\nexport async function runProposeReview<State, Summary = unknown>(\n config: ProposeReviewConfig<State, Summary>,\n): Promise<ProposeReviewReport<State, Summary>> {\n const maxShots = config.maxShots ?? 10\n const maxWallMs = config.maxWallMs ?? 10 * 60 * 1000\n const confidenceFloor = config.confidenceFloor ?? 0.3\n const confidenceFloorWindow = config.confidenceFloorWindow ?? 2\n const memory = config.memory ?? inMemoryReviewStore()\n const fallbackInstruction = config.fallbackInstruction ?? DEFAULT_FALLBACK_INSTRUCTION\n\n const emitter = config.store ? new TraceEmitter(config.store) : null\n if (emitter) {\n await emitter.startRun({\n scenarioId: config.scenarioId ?? 'propose-review',\n projectId: config.projectId,\n variantId: config.variantId,\n layer: 'meta',\n tags: {\n goal: config.goal.slice(0, 120),\n maxShots: String(maxShots),\n },\n })\n }\n\n const abort = new AbortController()\n const wallStart = Date.now()\n const wallTimer = setTimeout(\n () => abort.abort(new Error('propose-review wall timeout')),\n maxWallMs,\n )\n\n const shots: ProposeReviewShot<State, Summary>[] = []\n let state = config.initialState\n let priorReview: Review | null = null\n let lastVerification: Verification = { pass: false }\n let failureClass: FailureClass | undefined\n let completed = false\n let lowConfidenceStreak = 0\n\n try {\n for (let shot = 1; shot <= maxShots; shot++) {\n if (abort.signal.aborted) {\n failureClass = 'timeout'\n break\n }\n\n const shotStart = Date.now()\n const shotHandle = emitter ? await emitter.span({ kind: 'tool', name: `shot-${shot}` }) : null\n\n // 1. Propose.\n let proposeOut: ProposeOutput<State, Summary>\n try {\n proposeOut = await config.propose({\n shot,\n goal: config.goal,\n state,\n priorReview,\n abortSignal: abort.signal,\n emitter: emitter ?? undefined,\n })\n } catch (err) {\n await shotHandle?.fail(err instanceof Error ? err : String(err))\n failureClass = 'unknown'\n throw err\n }\n state = proposeOut.state\n const traceSummary = proposeOut.traceSummary\n\n // 2. Verify.\n let verification: Verification\n try {\n verification = await config.verify(state)\n } catch (err) {\n await shotHandle?.fail(err instanceof Error ? err : String(err))\n failureClass = 'unknown'\n throw err\n }\n lastVerification = verification\n\n // 3. Review — short-circuit on pass; soft-fail on throw.\n const memorySnapshot = await memory.load()\n const verificationDigest = {\n pass: verification.pass,\n score: verification.score,\n failingLayers: verification.failingLayers ?? [],\n }\n\n let review: Review\n let reviewAvailable = true\n let reviewError: string | undefined\n\n if (verification.pass) {\n review = {\n observations: 'verification passed — skipping reviewer LLM call',\n diagnosis: 'no failures to diagnose',\n nextShotInstruction: '(done)',\n shouldContinue: false,\n confidence: 1,\n }\n } else {\n try {\n review = await config.review({\n shot,\n goal: config.goal,\n state,\n verification,\n traceSummary,\n memory: memorySnapshot,\n })\n review = coerceReview(review)\n } catch (err) {\n reviewAvailable = false\n reviewError = err instanceof Error ? err.message : String(err)\n const lastInstruction =\n memorySnapshot.length > 0\n ? memorySnapshot[memorySnapshot.length - 1]!.nextShotInstruction\n : fallbackInstruction\n review = {\n observations: '(reviewer unavailable — using last-known instruction)',\n diagnosis: reviewError,\n nextShotInstruction: lastInstruction,\n shouldContinue: true,\n confidence: 0.3,\n }\n }\n }\n\n const entry: ReviewMemoryEntry = {\n shot,\n timestamp: Date.now(),\n ...review,\n verification: verificationDigest,\n }\n await memory.append(entry)\n\n const shotRecord: ProposeReviewShot<State, Summary> = {\n shot,\n state,\n verification,\n traceSummary,\n review,\n reviewAvailable,\n reviewError,\n durationMs: Date.now() - shotStart,\n }\n shots.push(shotRecord)\n\n await shotHandle?.end({\n attributes: {\n verificationPass: verification.pass,\n verificationScore: verification.score ?? null,\n reviewShouldContinue: review.shouldContinue,\n reviewConfidence: review.confidence,\n reviewAvailable,\n },\n } as Partial<SpanHandle['span']>)\n\n // 4. Exit rules.\n if (verification.pass) {\n completed = true\n break\n }\n if (!review.shouldContinue) {\n break\n }\n if (confidenceFloorWindow > 0 && review.confidence <= confidenceFloor) {\n lowConfidenceStreak += 1\n if (lowConfidenceStreak >= confidenceFloorWindow) break\n } else {\n lowConfidenceStreak = 0\n }\n\n priorReview = review\n }\n\n if (!completed && !failureClass) {\n failureClass = shots.length >= maxShots ? 'budget_exceeded' : 'unknown'\n }\n } finally {\n clearTimeout(wallTimer)\n }\n\n const score = lastVerification.pass\n ? 1\n : typeof lastVerification.score === 'number'\n ? lastVerification.score\n : 0\n\n if (emitter) {\n await emitter.endRun({\n pass: completed,\n score,\n failureClass,\n notes: `${shots.length} shot(s); final pass=${lastVerification.pass}`,\n })\n }\n\n return {\n runId: emitter?.runId ?? null,\n completed,\n shots,\n finalState: state,\n finalVerification: lastVerification,\n failureClass,\n wallMs: Date.now() - wallStart,\n score,\n }\n}\n\n// ── Reviewer helper (LLM-backed) ─────────────────────────────────────\n\nexport type LlmJsonCall = (req: { system: string; user: string }) => Promise<unknown>\n\nexport interface LlmReviewerConfig<State, Summary = unknown> {\n callJson: LlmJsonCall\n renderState?: (state: State) => string\n renderTraceSummary?: (summary: Summary | undefined) => string\n /** Appended to the default system prompt. */\n systemPromptAddendum?: string\n}\n\nconst REVIEWER_SYSTEM_PROMPT = `You are a senior reviewer directing a multi-shot build loop.\nYou do NOT grade — the verifier already did. Your job is to direct the worker's next shot.\nYou are blind to the worker's inner monologue. You see what it DID, not what it thought.\nReturn STRICT JSON matching the schema. No prose outside the JSON.`\n\nexport function createLlmReviewer<State, Summary = unknown>(\n cfg: LlmReviewerConfig<State, Summary>,\n): ReviewFn<State, Summary> {\n const renderState = cfg.renderState ?? ((s: State) => safeJson(s))\n const renderTraceSummary =\n cfg.renderTraceSummary ??\n ((s: Summary | undefined) => (s === undefined ? '(none)' : safeJson(s)))\n const system = cfg.systemPromptAddendum\n ? `${REVIEWER_SYSTEM_PROMPT}\\n\\n${cfg.systemPromptAddendum}`\n : REVIEWER_SYSTEM_PROMPT\n\n return async (input) => {\n const memoryBlock =\n input.memory.length === 0\n ? '(no prior shots — this is shot 1)'\n : input.memory\n .map((m) =>\n [\n `shot ${m.shot} — verification.pass=${m.verification.pass}` +\n (typeof m.verification.score === 'number'\n ? ` score=${m.verification.score.toFixed(2)}`\n : '') +\n ` confidence=${m.confidence.toFixed(2)} failing=[${(m.verification.failingLayers ?? []).join(',')}]`,\n ` observations: ${m.observations.slice(0, 400)}`,\n ` diagnosis: ${m.diagnosis.slice(0, 400)}`,\n ` instruction given: ${m.nextShotInstruction.slice(0, 400)}`,\n ].join('\\n'),\n )\n .join('\\n\\n')\n\n const user = [\n `=== GOAL ===`,\n input.goal,\n ``,\n `=== SHOT NUMBER ===`,\n String(input.shot),\n ``,\n `=== CURRENT STATE ===`,\n renderState(input.state),\n ``,\n `=== TRACE SUMMARY ===`,\n renderTraceSummary(input.traceSummary),\n ``,\n `=== VERIFICATION ===`,\n summarizeVerification(input.verification),\n ``,\n `=== REVIEWER MEMORY (prior shots) ===`,\n memoryBlock,\n ``,\n `=== YOUR TASK ===`,\n `Return STRICT JSON:`,\n `{`,\n ` \"observations\": string (20..2000 chars, first-person worker behavior — quote counts, errors, loops)`,\n ` \"diagnosis\": string (20..1500 chars, root cause, NOT a restatement of verification)`,\n ` \"nextShotInstruction\": string (40..3000 chars, concrete directive to the worker)`,\n ` \"shouldContinue\": boolean (false if verification.pass, or if thrashing, or unachievable)`,\n ` \"confidence\": number in [0,1]`,\n `}`,\n ].join('\\n')\n\n const raw = await cfg.callJson({ system, user })\n return coerceReview(raw as Partial<Review>)\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\nfunction coerceReview(raw: Partial<Review> | null | undefined): Review {\n if (!raw || typeof raw !== 'object') {\n throw new Error('reviewer returned non-object')\n }\n const observations = typeof raw.observations === 'string' ? raw.observations : ''\n const diagnosis = typeof raw.diagnosis === 'string' ? raw.diagnosis : ''\n const nextShotInstruction =\n typeof raw.nextShotInstruction === 'string' ? raw.nextShotInstruction : ''\n if (!observations || !diagnosis || !nextShotInstruction) {\n throw new Error('reviewer missing required string fields')\n }\n if (typeof raw.shouldContinue !== 'boolean') {\n throw new Error('reviewer missing shouldContinue boolean')\n }\n const confidenceRaw = Number(raw.confidence)\n if (!Number.isFinite(confidenceRaw)) {\n throw new Error('reviewer confidence not finite')\n }\n return {\n observations,\n diagnosis,\n nextShotInstruction,\n shouldContinue: raw.shouldContinue,\n confidence: Math.max(0, Math.min(1, confidenceRaw)),\n }\n}\n\nfunction summarizeVerification(v: Verification): string {\n const header =\n `pass=${v.pass}` +\n (typeof v.score === 'number' ? ` score=${v.score.toFixed(3)}` : '') +\n (v.failingLayers && v.failingLayers.length > 0\n ? ` failing=[${v.failingLayers.join(', ')}]`\n : '')\n const details = v.details === undefined ? '' : `\\n${safeJson(v.details).slice(0, 1500)}`\n return header + details\n}\n\nfunction safeJson(x: unknown): string {\n try {\n return JSON.stringify(x, null, 2)\n } catch {\n return String(x)\n }\n}\n","import {\n type ControlRunResult,\n type ControlRuntimeConfig,\n objectiveEval,\n runAgentControlLoop,\n} from './control-runtime'\nimport {\n inMemoryReviewStore,\n type ProposeFn,\n type ProposeOutput,\n type Review,\n type ReviewFn,\n type ReviewMemoryEntry,\n type ReviewMemoryStore,\n type Verification,\n type VerifyFn,\n} from './propose-review'\nimport type { FailureClass } from './trace/schema'\nimport type { TraceStore } from './trace/store'\n\nexport interface ProposeReviewControlState<State, Summary = unknown> {\n shot: number\n state: State\n priorReview: Review | null\n verification: Verification\n traceSummary?: Summary\n memory: ReviewMemoryEntry[]\n completed: boolean\n reviewAvailable: boolean\n reviewError?: string\n}\n\nexport interface ProposeReviewControlAction {\n type: 'propose-review-shot'\n shot: number\n}\n\nexport interface ProposeReviewControlResult<State, Summary = unknown> {\n state: State\n verification: Verification\n traceSummary?: Summary\n review: Review | null\n reviewAvailable: boolean\n reviewError?: string\n}\n\nexport interface ProposeReviewControlConfig<State, Summary = unknown> {\n goal: string\n initialState: State\n propose: ProposeFn<State, Summary>\n verify: VerifyFn<State>\n review: ReviewFn<State, Summary>\n maxShots?: number\n maxWallMs?: number\n memory?: ReviewMemoryStore\n store?: TraceStore\n scenarioId?: string\n projectId?: string\n variantId?: string\n fallbackInstruction?: string\n confidenceFloor?: number\n confidenceFloorWindow?: number\n failureClassFromVerification?: (verification: Verification) => FailureClass | undefined\n actionFailure?: ControlRuntimeConfig<\n ProposeReviewControlState<State, Summary>,\n ProposeReviewControlAction,\n ProposeReviewControlResult<State, Summary>\n >['actionFailure']\n}\n\nconst DEFAULT_FALLBACK_INSTRUCTION =\n 'Inspect the verification failures above. Fix the critical issues first, then the major ones. Do not restate the failures — act on them.'\n\nexport async function runProposeReviewAsControlLoop<State, Summary = unknown>(\n config: ProposeReviewControlConfig<State, Summary>,\n): Promise<\n ControlRunResult<\n ProposeReviewControlState<State, Summary>,\n ProposeReviewControlAction,\n ProposeReviewControlResult<State, Summary>\n >\n> {\n const maxShots = config.maxShots ?? 10\n const confidenceFloor = config.confidenceFloor ?? 0.3\n const confidenceFloorWindow = config.confidenceFloorWindow ?? 2\n const memory = config.memory ?? inMemoryReviewStore()\n const fallbackInstruction = config.fallbackInstruction ?? DEFAULT_FALLBACK_INSTRUCTION\n const failureClassFromVerification =\n config.failureClassFromVerification ?? controlFailureClassFromVerification\n let lowConfidenceStreak = 0\n\n let current: ProposeReviewControlState<State, Summary> = {\n shot: 0,\n state: config.initialState,\n priorReview: null,\n verification: { pass: false },\n memory: await memory.load(),\n completed: false,\n reviewAvailable: false,\n }\n\n return runAgentControlLoop({\n intent: config.goal,\n budget: { maxSteps: maxShots, maxWallMs: config.maxWallMs },\n store: config.store,\n scenarioId: config.scenarioId ?? 'propose-review-control',\n projectId: config.projectId,\n variantId: config.variantId,\n actionFailure: config.actionFailure ?? 'stop',\n observe: () => current,\n validate: ({ state }) => [\n objectiveEval({\n id: 'verification',\n passed: state.verification.pass,\n score: state.verification.score,\n severity: 'critical',\n detail: state.verification.pass\n ? 'verification passed'\n : `verification failed${state.verification.failingLayers?.length ? `: ${state.verification.failingLayers.join(', ')}` : ''}`,\n }),\n ],\n shouldStop: ({ state }) => {\n if (state.verification.pass) {\n return {\n stop: true,\n pass: true,\n reason: 'verification passed',\n score: state.verification.score,\n }\n }\n if (state.completed) {\n return {\n stop: true,\n pass: false,\n reason: 'reviewer stopped continuation',\n score: state.verification.score,\n failureClass: failureClassFromVerification(state.verification),\n }\n }\n return {\n stop: false,\n pass: false,\n reason: 'verification still failing',\n score: state.verification.score,\n }\n },\n decide: ({ state }) => ({\n type: 'continue',\n action: { type: 'propose-review-shot', shot: state.shot + 1 },\n reason: state.priorReview?.nextShotInstruction ?? fallbackInstruction,\n }),\n act: async (action, ctx) => {\n const shot = action.shot\n const proposeOut: ProposeOutput<State, Summary> = await config.propose({\n shot,\n goal: config.goal,\n state: current.state,\n priorReview: current.priorReview,\n abortSignal: ctx.abortSignal,\n emitter: ctx.emitter,\n })\n\n const nextState = proposeOut.state\n const verification = await config.verify(nextState)\n let review: Review | null = null\n let reviewAvailable = false\n let reviewError: string | undefined\n let shouldContinue = !verification.pass\n\n if (!verification.pass) {\n try {\n review = await config.review({\n shot,\n goal: config.goal,\n state: nextState,\n verification,\n traceSummary: proposeOut.traceSummary,\n memory: await memory.load(),\n })\n reviewAvailable = true\n shouldContinue = review.shouldContinue\n lowConfidenceStreak = review.confidence <= confidenceFloor ? lowConfidenceStreak + 1 : 0\n if (confidenceFloorWindow > 0 && lowConfidenceStreak >= confidenceFloorWindow)\n shouldContinue = false\n } catch (err) {\n reviewError = err instanceof Error ? err.message : String(err)\n review = current.priorReview ?? {\n observations: 'Reviewer unavailable.',\n diagnosis: reviewError,\n nextShotInstruction: fallbackInstruction,\n shouldContinue: true,\n confidence: 0,\n }\n shouldContinue = true\n }\n } else {\n review = {\n observations: 'Verification passed.',\n diagnosis: 'No further revision needed.',\n nextShotInstruction: '',\n shouldContinue: false,\n confidence: 1,\n }\n }\n\n const entry: ReviewMemoryEntry = {\n ...(review ?? {\n observations: 'No review.',\n diagnosis: '',\n nextShotInstruction: fallbackInstruction,\n shouldContinue,\n confidence: 0,\n }),\n shot,\n timestamp: Date.now(),\n verification: {\n pass: verification.pass,\n score: verification.score,\n failingLayers: verification.failingLayers,\n },\n }\n await memory.append(entry)\n\n current = {\n shot,\n state: nextState,\n priorReview: review,\n verification,\n traceSummary: proposeOut.traceSummary,\n memory: await memory.load(),\n completed: verification.pass || !shouldContinue,\n reviewAvailable,\n reviewError,\n }\n\n return {\n state: nextState,\n verification,\n traceSummary: proposeOut.traceSummary,\n review,\n reviewAvailable,\n reviewError,\n }\n },\n })\n}\n\nexport function controlFailureClassFromVerification(\n verification: Verification,\n): FailureClass | undefined {\n if (verification.pass) return undefined\n return verification.failingLayers?.length ? 'instruction_following' : 'unknown'\n}\n"],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { S as ToolSpan, c as JudgeSpan, f as Run, l as LlmSpan, o as FailureClass } from "./schema-BtVldJ3T.js";
2
+ import { s as TraceStore } from "./store-CT9YIIve.js";
3
+ //#region src/trace/query.d.ts
4
+ declare function runsForScenario(store: TraceStore, scenarioId: string): Promise<Run[]>;
5
+ declare function llmSpans(store: TraceStore, runId?: string): Promise<LlmSpan[]>;
6
+ declare function toolSpans(store: TraceStore, runId?: string, toolName?: string): Promise<ToolSpan[]>;
7
+ /** Query judge-kind spans from the trace store, optionally scoped to a single run. */
8
+ declare function judgeSpans(store: TraceStore, runId?: string): Promise<JudgeSpan[]>;
9
+ /** Group spans by any key selector. */
10
+ declare function groupBy<T, K extends string | number>(items: T[], key: (t: T) => K): Map<K, T[]>;
11
+ /** Hash tool arguments to an orderless-key-stable string for de-duplication. */
12
+ declare function argHash(args: unknown): string;
13
+ /** Whether argument-based comparisons are valid for this tool call. */
14
+ declare function hasCapturedToolArgs(span: ToolSpan): boolean;
15
+ /** Sum an LLM-span array into aggregate token + cost. */
16
+ declare function aggregateLlm(spans: LlmSpan[]): {
17
+ inputTokens: number;
18
+ outputTokens: number;
19
+ cachedTokens: number;
20
+ cacheWriteTokens: number;
21
+ reasoningTokens: number;
22
+ costUsd: number;
23
+ };
24
+ /** Pick the outcome's failure class when present, else derive 'success' from run status. */
25
+ declare function runFailureClass(run: Run): FailureClass;
26
+ //#endregion
27
+ export { judgeSpans as a, runsForScenario as c, hasCapturedToolArgs as i, toolSpans as l, argHash as n, llmSpans as o, groupBy as r, runFailureClass as s, aggregateLlm as t };
28
+ //# sourceMappingURL=query-CJ_DX8vl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-CJ_DX8vl.d.ts","names":[],"sources":["../src/trace/query.ts"],"mappings":";;;iBAasB,gBAAgB,OAAO,YAAY,qBAAqB,QAAQ;iBAIhE,SAAS,OAAO,YAAY,iBAAiB,QAAQ;iBAKrD,UACpB,OAAO,YACP,gBACA,oBACC,QAAQ;;iBAMW,WAAW,OAAO,YAAY,iBAAiB,QAAQ;;iBAM7D,QAAQ,GAAG,2BAA2B,OAAO,KAAK,MAAM,GAAG,MAAM,IAAI,IAAI,GAAG;;iBAe5E,QAAQ;;iBAKR,oBAAoB,MAAM;;iBAuB1B,aAAa,OAAO;EAClC;EACA;EACA;EACA;EACA;EACA;;;iBAuBc,gBAAgB,KAAK,MAAM"}
@@ -0,0 +1,83 @@
1
+ import { i as isLlmSpan, r as isJudgeSpan, s as isToolSpan } from "./schema-CRhEY1SO.js";
2
+ //#region src/trace/query.ts
3
+ async function runsForScenario(store, scenarioId) {
4
+ return store.listRuns({ scenarioId });
5
+ }
6
+ async function llmSpans(store, runId) {
7
+ return (await store.spans({
8
+ runId,
9
+ kind: "llm"
10
+ })).filter(isLlmSpan);
11
+ }
12
+ async function toolSpans(store, runId, toolName) {
13
+ return (await store.spans({
14
+ runId,
15
+ kind: "tool",
16
+ toolName
17
+ })).filter(isToolSpan);
18
+ }
19
+ /** Query judge-kind spans from the trace store, optionally scoped to a single run. */
20
+ async function judgeSpans(store, runId) {
21
+ return (await store.spans({
22
+ runId,
23
+ kind: "judge"
24
+ })).filter(isJudgeSpan);
25
+ }
26
+ /** Group spans by any key selector. */
27
+ function groupBy(items, key) {
28
+ const map = /* @__PURE__ */ new Map();
29
+ for (const item of items) {
30
+ const k = key(item);
31
+ let bucket = map.get(k);
32
+ if (!bucket) {
33
+ bucket = [];
34
+ map.set(k, bucket);
35
+ }
36
+ bucket.push(item);
37
+ }
38
+ return map;
39
+ }
40
+ /** Hash tool arguments to an orderless-key-stable string for de-duplication. */
41
+ function argHash(args) {
42
+ return stableStringify(args);
43
+ }
44
+ /** Whether argument-based comparisons are valid for this tool call. */
45
+ function hasCapturedToolArgs(span) {
46
+ return span.argsCaptured !== false;
47
+ }
48
+ function stableStringify(value) {
49
+ if (value === void 0) return "undefined";
50
+ if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "undefined";
51
+ if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
52
+ const obj = value;
53
+ return `{${Object.keys(obj).filter((k) => obj[k] !== void 0).sort().map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`).join(",")}}`;
54
+ }
55
+ /** Sum an LLM-span array into aggregate token + cost. */
56
+ function aggregateLlm(spans) {
57
+ return spans.reduce((acc, s) => ({
58
+ inputTokens: acc.inputTokens + (s.inputTokens ?? 0),
59
+ outputTokens: acc.outputTokens + (s.outputTokens ?? 0),
60
+ cachedTokens: acc.cachedTokens + (s.cachedTokens ?? 0),
61
+ cacheWriteTokens: acc.cacheWriteTokens + (s.cacheWriteTokens ?? 0),
62
+ reasoningTokens: acc.reasoningTokens + (s.reasoningTokens ?? 0),
63
+ costUsd: acc.costUsd + (s.costUsd ?? 0)
64
+ }), {
65
+ inputTokens: 0,
66
+ outputTokens: 0,
67
+ cachedTokens: 0,
68
+ cacheWriteTokens: 0,
69
+ reasoningTokens: 0,
70
+ costUsd: 0
71
+ });
72
+ }
73
+ /** Pick the outcome's failure class when present, else derive 'success' from run status. */
74
+ function runFailureClass(run) {
75
+ if (run.outcome?.failureClass) return run.outcome.failureClass;
76
+ if (run.status === "completed" && run.outcome?.pass !== false) return "success";
77
+ if (run.status === "aborted") return "budget_exceeded";
78
+ return "unknown";
79
+ }
80
+ //#endregion
81
+ export { judgeSpans as a, runsForScenario as c, hasCapturedToolArgs as i, toolSpans as l, argHash as n, llmSpans as o, groupBy as r, runFailureClass as s, aggregateLlm as t };
82
+
83
+ //# sourceMappingURL=query-Di7eEQ79.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-Di7eEQ79.js","names":[],"sources":["../src/trace/query.ts"],"sourcesContent":["/**\n * Typed query helpers over TraceStore.\n *\n * Not a full SQL engine — a minimal, composable set of operators that\n * cover the canned-pipeline use cases. For ad-hoc analytics, persist to\n * NDJSON and point DuckDB at it; the schema is stable so external SQL\n * tooling works out of the box.\n */\n\nimport type { FailureClass, JudgeSpan, LlmSpan, Run, ToolSpan } from './schema'\nimport { isJudgeSpan, isLlmSpan, isToolSpan } from './schema'\nimport type { TraceStore } from './store'\n\nexport async function runsForScenario(store: TraceStore, scenarioId: string): Promise<Run[]> {\n return store.listRuns({ scenarioId })\n}\n\nexport async function llmSpans(store: TraceStore, runId?: string): Promise<LlmSpan[]> {\n const spans = await store.spans({ runId, kind: 'llm' })\n return spans.filter(isLlmSpan)\n}\n\nexport async function toolSpans(\n store: TraceStore,\n runId?: string,\n toolName?: string,\n): Promise<ToolSpan[]> {\n const spans = await store.spans({ runId, kind: 'tool', toolName })\n return spans.filter(isToolSpan)\n}\n\n/** Query judge-kind spans from the trace store, optionally scoped to a single run. */\nexport async function judgeSpans(store: TraceStore, runId?: string): Promise<JudgeSpan[]> {\n const spans = await store.spans({ runId, kind: 'judge' })\n return spans.filter(isJudgeSpan)\n}\n\n/** Group spans by any key selector. */\nexport function groupBy<T, K extends string | number>(items: T[], key: (t: T) => K): Map<K, T[]> {\n const map = new Map<K, T[]>()\n for (const item of items) {\n const k = key(item)\n let bucket = map.get(k)\n if (!bucket) {\n bucket = []\n map.set(k, bucket)\n }\n bucket.push(item)\n }\n return map\n}\n\n/** Hash tool arguments to an orderless-key-stable string for de-duplication. */\nexport function argHash(args: unknown): string {\n return stableStringify(args)\n}\n\n/** Whether argument-based comparisons are valid for this tool call. */\nexport function hasCapturedToolArgs(span: ToolSpan): boolean {\n return span.argsCaptured !== false\n}\n\nfunction stableStringify(value: unknown): string {\n // Must ALWAYS return a string: JSON.stringify(undefined) — and stringify of\n // functions/symbols — yields the JS value `undefined`, which would make\n // argHash return a non-string and silently break the de-dup keys behind\n // stuck-loop and failure-cluster.\n if (value === undefined) return 'undefined'\n if (value === null || typeof value !== 'object') return JSON.stringify(value) ?? 'undefined'\n if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`\n // Drop undefined-valued keys to match JSON.stringify semantics, so\n // `{a:1}` and `{a:1,b:undefined}` hash identically.\n const obj = value as Record<string, unknown>\n const keys = Object.keys(obj)\n .filter((k) => obj[k] !== undefined)\n .sort()\n const parts = keys.map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`)\n return `{${parts.join(',')}}`\n}\n\n/** Sum an LLM-span array into aggregate token + cost. */\nexport function aggregateLlm(spans: LlmSpan[]): {\n inputTokens: number\n outputTokens: number\n cachedTokens: number\n cacheWriteTokens: number\n reasoningTokens: number\n costUsd: number\n} {\n return spans.reduce(\n (acc, s) => ({\n inputTokens: acc.inputTokens + (s.inputTokens ?? 0),\n outputTokens: acc.outputTokens + (s.outputTokens ?? 0),\n cachedTokens: acc.cachedTokens + (s.cachedTokens ?? 0),\n cacheWriteTokens: acc.cacheWriteTokens + (s.cacheWriteTokens ?? 0),\n reasoningTokens: acc.reasoningTokens + (s.reasoningTokens ?? 0),\n costUsd: acc.costUsd + (s.costUsd ?? 0),\n }),\n {\n inputTokens: 0,\n outputTokens: 0,\n cachedTokens: 0,\n cacheWriteTokens: 0,\n reasoningTokens: 0,\n costUsd: 0,\n },\n )\n}\n\n/** Pick the outcome's failure class when present, else derive 'success' from run status. */\nexport function runFailureClass(run: Run): FailureClass {\n if (run.outcome?.failureClass) return run.outcome.failureClass\n if (run.status === 'completed' && run.outcome?.pass !== false) return 'success'\n if (run.status === 'aborted') return 'budget_exceeded'\n return 'unknown'\n}\n"],"mappings":";;AAaA,eAAsB,gBAAgB,OAAmB,YAAoC;CAC3F,OAAO,MAAM,SAAS,EAAE,WAAW,CAAC;AACtC;AAEA,eAAsB,SAAS,OAAmB,OAAoC;CAEpF,QAAO,MADa,MAAM,MAAM;EAAE;EAAO,MAAM;CAAM,CAAC,EAAA,CACzC,OAAO,SAAS;AAC/B;AAEA,eAAsB,UACpB,OACA,OACA,UACqB;CAErB,QAAO,MADa,MAAM,MAAM;EAAE;EAAO,MAAM;EAAQ;CAAS,CAAC,EAAA,CACpD,OAAO,UAAU;AAChC;;AAGA,eAAsB,WAAW,OAAmB,OAAsC;CAExF,QAAO,MADa,MAAM,MAAM;EAAE;EAAO,MAAM;CAAQ,CAAC,EAAA,CAC3C,OAAO,WAAW;AACjC;;AAGA,SAAgB,QAAsC,OAAY,KAA+B;CAC/F,MAAM,sBAAM,IAAI,IAAY;CAC5B,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,IAAI,IAAI,IAAI;EAClB,IAAI,SAAS,IAAI,IAAI,CAAC;EACtB,IAAI,CAAC,QAAQ;GACX,SAAS,CAAC;GACV,IAAI,IAAI,GAAG,MAAM;EACnB;EACA,OAAO,KAAK,IAAI;CAClB;CACA,OAAO;AACT;;AAGA,SAAgB,QAAQ,MAAuB;CAC7C,OAAO,gBAAgB,IAAI;AAC7B;;AAGA,SAAgB,oBAAoB,MAAyB;CAC3D,OAAO,KAAK,iBAAiB;AAC/B;AAEA,SAAS,gBAAgB,OAAwB;CAK/C,IAAI,UAAU,KAAA,GAAW,OAAO;CAChC,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU,OAAO,KAAK,UAAU,KAAK,KAAK;CACjF,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,IAAI,MAAM,IAAI,eAAe,CAAC,CAAC,KAAK,GAAG,EAAE;CAG1E,MAAM,MAAM;CAKZ,OAAO,IAJM,OAAO,KAAK,GAAG,CAAC,CAC1B,QAAQ,MAAM,IAAI,OAAO,KAAA,CAAS,CAAC,CACnC,KACc,CAAC,CAAC,KAAK,MAAM,GAAG,KAAK,UAAU,CAAC,EAAE,GAAG,gBAAgB,IAAI,EAAE,GAC7D,CAAC,CAAC,KAAK,GAAG,EAAE;AAC7B;;AAGA,SAAgB,aAAa,OAO3B;CACA,OAAO,MAAM,QACV,KAAK,OAAO;EACX,aAAa,IAAI,eAAe,EAAE,eAAe;EACjD,cAAc,IAAI,gBAAgB,EAAE,gBAAgB;EACpD,cAAc,IAAI,gBAAgB,EAAE,gBAAgB;EACpD,kBAAkB,IAAI,oBAAoB,EAAE,oBAAoB;EAChE,iBAAiB,IAAI,mBAAmB,EAAE,mBAAmB;EAC7D,SAAS,IAAI,WAAW,EAAE,WAAW;CACvC,IACA;EACE,aAAa;EACb,cAAc;EACd,cAAc;EACd,kBAAkB;EAClB,iBAAiB;EACjB,SAAS;CACX,CACF;AACF;;AAGA,SAAgB,gBAAgB,KAAwB;CACtD,IAAI,IAAI,SAAS,cAAc,OAAO,IAAI,QAAQ;CAClD,IAAI,IAAI,WAAW,eAAe,IAAI,SAAS,SAAS,OAAO,OAAO;CACtE,IAAI,IAAI,WAAW,WAAW,OAAO;CACrC,OAAO;AACT"}
@@ -0,0 +1,201 @@
1
+ import { promises } from "node:fs";
2
+ import * as path from "node:path";
3
+ //#region src/trace/raw-provider-sink.ts
4
+ /**
5
+ * RawProviderSink — first-class persistence for the actual HTTP-level
6
+ * request/response bodies of every LLM provider call.
7
+ *
8
+ * Why this is a separate sink from the structured `LlmSpan`:
9
+ *
10
+ * - `LlmSpan` records the *intent* — model name, messages, output text,
11
+ * usage. It's what dashboards read; it's NOT enough for forensics.
12
+ * - When a downstream consumer reports "the verifier used the wrong route"
13
+ * or "tokens look right but reasoning was missing," the only way to
14
+ * answer is the raw HTTP body. Span fields can lie (a proxy can echo
15
+ * a different `model` value than what actually answered); the raw
16
+ * response is ground truth.
17
+ *
18
+ * Default behaviour: opt-in. Pass `rawSink` to `LlmClientOptions` (or the
19
+ * matrix runner / BuilderSession sets it up automatically) and every
20
+ * request, response, and error is recorded — including retries, with the
21
+ * attempt index attached so a flaky call's full event chain is recoverable.
22
+ *
23
+ * Redaction is enforced at sink time. The default redactor strips
24
+ * `Authorization`, `X-Api-Key`, `X-Auth-Token`, `Cookie` headers and any
25
+ * payload field whose key matches `apiKey | api_key | bearer | password |
26
+ * secret | token` (case-insensitive). Override via the sink constructor or
27
+ * the per-call `redactor`. The `redactedFields` array on the persisted
28
+ * event lets a reviewer see what was stripped without exposing the values.
29
+ */
30
+ const REDACTED_HEADER_NAMES = /* @__PURE__ */ new Set([
31
+ "authorization",
32
+ "x-api-key",
33
+ "x-auth-token",
34
+ "cookie",
35
+ "set-cookie",
36
+ "proxy-authorization"
37
+ ]);
38
+ const REDACTED_BODY_KEY = /^(api[_-]?key|bearer|password|secret|token|access[_-]?token|refresh[_-]?token)$/i;
39
+ /**
40
+ * Default redactor — strips well-known auth headers and any body field whose
41
+ * key matches the credential pattern. Records every redacted path on
42
+ * `event.redactedFields` so a downstream reviewer can see what was removed.
43
+ */
44
+ function defaultProviderRedactor(event) {
45
+ const redactedFields = [...event.redactedFields ?? []];
46
+ const requestHeaders = redactHeaders(event.requestHeaders, "request", redactedFields);
47
+ const responseHeaders = redactHeaders(event.responseHeaders, "response", redactedFields);
48
+ const requestBody = redactBody(event.requestBody, "requestBody", redactedFields);
49
+ const responseBody = redactBody(event.responseBody, "responseBody", redactedFields);
50
+ return {
51
+ ...event,
52
+ requestHeaders,
53
+ responseHeaders,
54
+ requestBody,
55
+ responseBody,
56
+ redactedFields
57
+ };
58
+ }
59
+ function redactHeaders(headers, prefix, redactedFields) {
60
+ if (!headers) return headers;
61
+ const out = {};
62
+ for (const [k, v] of Object.entries(headers)) {
63
+ if (REDACTED_HEADER_NAMES.has(k.toLowerCase())) {
64
+ redactedFields.push(`${prefix}Headers.${k}`);
65
+ continue;
66
+ }
67
+ out[k] = v;
68
+ }
69
+ return out;
70
+ }
71
+ function redactBody(value, pathStr, redactedFields) {
72
+ if (value == null) return value;
73
+ if (Array.isArray(value)) return value.map((v, i) => redactBody(v, `${pathStr}[${i}]`, redactedFields));
74
+ if (typeof value === "object") {
75
+ const out = {};
76
+ for (const [k, v] of Object.entries(value)) {
77
+ if (REDACTED_BODY_KEY.test(k)) {
78
+ redactedFields.push(`${pathStr}.${k}`);
79
+ continue;
80
+ }
81
+ out[k] = redactBody(v, `${pathStr}.${k}`, redactedFields);
82
+ }
83
+ return out;
84
+ }
85
+ return value;
86
+ }
87
+ var InMemoryRawProviderSink = class {
88
+ events = [];
89
+ redactor;
90
+ constructor(opts = {}) {
91
+ this.redactor = opts.redactor ?? defaultProviderRedactor;
92
+ }
93
+ async record(event) {
94
+ this.events.push(this.redactor({
95
+ ...event,
96
+ redactedFields: event.redactedFields ?? []
97
+ }));
98
+ }
99
+ async list(filter = {}) {
100
+ return this.events.filter((e) => (filter.runId === void 0 || e.runId === filter.runId) && (filter.spanId === void 0 || e.spanId === filter.spanId) && (filter.direction === void 0 || e.direction === filter.direction) && (filter.attemptIndex === void 0 || e.attemptIndex === filter.attemptIndex));
101
+ }
102
+ size() {
103
+ return this.events.length;
104
+ }
105
+ };
106
+ var NoopRawProviderSink = class {
107
+ async record() {}
108
+ /**
109
+ * Returns an empty array. Implemented so `assertRunCaptured` does not
110
+ * trip the `no_raw_sink` issue when a caller explicitly opts out of
111
+ * capture by passing this sink — opt-out is a deliberate choice, not a
112
+ * misconfiguration.
113
+ */
114
+ async list() {
115
+ return [];
116
+ }
117
+ };
118
+ var FileSystemRawProviderSink = class {
119
+ dir;
120
+ fileName;
121
+ rollAtBytes;
122
+ redactor;
123
+ bytesWritten = 0;
124
+ rollIndex = 0;
125
+ initPromise = null;
126
+ constructor(opts) {
127
+ this.dir = opts.dir;
128
+ this.fileName = opts.fileName ?? "raw-provider-events.ndjson";
129
+ this.rollAtBytes = opts.rollAtBytes ?? 32 * 1024 * 1024;
130
+ this.redactor = opts.redactor ?? defaultProviderRedactor;
131
+ }
132
+ async ensureInit() {
133
+ if (!this.initPromise) this.initPromise = promises.mkdir(this.dir, { recursive: true }).then(() => void 0);
134
+ await this.initPromise;
135
+ }
136
+ currentPath() {
137
+ if (this.rollIndex === 0) return path.join(this.dir, this.fileName);
138
+ return path.join(this.dir, `${this.fileName}.${this.rollIndex}`);
139
+ }
140
+ async record(event) {
141
+ await this.ensureInit();
142
+ const redacted = this.redactor({
143
+ ...event,
144
+ redactedFields: event.redactedFields ?? []
145
+ });
146
+ const line = `${JSON.stringify(redacted)}\n`;
147
+ if (this.bytesWritten + line.length > this.rollAtBytes && this.bytesWritten > 0) {
148
+ this.rollIndex += 1;
149
+ this.bytesWritten = 0;
150
+ }
151
+ await promises.appendFile(this.currentPath(), line, "utf8");
152
+ this.bytesWritten += line.length;
153
+ }
154
+ async list(filter = {}) {
155
+ await this.ensureInit();
156
+ const out = [];
157
+ for (let i = 0; i <= this.rollIndex; i++) {
158
+ const file = i === 0 ? path.join(this.dir, this.fileName) : path.join(this.dir, `${this.fileName}.${i}`);
159
+ let body;
160
+ try {
161
+ body = await promises.readFile(file, "utf8");
162
+ } catch (err) {
163
+ if (err.code === "ENOENT") continue;
164
+ throw err;
165
+ }
166
+ for (const line of body.split("\n")) {
167
+ if (!line) continue;
168
+ const event = JSON.parse(line);
169
+ if (filter.runId !== void 0 && event.runId !== filter.runId) continue;
170
+ if (filter.spanId !== void 0 && event.spanId !== filter.spanId) continue;
171
+ if (filter.direction !== void 0 && event.direction !== filter.direction) continue;
172
+ if (filter.attemptIndex !== void 0 && event.attemptIndex !== filter.attemptIndex) continue;
173
+ out.push(event);
174
+ }
175
+ }
176
+ return out;
177
+ }
178
+ };
179
+ /**
180
+ * Best-effort provider id from a base URL. Falls back to the URL host when
181
+ * none of the well-known patterns match.
182
+ */
183
+ function providerFromBaseUrl(baseUrl) {
184
+ const lower = baseUrl.toLowerCase();
185
+ if (lower.includes("api.openai.com")) return "openai";
186
+ if (lower.includes("api.anthropic.com")) return "anthropic";
187
+ if (lower.includes("generativelanguage.googleapis.com")) return "google";
188
+ if (lower.includes("api.together.ai") || lower.includes("api.together.xyz")) return "together";
189
+ if (lower.includes("api.deepseek.com")) return "deepseek";
190
+ if (lower.includes("router.tangle.tools")) return "tangle-router";
191
+ if (lower.includes("api.litellm") || lower.includes("litellm")) return "litellm";
192
+ try {
193
+ return new URL(baseUrl).host;
194
+ } catch {
195
+ return baseUrl;
196
+ }
197
+ }
198
+ //#endregion
199
+ export { providerFromBaseUrl as a, defaultProviderRedactor as i, InMemoryRawProviderSink as n, NoopRawProviderSink as r, FileSystemRawProviderSink as t };
200
+
201
+ //# sourceMappingURL=raw-provider-sink-BQd7mzyT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-provider-sink-BQd7mzyT.js","names":["fs"],"sources":["../src/trace/raw-provider-sink.ts"],"sourcesContent":["/**\n * RawProviderSink — first-class persistence for the actual HTTP-level\n * request/response bodies of every LLM provider call.\n *\n * Why this is a separate sink from the structured `LlmSpan`:\n *\n * - `LlmSpan` records the *intent* — model name, messages, output text,\n * usage. It's what dashboards read; it's NOT enough for forensics.\n * - When a downstream consumer reports \"the verifier used the wrong route\"\n * or \"tokens look right but reasoning was missing,\" the only way to\n * answer is the raw HTTP body. Span fields can lie (a proxy can echo\n * a different `model` value than what actually answered); the raw\n * response is ground truth.\n *\n * Default behaviour: opt-in. Pass `rawSink` to `LlmClientOptions` (or the\n * matrix runner / BuilderSession sets it up automatically) and every\n * request, response, and error is recorded — including retries, with the\n * attempt index attached so a flaky call's full event chain is recoverable.\n *\n * Redaction is enforced at sink time. The default redactor strips\n * `Authorization`, `X-Api-Key`, `X-Auth-Token`, `Cookie` headers and any\n * payload field whose key matches `apiKey | api_key | bearer | password |\n * secret | token` (case-insensitive). Override via the sink constructor or\n * the per-call `redactor`. The `redactedFields` array on the persisted\n * event lets a reviewer see what was stripped without exposing the values.\n */\n\nimport { promises as fs } from 'node:fs'\nimport * as path from 'node:path'\n\nexport type RawProviderDirection = 'request' | 'response' | 'error'\n\nexport interface RawProviderEvent {\n /** Stable id. Generated by the sink if omitted. */\n eventId: string\n /** Trace context populated by `LlmClient` when the call is wrapped in a span. */\n runId?: string\n spanId?: string\n /**\n * Logical provider name. Free-form so callers can use whatever id matches\n * their topology (`'openai'`, `'anthropic'`, `'tangle-router'`, …). When\n * omitted, derived from `baseUrl` in `LlmClientOptions`.\n */\n provider: string\n model: string\n /** Endpoint path, e.g. `'/v1/chat/completions'`. */\n endpoint: string\n /** Base URL used for the call (already-normalised — no trailing slash). */\n baseUrl: string\n /** 0-indexed retry attempt. The first attempt is 0; a retried call gets 1, 2, … */\n attemptIndex: number\n direction: RawProviderDirection\n /** Unix ms. */\n timestamp: number\n /** Wall-clock duration of the call leg. Set on `response` and `error` events; null on `request`. */\n durationMs?: number\n statusCode?: number\n requestHeaders?: Record<string, string>\n requestBody?: unknown\n responseHeaders?: Record<string, string>\n responseBody?: unknown\n /** Set on `direction: 'error'` events. */\n errorMessage?: string\n /** Field paths the redactor stripped from this event ('header:Authorization', 'body.apiKey', …). */\n redactedFields: string[]\n}\n\nexport interface RawProviderSinkFilter {\n runId?: string\n spanId?: string\n direction?: RawProviderDirection\n attemptIndex?: number\n}\n\nexport interface RawProviderSink {\n record(event: RawProviderEvent): Promise<void>\n /** Optional listing — implementations that durably persist (file, db) should support this. */\n list?(filter?: RawProviderSinkFilter): Promise<RawProviderEvent[]>\n /** Optional teardown for backed implementations. */\n close?(): Promise<void>\n}\n\nexport type ProviderRedactor = (event: RawProviderEvent) => RawProviderEvent\n\nconst REDACTED_HEADER_NAMES = new Set([\n 'authorization',\n 'x-api-key',\n 'x-auth-token',\n 'cookie',\n 'set-cookie',\n 'proxy-authorization',\n])\n\nconst REDACTED_BODY_KEY =\n /^(api[_-]?key|bearer|password|secret|token|access[_-]?token|refresh[_-]?token)$/i\n\n/**\n * Default redactor — strips well-known auth headers and any body field whose\n * key matches the credential pattern. Records every redacted path on\n * `event.redactedFields` so a downstream reviewer can see what was removed.\n */\nexport function defaultProviderRedactor(event: RawProviderEvent): RawProviderEvent {\n const redactedFields: string[] = [...(event.redactedFields ?? [])]\n const requestHeaders = redactHeaders(event.requestHeaders, 'request', redactedFields)\n const responseHeaders = redactHeaders(event.responseHeaders, 'response', redactedFields)\n const requestBody = redactBody(event.requestBody, 'requestBody', redactedFields)\n const responseBody = redactBody(event.responseBody, 'responseBody', redactedFields)\n return { ...event, requestHeaders, responseHeaders, requestBody, responseBody, redactedFields }\n}\n\nfunction redactHeaders(\n headers: Record<string, string> | undefined,\n prefix: 'request' | 'response',\n redactedFields: string[],\n): Record<string, string> | undefined {\n if (!headers) return headers\n const out: Record<string, string> = {}\n for (const [k, v] of Object.entries(headers)) {\n if (REDACTED_HEADER_NAMES.has(k.toLowerCase())) {\n redactedFields.push(`${prefix}Headers.${k}`)\n continue\n }\n out[k] = v\n }\n return out\n}\n\nfunction redactBody(value: unknown, pathStr: string, redactedFields: string[]): unknown {\n if (value == null) return value\n if (Array.isArray(value))\n return value.map((v, i) => redactBody(v, `${pathStr}[${i}]`, redactedFields))\n if (typeof value === 'object') {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (REDACTED_BODY_KEY.test(k)) {\n redactedFields.push(`${pathStr}.${k}`)\n continue\n }\n out[k] = redactBody(v, `${pathStr}.${k}`, redactedFields)\n }\n return out\n }\n return value\n}\n\n// ── In-memory ────────────────────────────────────────────────────────────\n\nexport interface InMemoryRawProviderSinkOptions {\n redactor?: ProviderRedactor\n}\n\nexport class InMemoryRawProviderSink implements RawProviderSink {\n private events: RawProviderEvent[] = []\n private redactor: ProviderRedactor\n\n constructor(opts: InMemoryRawProviderSinkOptions = {}) {\n this.redactor = opts.redactor ?? defaultProviderRedactor\n }\n\n async record(event: RawProviderEvent): Promise<void> {\n this.events.push(this.redactor({ ...event, redactedFields: event.redactedFields ?? [] }))\n }\n\n async list(filter: RawProviderSinkFilter = {}): Promise<RawProviderEvent[]> {\n return this.events.filter(\n (e) =>\n (filter.runId === undefined || e.runId === filter.runId) &&\n (filter.spanId === undefined || e.spanId === filter.spanId) &&\n (filter.direction === undefined || e.direction === filter.direction) &&\n (filter.attemptIndex === undefined || e.attemptIndex === filter.attemptIndex),\n )\n }\n\n size(): number {\n return this.events.length\n }\n}\n\nexport class NoopRawProviderSink implements RawProviderSink {\n async record(): Promise<void> {\n /* no-op */\n }\n /**\n * Returns an empty array. Implemented so `assertRunCaptured` does not\n * trip the `no_raw_sink` issue when a caller explicitly opts out of\n * capture by passing this sink — opt-out is a deliberate choice, not a\n * misconfiguration.\n */\n async list(): Promise<RawProviderEvent[]> {\n return []\n }\n}\n\n// ── Filesystem (NDJSON) ──────────────────────────────────────────────────\n\nexport interface FileSystemRawProviderSinkOptions {\n /** Directory the NDJSON file is written into. Created if missing. */\n dir: string\n /** File name; default `'raw-provider-events.ndjson'`. */\n fileName?: string\n /** Bytes after which the writer rolls over to a new file (default 32 MiB). */\n rollAtBytes?: number\n redactor?: ProviderRedactor\n}\n\nexport class FileSystemRawProviderSink implements RawProviderSink {\n private dir: string\n private fileName: string\n private rollAtBytes: number\n private redactor: ProviderRedactor\n private bytesWritten = 0\n private rollIndex = 0\n private initPromise: Promise<void> | null = null\n\n constructor(opts: FileSystemRawProviderSinkOptions) {\n this.dir = opts.dir\n this.fileName = opts.fileName ?? 'raw-provider-events.ndjson'\n this.rollAtBytes = opts.rollAtBytes ?? 32 * 1024 * 1024\n this.redactor = opts.redactor ?? defaultProviderRedactor\n }\n\n private async ensureInit(): Promise<void> {\n if (!this.initPromise) {\n this.initPromise = fs.mkdir(this.dir, { recursive: true }).then(() => undefined)\n }\n await this.initPromise\n }\n\n private currentPath(): string {\n if (this.rollIndex === 0) return path.join(this.dir, this.fileName)\n return path.join(this.dir, `${this.fileName}.${this.rollIndex}`)\n }\n\n async record(event: RawProviderEvent): Promise<void> {\n await this.ensureInit()\n const redacted = this.redactor({ ...event, redactedFields: event.redactedFields ?? [] })\n const line = `${JSON.stringify(redacted)}\\n`\n if (this.bytesWritten + line.length > this.rollAtBytes && this.bytesWritten > 0) {\n this.rollIndex += 1\n this.bytesWritten = 0\n }\n await fs.appendFile(this.currentPath(), line, 'utf8')\n this.bytesWritten += line.length\n }\n\n async list(filter: RawProviderSinkFilter = {}): Promise<RawProviderEvent[]> {\n await this.ensureInit()\n const out: RawProviderEvent[] = []\n for (let i = 0; i <= this.rollIndex; i++) {\n const file =\n i === 0 ? path.join(this.dir, this.fileName) : path.join(this.dir, `${this.fileName}.${i}`)\n let body: string\n try {\n body = await fs.readFile(file, 'utf8')\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') continue\n throw err\n }\n for (const line of body.split('\\n')) {\n if (!line) continue\n const event = JSON.parse(line) as RawProviderEvent\n if (filter.runId !== undefined && event.runId !== filter.runId) continue\n if (filter.spanId !== undefined && event.spanId !== filter.spanId) continue\n if (filter.direction !== undefined && event.direction !== filter.direction) continue\n if (filter.attemptIndex !== undefined && event.attemptIndex !== filter.attemptIndex)\n continue\n out.push(event)\n }\n }\n return out\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\n/**\n * Best-effort provider id from a base URL. Falls back to the URL host when\n * none of the well-known patterns match.\n */\nexport function providerFromBaseUrl(baseUrl: string): string {\n const lower = baseUrl.toLowerCase()\n if (lower.includes('api.openai.com')) return 'openai'\n if (lower.includes('api.anthropic.com')) return 'anthropic'\n if (lower.includes('generativelanguage.googleapis.com')) return 'google'\n if (lower.includes('api.together.ai') || lower.includes('api.together.xyz')) return 'together'\n if (lower.includes('api.deepseek.com')) return 'deepseek'\n if (lower.includes('router.tangle.tools')) return 'tangle-router'\n if (lower.includes('api.litellm') || lower.includes('litellm')) return 'litellm'\n try {\n return new URL(baseUrl).host\n } catch {\n return baseUrl\n }\n}\n"],"mappings":"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"}