reeval 0.9.0 → 0.10.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 (318) hide show
  1. package/README.md +42 -30
  2. package/THIRD_PARTY_NOTICES.md +218 -11
  3. package/assets/package.json +1 -1
  4. package/assets/pnpm-lock.yaml +30 -30
  5. package/dist/adapter-DWlpOtRn.js +279 -0
  6. package/dist/adapter-DWlpOtRn.js.map +1 -0
  7. package/dist/{agent-6FefIhX7.js → agent-CURAwx_q.js} +6 -6
  8. package/dist/{agent-6FefIhX7.js.map → agent-CURAwx_q.js.map} +1 -1
  9. package/dist/{agent-WSmTaesf.js → agent-CaS_2Sce.js} +46 -15
  10. package/dist/agent-CaS_2Sce.js.map +1 -0
  11. package/dist/{analysis-DlGBDjTj.js → analysis-Bxub9LMT.js} +4 -4
  12. package/dist/{analysis-DlGBDjTj.js.map → analysis-Bxub9LMT.js.map} +1 -1
  13. package/dist/{assemble-BCZzTyR7.js → assemble-B9Alds-z.js} +69 -41
  14. package/dist/assemble-B9Alds-z.js.map +1 -0
  15. package/dist/assemble-J5MukZFY.js +1 -0
  16. package/dist/{client-Bbo9SPlK.js → assert-EUIoRdIt.js} +10 -113
  17. package/dist/assert-EUIoRdIt.js.map +1 -0
  18. package/dist/bridge/index.mjs +248 -55
  19. package/dist/{capture-Bp74Z6Fr.js → capture-CNb9SuU5.js} +145 -31
  20. package/dist/capture-CNb9SuU5.js.map +1 -0
  21. package/dist/capture-jquXZBKK.js +1 -0
  22. package/dist/{cli-CVrMh_qz.js → cli-D303Vj5N.js} +133 -115
  23. package/dist/cli-D303Vj5N.js.map +1 -0
  24. package/dist/{cli-spec-CKEYa8V2.js → cli-spec-BPZbQG2p.js} +36 -17
  25. package/dist/cli-spec-BPZbQG2p.js.map +1 -0
  26. package/dist/cli.js +4 -2
  27. package/dist/cli.js.map +1 -1
  28. package/dist/client-fcwgwOAD.js +106 -0
  29. package/dist/client-fcwgwOAD.js.map +1 -0
  30. package/dist/{command-CzIFp1JQ.js → command-BLfT7vnQ.js} +18 -17
  31. package/dist/command-BLfT7vnQ.js.map +1 -0
  32. package/dist/{command-C5xFPKHM.js → command-BT9a37ZR.js} +374 -72
  33. package/dist/command-BT9a37ZR.js.map +1 -0
  34. package/dist/{command-DUT5l13I.js → command-Bge8F7Ko.js} +316 -83
  35. package/dist/command-Bge8F7Ko.js.map +1 -0
  36. package/dist/command-BkFjijN2.js +1 -0
  37. package/dist/{command-BFP0hKEb.js → command-CMJtHKRa.js} +14 -14
  38. package/dist/{command-BFP0hKEb.js.map → command-CMJtHKRa.js.map} +1 -1
  39. package/dist/commands-1p-bIWhN.js +1 -0
  40. package/dist/{commands-CLmPBrTS.js → commands-BFx16WB8.js} +7 -7
  41. package/dist/commands-BFx16WB8.js.map +1 -0
  42. package/dist/config-DEgnUiU-.js +756 -0
  43. package/dist/config-DEgnUiU-.js.map +1 -0
  44. package/dist/{context-DbSMEVKs.js → context-C1mxXh80.js} +11 -3
  45. package/dist/context-C1mxXh80.js.map +1 -0
  46. package/dist/{db-CfQFwJtq.js → db-CdHizc4_.js} +455 -36
  47. package/dist/db-CdHizc4_.js.map +1 -0
  48. package/dist/db-Dm1cRJJP.js +2 -0
  49. package/dist/debug-D7bEv_UV.js +1 -0
  50. package/dist/{dist-CTzThfu_.js → dist-B8hJImYt.js} +17 -4
  51. package/dist/dist-B8hJImYt.js.map +1 -0
  52. package/dist/{docker-CRQGQbIt.js → docker-7b_2SaH7.js} +22 -21
  53. package/dist/docker-7b_2SaH7.js.map +1 -0
  54. package/dist/{docker-DV2GNgle.js → docker-sZrNrr82.js} +3 -3
  55. package/dist/docker-sZrNrr82.js.map +1 -0
  56. package/dist/docker-yauK-9X8.js +1 -0
  57. package/dist/{doctor-DlKycx5H.js → doctor-BYNok4UO.js} +262 -83
  58. package/dist/doctor-BYNok4UO.js.map +1 -0
  59. package/dist/{duration-JsJrIWXq.js → duration-CEOQww97.js} +2 -2
  60. package/dist/{duration-JsJrIWXq.js.map → duration-CEOQww97.js.map} +1 -1
  61. package/dist/{egress-BhzNh7Yi.js → egress-C4PZTSSe.js} +146 -14
  62. package/dist/egress-C4PZTSSe.js.map +1 -0
  63. package/dist/environment-DNjRk0nU.js +1133 -0
  64. package/dist/environment-DNjRk0nU.js.map +1 -0
  65. package/dist/{errors-yDAEwmZo.js → errors-B6BSMs03.js} +2 -2
  66. package/dist/errors-B6BSMs03.js.map +1 -0
  67. package/dist/{errors-C9w_ud7g.js → errors-r025B0Zb.js} +4 -4
  68. package/dist/errors-r025B0Zb.js.map +1 -0
  69. package/dist/evaluate-C1UVL21l.d.ts +92 -0
  70. package/dist/evaluate-D4zeRGBF.js +2351 -0
  71. package/dist/evaluate-D4zeRGBF.js.map +1 -0
  72. package/dist/files-BAt0i00X.js +1 -0
  73. package/dist/{files-CSzVADHn.js → files-BXUdY8tr.js} +9 -8
  74. package/dist/{files-CSzVADHn.js.map → files-BXUdY8tr.js.map} +1 -1
  75. package/dist/files-BhyltlDB.js +1 -0
  76. package/dist/files-Bk1mC3AN.js +43 -0
  77. package/dist/files-Bk1mC3AN.js.map +1 -0
  78. package/dist/{files-DJUFg-4e.js → files-DQmHE7pb.js} +5 -5
  79. package/dist/{files-DJUFg-4e.js.map → files-DQmHE7pb.js.map} +1 -1
  80. package/dist/files-ZZPqfAo6.js +1 -0
  81. package/dist/harness-B8QC9u0O.js +323 -0
  82. package/dist/harness-B8QC9u0O.js.map +1 -0
  83. package/dist/harness.d.ts +16 -30
  84. package/dist/harness.js +1 -2
  85. package/dist/{header-CALhmafp.js → header-hK-Z_Po9.js} +2 -2
  86. package/dist/{header-CALhmafp.js.map → header-hK-Z_Po9.js.map} +1 -1
  87. package/dist/{images-BMgdpMAX.js → images-0On0cztu.js} +114 -45
  88. package/dist/images-0On0cztu.js.map +1 -0
  89. package/dist/index.d.ts +9 -37
  90. package/dist/index.js +6 -2138
  91. package/dist/{init-BIdLF0F9.js → init-B77Rpcqc.js} +26 -8
  92. package/dist/init-B77Rpcqc.js.map +1 -0
  93. package/dist/init-BrOWin3W.js +1 -0
  94. package/dist/{invocations-CLaL8AuW.js → invocations-DbGfBAA_.js} +4 -4
  95. package/dist/{invocations-CLaL8AuW.js.map → invocations-DbGfBAA_.js.map} +1 -1
  96. package/dist/{judge-CeYPN8P_.js → judge-DW_GDOmB.js} +11 -19
  97. package/dist/{judge-CeYPN8P_.js.map → judge-DW_GDOmB.js.map} +1 -1
  98. package/dist/judge.d.ts +2 -2
  99. package/dist/judge.js +1 -1
  100. package/dist/{live-S0qODb6o.js → live-jlfszAbb.js} +9 -20
  101. package/dist/live-jlfszAbb.js.map +1 -0
  102. package/dist/matchers-Ddmc2z7H.js +118 -0
  103. package/dist/matchers-Ddmc2z7H.js.map +1 -0
  104. package/dist/{model-DEQo3FkZ.js → model-DaVCY3rb.js} +2 -2
  105. package/dist/{model-DEQo3FkZ.js.map → model-DaVCY3rb.js.map} +1 -1
  106. package/dist/model-NM3ID0uR.js +1 -0
  107. package/dist/{model-B1BZoZ9b.js → model-h_cDtcRr.js} +18 -17
  108. package/dist/model-h_cDtcRr.js.map +1 -0
  109. package/dist/model-nwWJvaUR.js +1 -0
  110. package/dist/{model-BOnlAPzs.js → model-oqcDplJG.js} +111 -19
  111. package/dist/model-oqcDplJG.js.map +1 -0
  112. package/dist/{node-Co7EXge0.js → node-B3ydHo6t.js} +10 -47
  113. package/dist/node-B3ydHo6t.js.map +1 -0
  114. package/dist/object-CLf2-tNq.js +9 -0
  115. package/dist/object-CLf2-tNq.js.map +1 -0
  116. package/dist/{opencode-providers-ByD85Q0l.js → opencode-providers-J9colP0-.js} +96 -21
  117. package/dist/opencode-providers-J9colP0-.js.map +1 -0
  118. package/dist/options-Bh2W63dK.js +1119 -0
  119. package/dist/options-Bh2W63dK.js.map +1 -0
  120. package/dist/{pairs-DDsjgm5F.js → pairs-CnInRu-G.js} +76 -2
  121. package/dist/{pairs-DDsjgm5F.js.map → pairs-CnInRu-G.js.map} +1 -1
  122. package/dist/{patch-bDV8YFW0.js → patch-Zac5aIRM.js} +6 -6
  123. package/dist/{patch-bDV8YFW0.js.map → patch-Zac5aIRM.js.map} +1 -1
  124. package/dist/{plan-DUydFc_1.js → plan-C9Cy27Ay.js} +24 -9
  125. package/dist/plan-C9Cy27Ay.js.map +1 -0
  126. package/dist/preflight-CPWpQeBI.js +1 -0
  127. package/dist/{preflight-BkoSxf4C.js → preflight-D7iFPKeK.js} +8 -7
  128. package/dist/preflight-D7iFPKeK.js.map +1 -0
  129. package/dist/prepare-BGjePFQl.js +2 -0
  130. package/dist/{prepare-CUAWHebF.js → prepare-doGxaAGR.js} +38 -30
  131. package/dist/prepare-doGxaAGR.js.map +1 -0
  132. package/dist/{provenance-D7HK3vzt.js → provenance-DmE9uPVt.js} +3 -3
  133. package/dist/{provenance-D7HK3vzt.js.map → provenance-DmE9uPVt.js.map} +1 -1
  134. package/dist/provider-DehR4CMN.js +1 -0
  135. package/dist/providers-gDMko8fl.js +1 -0
  136. package/dist/providers-tAOD1NQN.js +165 -0
  137. package/dist/providers-tAOD1NQN.js.map +1 -0
  138. package/dist/{query-BjBMLa-C.js → query-Bes9Kh6Y.js} +3 -3
  139. package/dist/{query-BjBMLa-C.js.map → query-Bes9Kh6Y.js.map} +1 -1
  140. package/dist/query-C_G_svLU.js +1 -0
  141. package/dist/questions-DjAwMxZ3.js +524 -0
  142. package/dist/questions-DjAwMxZ3.js.map +1 -0
  143. package/dist/{record-BRP9vZrj.js → record-BKmMvZ6O.js} +9 -1
  144. package/dist/{record-BRP9vZrj.js.map → record-BKmMvZ6O.js.map} +1 -1
  145. package/dist/remote-HDRt16ew.js +378 -0
  146. package/dist/remote-HDRt16ew.js.map +1 -0
  147. package/dist/{results-Di7m8dQ3.js → results-DuauQI3Z.js} +4 -4
  148. package/dist/{results-Di7m8dQ3.js.map → results-DuauQI3Z.js.map} +1 -1
  149. package/dist/{resume-SUz1GskV.js → resume-BRfa8E_s.js} +10 -10
  150. package/dist/{resume-SUz1GskV.js.map → resume-BRfa8E_s.js.map} +1 -1
  151. package/dist/{root-CvdRlRZX.js → root-DICDHCtp.js} +4 -4
  152. package/dist/{root-CvdRlRZX.js.map → root-DICDHCtp.js.map} +1 -1
  153. package/dist/{runtime-DdsfnRz_.js → runtime-PX_oXiCS.js} +23 -71
  154. package/dist/runtime-PX_oXiCS.js.map +1 -0
  155. package/dist/sandbox-D3A8oUb7.js +70 -0
  156. package/dist/sandbox-D3A8oUb7.js.map +1 -0
  157. package/dist/sandbox.d.ts +19 -6
  158. package/dist/sandbox.js +1 -2
  159. package/dist/server-C7sg1ndo.js +1 -0
  160. package/dist/{server-BNnXtmS8.js → server-XDleKaF_.js} +11 -11
  161. package/dist/server-XDleKaF_.js.map +1 -0
  162. package/dist/shared-DYpIb1BI.js +166 -0
  163. package/dist/shared-DYpIb1BI.js.map +1 -0
  164. package/dist/{source-Dof0NQBm.js → source-C8xumIWj.js} +2 -2
  165. package/dist/{source-Dof0NQBm.js.map → source-C8xumIWj.js.map} +1 -1
  166. package/dist/source-fGd0SaKP.js +1 -0
  167. package/dist/{src-8rRXy4u9.js → src-B7treWa8.js} +1538 -180
  168. package/dist/src-B7treWa8.js.map +1 -0
  169. package/dist/{src-C1E9HDWO.js → src-C7_1SqDP.js} +3 -3
  170. package/dist/{src-C1E9HDWO.js.map → src-C7_1SqDP.js.map} +1 -1
  171. package/dist/{src-DDNXsD9H.js → src-CF17Ug08.js} +5 -4
  172. package/dist/src-CF17Ug08.js.map +1 -0
  173. package/dist/{src-C_4Umgh2.js → src-CFp86GtV.js} +52 -51
  174. package/dist/src-CFp86GtV.js.map +1 -0
  175. package/dist/src-C_lPtowT.js +2 -0
  176. package/dist/src-DIL0jST0.js +368 -0
  177. package/dist/src-DIL0jST0.js.map +1 -0
  178. package/dist/src-DNnG4e4R.js +2 -0
  179. package/dist/src-DTbrY1hi.js +2 -0
  180. package/dist/src-DdyJEh2v.js +2 -0
  181. package/dist/src-Dj9PAroc.js +2 -0
  182. package/dist/src-Du8H85Qq.js +2 -0
  183. package/dist/src-DvCg0NBs.js +324 -0
  184. package/dist/src-DvCg0NBs.js.map +1 -0
  185. package/dist/{src-COgE7991.js → src-DvK0EIZx.js} +5 -5
  186. package/dist/{src-COgE7991.js.map → src-DvK0EIZx.js.map} +1 -1
  187. package/dist/{src-DVy58-zZ.js → src-FGXhkEkH.js} +5 -5
  188. package/dist/{src-DVy58-zZ.js.map → src-FGXhkEkH.js.map} +1 -1
  189. package/dist/src-jzagbuqH.js +2 -0
  190. package/dist/src-ofUaYbuY.js +3 -0
  191. package/dist/src-pJZOrYR9.js +1 -0
  192. package/dist/{src-D95O-Smv.js → src-u8_ixn_F.js} +15 -11
  193. package/dist/src-u8_ixn_F.js.map +1 -0
  194. package/dist/{state-CiXyLqg0.js → state-C__9swoG.js} +35 -23
  195. package/dist/state-C__9swoG.js.map +1 -0
  196. package/dist/state-CeR6oz0k.js +66 -0
  197. package/dist/state-CeR6oz0k.js.map +1 -0
  198. package/dist/state-CgjQo29K.js +1 -0
  199. package/dist/studio-app/assets/index-CwQN3f_h.css +2 -0
  200. package/dist/studio-app/assets/{index-CROH2NB3.js → index-DrQc2Yxd.js} +11 -11
  201. package/dist/studio-app/index.html +2 -2
  202. package/dist/{summary-BTksrIxn.js → summary-BLAVLySU.js} +150 -19
  203. package/dist/summary-BLAVLySU.js.map +1 -0
  204. package/dist/{summary-2OAWF2N7.js → summary-DgyjUh_l.js} +7 -7
  205. package/dist/{summary-2OAWF2N7.js.map → summary-DgyjUh_l.js.map} +1 -1
  206. package/dist/testing.d.ts +3 -2
  207. package/dist/testing.js +3 -2
  208. package/dist/{tool-target-BU1JnSE9.js → tool-target-D2mcYlSQ.js} +14 -7
  209. package/dist/tool-target-D2mcYlSQ.js.map +1 -0
  210. package/dist/{tools-B10Uj7OI.js → tools-GCyNYSc1.js} +6 -6
  211. package/dist/tools-GCyNYSc1.js.map +1 -0
  212. package/dist/transcript-BNNANU8A.js +64 -0
  213. package/dist/transcript-BNNANU8A.js.map +1 -0
  214. package/dist/{types-D8RLfkFP.d.ts → types-g17bRAzt.d.ts} +389 -42
  215. package/dist/{usage-DDF_6tkV.js → usage-CleNKkly.js} +4 -2
  216. package/dist/{usage-DDF_6tkV.js.map → usage-CleNKkly.js.map} +1 -1
  217. package/dist/view/index.d.ts +42 -8
  218. package/dist/view/index.js +6 -6
  219. package/dist/views-BW6oCDUQ.js +2 -0
  220. package/dist/{views-Dqa5ojfZ.js → views-BmQF4UCI.js} +13 -8
  221. package/dist/views-BmQF4UCI.js.map +1 -0
  222. package/dist/{worker-entry-BAikHl9F.js → worker-entry-yOchGYYv.js} +16 -229
  223. package/dist/worker-entry-yOchGYYv.js.map +1 -0
  224. package/dist/{workspace-C-TrNIUc.js → workspace-CgyHEM0l.js} +6 -6
  225. package/dist/{workspace-C-TrNIUc.js.map → workspace-CgyHEM0l.js.map} +1 -1
  226. package/dist/workspace-D8sSgpiy.js +1 -0
  227. package/package.json +12 -12
  228. package/dist/agent-WSmTaesf.js.map +0 -1
  229. package/dist/assemble-BCZzTyR7.js.map +0 -1
  230. package/dist/assemble-C5qq5yT2.js +0 -2
  231. package/dist/capture-Bp74Z6Fr.js.map +0 -1
  232. package/dist/capture-DS-cPyuE.js +0 -2
  233. package/dist/cli-CVrMh_qz.js.map +0 -1
  234. package/dist/cli-spec-CKEYa8V2.js.map +0 -1
  235. package/dist/client-Bbo9SPlK.js.map +0 -1
  236. package/dist/command-BrmXUC-W.js +0 -2
  237. package/dist/command-C5xFPKHM.js.map +0 -1
  238. package/dist/command-CzIFp1JQ.js.map +0 -1
  239. package/dist/command-DUT5l13I.js.map +0 -1
  240. package/dist/commands-CLmPBrTS.js.map +0 -1
  241. package/dist/commands-fI3G2Wnh.js +0 -2
  242. package/dist/config-CGvBeewH.js +0 -457
  243. package/dist/config-CGvBeewH.js.map +0 -1
  244. package/dist/context-DbSMEVKs.js.map +0 -1
  245. package/dist/db-CSSFtGcN.js +0 -3
  246. package/dist/db-CfQFwJtq.js.map +0 -1
  247. package/dist/debug-SEmW4w8f.js +0 -2
  248. package/dist/dist-CTzThfu_.js.map +0 -1
  249. package/dist/docker-CRQGQbIt.js.map +0 -1
  250. package/dist/docker-DV2GNgle.js.map +0 -1
  251. package/dist/docker-Df_YOxxB.js +0 -2
  252. package/dist/doctor-DlKycx5H.js.map +0 -1
  253. package/dist/egress-BhzNh7Yi.js.map +0 -1
  254. package/dist/environment-1jE-HhO-.js +0 -657
  255. package/dist/environment-1jE-HhO-.js.map +0 -1
  256. package/dist/errors-C9w_ud7g.js.map +0 -1
  257. package/dist/errors-yDAEwmZo.js.map +0 -1
  258. package/dist/fake-instructions-CUI33I_F.js +0 -32
  259. package/dist/fake-instructions-CUI33I_F.js.map +0 -1
  260. package/dist/files-AiEKuEZe.js +0 -2
  261. package/dist/files-BM78_nnF.js +0 -2
  262. package/dist/files-BMCvfB4X.js +0 -2
  263. package/dist/harness-CeCp2GSW.js +0 -171
  264. package/dist/harness-CeCp2GSW.js.map +0 -1
  265. package/dist/images-BMgdpMAX.js.map +0 -1
  266. package/dist/index.js.map +0 -1
  267. package/dist/init-B6vegaP_.js +0 -2
  268. package/dist/init-BIdLF0F9.js.map +0 -1
  269. package/dist/jiti-BcJHCtrb.js +0 -46
  270. package/dist/jiti-BcJHCtrb.js.map +0 -1
  271. package/dist/live-S0qODb6o.js.map +0 -1
  272. package/dist/model-B1BZoZ9b.js.map +0 -1
  273. package/dist/model-BOnlAPzs.js.map +0 -1
  274. package/dist/model-DWeg5J7z.js +0 -2
  275. package/dist/model-FXko2kl7.js +0 -2
  276. package/dist/node-Co7EXge0.js.map +0 -1
  277. package/dist/opencode-providers-ByD85Q0l.js.map +0 -1
  278. package/dist/options-CKqyPGxX.js +0 -739
  279. package/dist/options-CKqyPGxX.js.map +0 -1
  280. package/dist/plan-DUydFc_1.js.map +0 -1
  281. package/dist/preflight-BkoSxf4C.js.map +0 -1
  282. package/dist/preflight-D5LW7Oqi.js +0 -2
  283. package/dist/prepare-CUAWHebF.js.map +0 -1
  284. package/dist/prepare-oji2oO8W.js +0 -3
  285. package/dist/provider-BDbNOQhQ.js +0 -2
  286. package/dist/providers-B1DzMvmH.js +0 -107
  287. package/dist/providers-B1DzMvmH.js.map +0 -1
  288. package/dist/providers-CpEfNU1F.js +0 -2
  289. package/dist/query-oPO_XrTy.js +0 -2
  290. package/dist/questions-B8by4Bbt.js +0 -234
  291. package/dist/questions-B8by4Bbt.js.map +0 -1
  292. package/dist/runtime-DdsfnRz_.js.map +0 -1
  293. package/dist/sandbox-D5v-of6d.js +0 -139
  294. package/dist/sandbox-D5v-of6d.js.map +0 -1
  295. package/dist/server-BNnXtmS8.js.map +0 -1
  296. package/dist/server-BNwoKzlm.js +0 -2
  297. package/dist/source-Bk_0ZaEY.js +0 -2
  298. package/dist/src-8rRXy4u9.js.map +0 -1
  299. package/dist/src-BGWuWp6I.js +0 -3
  300. package/dist/src-BRt0O02i.js +0 -3
  301. package/dist/src-Bx2x1ekD.js +0 -3
  302. package/dist/src-C_4Umgh2.js.map +0 -1
  303. package/dist/src-D95O-Smv.js.map +0 -1
  304. package/dist/src-DDNXsD9H.js.map +0 -1
  305. package/dist/src-DLa-ESW0.js +0 -4
  306. package/dist/src-cN0aB-WR.js +0 -3
  307. package/dist/src-cdIVjC5b.js +0 -2
  308. package/dist/src-sIsDHWYq.js +0 -3
  309. package/dist/state-Bo5zg4da.js +0 -2
  310. package/dist/state-CiXyLqg0.js.map +0 -1
  311. package/dist/studio-app/assets/index-B9MCTfuu.css +0 -2
  312. package/dist/summary-BTksrIxn.js.map +0 -1
  313. package/dist/tool-target-BU1JnSE9.js.map +0 -1
  314. package/dist/tools-B10Uj7OI.js.map +0 -1
  315. package/dist/views-Cs2Oqayd.js +0 -3
  316. package/dist/views-Dqa5ojfZ.js.map +0 -1
  317. package/dist/worker-entry-BAikHl9F.js.map +0 -1
  318. package/dist/workspace-Do_SiWBs.js +0 -2
@@ -1,34 +1,42 @@
1
- import { n as UsageError } from "./errors-yDAEwmZo.js";
1
+ import { n as UsageError } from "./errors-B6BSMs03.js";
2
2
  import { a as fromCwd, l as sha256 } from "./ids-Bp6ut7ZD.js";
3
+ import { r as questionShows, t as DEFAULT_QUESTION_STATE } from "./state-CeR6oz0k.js";
3
4
  import { n as clip } from "./text-gEcKjAyp.js";
4
- import { c as resolveAnalysisModel, l as SYSTEM_PROMPT, n as callAnalysisModel, t as analysisModelName } from "./model-B1BZoZ9b.js";
5
- import { t as ANALYSIS_PROMPT_VERSION } from "./analysis-DlGBDjTj.js";
6
- import { dt as compare } from "./model-BOnlAPzs.js";
5
+ import { c as resolveAnalysisModel, l as SYSTEM_PROMPT, n as callAnalysisModel, t as analysisModelName } from "./model-h_cDtcRr.js";
6
+ import { n as formatTokens } from "./usage-CleNKkly.js";
7
+ import { t as ANALYSIS_PROMPT_VERSION } from "./analysis-Bxub9LMT.js";
8
+ import { V as labelledJudgements, yt as compare } from "./model-oqcDplJG.js";
7
9
  import { a as familyLiftLabel, o as familyRateLabel, r as familyEffortLabel } from "./family-D2b7WD10.js";
8
- import { t as runHeader } from "./header-CALhmafp.js";
9
- import { a as sampleReasons } from "./pairs-DDsjgm5F.js";
10
- import { o as parseRecord, p as scratchDir } from "./files-CSzVADHn.js";
11
- import { l as writeCached, o as readCached, s as saveAnalysis } from "./files-DJUFg-4e.js";
12
- import { c as resolveRun, s as pickBaseline, t as RefError } from "./views-Dqa5ojfZ.js";
13
- import { c as lines, n as allRuns, t as CommandError, u as reachability } from "./commands-CLmPBrTS.js";
14
- import { a as commandSummary, i as checkCommand } from "./cli-spec-CKEYa8V2.js";
15
- import { s as openHistoryDb } from "./db-CfQFwJtq.js";
16
- import { t as author } from "./provenance-D7HK3vzt.js";
10
+ import { t as runHeader } from "./header-hK-Z_Po9.js";
11
+ import { n as headToHeadLines, r as pairTallies, s as sampleReasons, u as splitsLabel } from "./pairs-CnInRu-G.js";
12
+ import { o as parseRecord, p as scratchDir } from "./files-BXUdY8tr.js";
13
+ import { g as contrastsOf } from "./summary-BLAVLySU.js";
14
+ import { l as writeCached, o as readCached, s as saveAnalysis } from "./files-DQmHE7pb.js";
15
+ import { c as resolveRun, s as pickBaseline, t as RefError } from "./views-BmQF4UCI.js";
16
+ import { c as lines, n as allRuns, t as CommandError, u as reachability } from "./commands-BFx16WB8.js";
17
+ import { i as checkCommand, o as commandSummary } from "./cli-spec-BPZbQG2p.js";
18
+ import { l as TOOL_CLASSES, s as openHistoryDb } from "./db-CdHizc4_.js";
19
+ import { t as author } from "./provenance-DmE9uPVt.js";
17
20
  import { basename, join } from "node:path";
18
21
  import { readFile } from "node:fs/promises";
19
22
  //#region src/analysis/digest.ts
20
23
  const RULES = [
21
24
  `Lift (variant pass@1 minus control pass@1) is insufficient (not measured, never a results line) when either side has fewer than 2 counted attempts; otherwise it is an effect only when its 95% interval (Newcombe) excludes 0, and within noise when the interval spans 0, whatever the point estimate.`,
22
25
  "When sources or the eval fingerprint differ across the compared runs, the pass@1 difference is not comparable: the eval changed. Never call it an effect. Do not put those mixed counts on a results line. The first line of the analysis says the eval changed. A lift is an effect only when sources match; the two-attempt floor still applies then.",
23
- "Effort (tool calls, agent time, and tokens when both sides have usage samples) is compared with an exact Mann-Whitney test: \"fewer\"/\"more\" at p < 0.05; \"insufficient\" when the attempt counts can never reach it (2 vs 2 cannot) — never because a harness dropped usage. Attempts without usage are left out of the token sample only. If either side then has no token sample, the token metric is omitted (no line, not insufficient). A Goose cell does not blank tokens on Cursor cells in the same study. Pooled across evals, tokens are an effect only when at least 2/3 of the strata that reported usage agree.",
26
+ `Effort (tool calls, agent time, and tokens when both sides have usage samples) is compared with an exact Mann-Whitney test: "fewer"/"more" at p < 0.05; "insufficient" when the attempt counts can never reach it (2 vs 2 cannot) — never because a harness dropped usage. Attempts without usage are left out of the token sample only. If either side then has no token sample, the token metric is omitted (no line, not insufficient). A Goose cell does not blank tokens on Cursor cells in the same study. Pooled across evals, tokens are an effect only when at least 2/3 of the strata that reported usage agree. Effort's separated (given from 3 vs 3) says, per metric, that the two sides' ranges do not overlap: every attempt on one side beat every attempt on the other. insufficient with separated true is a directional signal: report the ratio, the n and "no overlap, not significant" as directional, never as an effect. separated false is no direction at all.`,
24
27
  "A family fact is one pooled evaluate.each: its cases are paired samples of one suite, so its lift (Newcombe paired interval and McNemar at one attempt a case, a t interval over cases otherwise) is the result for those cases; their own pass-rate facts carry no lift. insufficient (fewer than 6 discordant pairs or 6 cases) is not measured. A family's minLift gates the pooled lower bound.",
25
28
  "Each factor claim has a tier: controlled (two cells in one run that differ in one factor), pooled (the same contrast over comparable runs, and across evals), observed (a change between runs, which is weaker; \"confounded\" when several parts changed), not_measured (one level only).",
26
29
  `A cell with mixed outcomes is flaky only with at least 6 counted attempts over comparable runs; below that it is "insufficient", not flaky.`,
27
30
  "Drift marked noise changed only an agent CLI's own runtime state (e.g. ~/.cursor/cli-config.json): not a real change, and those runs stay comparable.",
28
31
  "An eval where every cell passes at least 95% is saturated: pass@1 cannot tell cells apart there, effort can.",
29
32
  "Judge verdicts carry no recorded reason; an explanation of a failed verdict is your reading of the cited output, and must say so.",
33
+ "A criteria fact lists each check (expect label, judges included) per cell: rows only for labels whose rate differs between cells, or is mixed within one; neverMet labels failed on every counted attempt of every cell, alwaysMet passed on all of them. A neverMet or alwaysMet label is the same in every arm: it can't explain a difference between arms.",
34
+ "frame study means every cell in scope is ungated (gate: 'none'): the run measures how its arms differ, so attempts that fail are data, not a failed gate.",
35
+ "setup, rules and cli give context and are not citable: cite facts, evidence and attempts.",
36
+ "A context-use fact counts each attempt's tool calls by class (context, dependency, web, verify, workspace) and lists which placed files each arm opened: how much an arm leaned on what its environment declared versus digging in installed packages. The classes are a heuristic over tool names and paths; cite them as counts, not as proof of intent.",
37
+ "A contrast fact (kind contrast) is one pair of arms on one harness, a against b, when an eval has two variants or more: pass rate and lift of a over b, the checks that tell them apart (discriminates or mixed; sameOnBoth counts the rest) and effort. It answers how two variants differ from each other, not only from the control; gating stays each variant against its control.",
30
38
  "A check (kind checks) whose verdict is both-pass or both-fail passes, or fails, on both the variant and its control: it is no evidence for or against the variant. Only discriminates rows say which requirement separated them.",
31
- "Compare-question win rates annotate the run: they never change pass, fail or the exit code. Cite them as annotation, never as a result that gates the run. A vote's reason is the model's wording: do not treat it as a check."
39
+ "Compare-question win rates annotate the run: they never change pass, fail or the exit code. Cite them as annotation, never as a result that gates the run. A vote's reason is the model's wording: do not treat it as a check. Each pair is voted in both orders; splits counts pairs whose two orders picked opposite sides (the position decided, not the work), and rates count such a pair as one win each. With more than two arms, read headToHead (a–b wins per pair, splits apart), not the pooled rates. shows lists what each side was shown: a question that shows output or transcript can favour the better-written account rather than the better work, and one that shows artifacts rests on screenshots."
32
40
  ];
33
41
  const pts = (x) => x === null || x === void 0 ? null : `${x >= 0 ? "+" : "−"}${Math.round(Math.abs(x) * 100)}`;
34
42
  const liftText = (points, lo, hi) => `${pts(points)} pts (95% ${pts(lo)}…${pts(hi)})`;
@@ -56,7 +64,7 @@ function evalSourcesChanged(base, head) {
56
64
  /** Short tags for the evals in scope: the file's base name, numbered when a file has several. */
57
65
  function evalTags(evals) {
58
66
  const tags = /* @__PURE__ */ new Map();
59
- const bases = evals.map((e) => basename(e.file).replace(/\.(?:eval|es)\.ts$|\.[jt]s$/, ""));
67
+ const bases = evals.map((e) => basename(e.file).replace(/(?:\.\w+)?\.[jt]s$/, ""));
60
68
  evals.forEach((e, i) => {
61
69
  const b = bases[i];
62
70
  const same = bases.filter((x) => x === b).length;
@@ -71,7 +79,91 @@ function cellTags(e) {
71
79
  const prefix = (c) => harnesses.length < 2 ? "" : `${kinds.length === harnesses.length ? c.harnessKind : c.harness}:`;
72
80
  return new Map(e.cells.map((c) => [c.key, `${prefix(c)}${c.variant ?? "control"}`]));
73
81
  }
82
+ /**
83
+ * Cell names for facts: each tag, with a compare's control named by its environment
84
+ * (`no-skill (control)`) so a reading can name the arm. Attempt ids keep the tag.
85
+ */
86
+ function cellNames(e, tags) {
87
+ const compare = e.cells.some((c) => c.role === "variant");
88
+ return new Map(e.cells.map((c) => {
89
+ const tag = tags.get(c.key) ?? c.key;
90
+ const named = compare && c.role === "control" && c.environment && c.environment !== "-";
91
+ return [c.key, named ? tag.replace(/control$/, `${c.environment} (control)`) : tag];
92
+ }));
93
+ }
74
94
  const counted = (a) => a.outcome === "pass" || a.outcome === "fail";
95
+ const LABEL_CHARS = 60;
96
+ const round2 = (x) => Math.round(x * 100) / 100;
97
+ const round1 = (x) => Math.round(x * 10) / 10;
98
+ const ratioText = (r) => r == null ? "×–" : `×${Number(r).toFixed(2)}`;
99
+ /** The labels of an attempt's assertions that failed or couldn't answer. */
100
+ const failedLabels = (a) => (a.assertions ?? []).filter((x) => x.status !== "pass").map((x) => clip(x.label, LABEL_CHARS));
101
+ /** Every counted attempt passed (`all`), none did, or some; undefined when none answered. */
102
+ const sideOf = (t) => {
103
+ const answered = t.pass + t.fail + t.error + t.notRun;
104
+ if (answered === 0) return void 0;
105
+ return t.pass === answered ? "all" : t.pass === 0 ? "none" : "some";
106
+ };
107
+ /** Items interleaved by group, groups in order of first appearance: one from each, then the next. */
108
+ function roundRobin(items, key) {
109
+ const groups = /* @__PURE__ */ new Map();
110
+ for (const item of items) groups.set(key(item), [...groups.get(key(item)) ?? [], item]);
111
+ const out = [];
112
+ for (let i = 0; out.length < items.length; i++) for (const g of groups.values()) if (i < g.length) out.push(g[i]);
113
+ return out;
114
+ }
115
+ /** `study` when every cell in scope is ungated, so the run compares arms rather than gating them. */
116
+ const frameOf = (evals) => {
117
+ const cells = evals.flatMap((e) => e.cells);
118
+ return cells.length && cells.every((c) => c.gate === "none") ? "study" : "gate";
119
+ };
120
+ /**
121
+ * One eval's checks per cell: a row with each cell's rate (and mean judge score) for each label
122
+ * that differs between cells or is mixed within one, and the labels every cell failed, or passed,
123
+ * on every counted attempt.
124
+ */
125
+ function criteriaOf(e, tag) {
126
+ const cells = e.cells.filter((c) => c.checks?.length);
127
+ const labels = [...new Set(cells.flatMap((c) => (c.checks ?? []).map((k) => k.label)))];
128
+ if (!labels.length) return null;
129
+ const scores = /* @__PURE__ */ new Map();
130
+ for (const a of e.attempts) {
131
+ if (!counted(a)) continue;
132
+ for (const j of labelledJudgements(a)) {
133
+ if (j.check === void 0) continue;
134
+ const id = `${a.cell}\0${j.check}`;
135
+ scores.set(id, [...scores.get(id) ?? [], j.judgement.score]);
136
+ }
137
+ }
138
+ const rows = [];
139
+ const neverMet = [];
140
+ const alwaysMet = [];
141
+ for (const label of labels) {
142
+ const tallies = cells.flatMap((c) => {
143
+ const k = c.checks?.find((x) => x.label === label);
144
+ return k ? [{
145
+ c,
146
+ k
147
+ }] : [];
148
+ });
149
+ const sides = new Set(tallies.map(({ k }) => sideOf(k)));
150
+ if (sides.size === 1 && sides.has("none")) neverMet.push(clip(label, LABEL_CHARS));
151
+ else if (sides.size === 1 && sides.has("all")) alwaysMet.push(clip(label, LABEL_CHARS));
152
+ else rows.push({
153
+ label: clip(label, LABEL_CHARS),
154
+ cells: Object.fromEntries(tallies.map(({ c, k }) => {
155
+ const s = scores.get(`${c.key}\0${label}`);
156
+ const mean = s?.length ? ` · ${(s.reduce((x, y) => x + y, 0) / s.length).toFixed(2)}` : "";
157
+ return [tag(c.key), `${k.pass}/${k.pass + k.fail + k.error + k.notRun}${mean}`];
158
+ }))
159
+ });
160
+ }
161
+ return {
162
+ rows,
163
+ neverMet,
164
+ alwaysMet
165
+ };
166
+ }
75
167
  /** The digest, and the evidence dropped from it to fit its cap, whole, for tools to read back. */
76
168
  async function buildDigestKeepingDropped(input) {
77
169
  const { head, base, db } = input;
@@ -80,6 +172,7 @@ async function buildDigestKeepingDropped(input) {
80
172
  const needle = input.evalFilter?.toLowerCase() ?? null;
81
173
  const inScope = (e) => !needle || e.id.toLowerCase().includes(needle);
82
174
  const scopeEvals = head.record.evals.filter(inScope);
175
+ const frame = frameOf(scopeEvals);
83
176
  const tags = evalTags(scopeEvals);
84
177
  const evalKeys = new Set(scopeEvals.map((e) => e.key));
85
178
  const tagOf = (key) => tags.get(key) ?? key;
@@ -90,25 +183,30 @@ async function buildDigestKeepingDropped(input) {
90
183
  for (const r of runs) for (const e of r.record.evals) {
91
184
  if (!evalKeys.has(e.key)) continue;
92
185
  const cells = cellTags(e);
93
- for (const [key, tag] of cells) cellTagOf.set(`${r.record.runId}\0${e.key}\0${key}`, tag);
186
+ const names = cellNames(e, cells);
187
+ for (const [key, name] of names) cellTagOf.set(`${r.record.runId}\0${e.key}\0${key}`, name);
94
188
  for (const a of e.attempts) {
95
189
  const id = `${short.get(r.record.runId)}/${tagOf(e.key)}/${cells.get(a.cell)}#${a.n}`;
96
190
  idOf.set(`${r.record.runId}\0${a.key}`, id);
97
- const judge = a.judgements[0];
98
191
  const any = a.files.transcript ?? a.files.judgeInput ?? a.checks.find((c) => c.log)?.log;
192
+ const assertions = a.assertions ?? [];
193
+ const failed = failedLabels(a);
194
+ const judges = labelledJudgements(a);
99
195
  attempts[id] = {
100
196
  run: short.get(r.record.runId),
101
197
  runId: r.record.runId,
102
198
  key: a.key,
103
199
  eval: tagOf(e.key),
104
200
  evalSlug: e.slug,
105
- cell: cells.get(a.cell),
201
+ cell: names.get(a.cell),
106
202
  attempt: a.id,
107
203
  outcome: a.outcome,
108
204
  tools: a.activity.tools,
109
205
  agentS: Math.round(a.timings.agentMs / 1e3),
110
- ...judge ? { judge: Math.round(judge.score * 100) / 100 } : {},
111
- checks: a.checks.length,
206
+ ...assertions.length ? { checks: `${assertions.filter((x) => x.status === "pass").length}/${assertions.length}` } : {},
207
+ ...failed.length ? { failed } : {},
208
+ ...judges.length ? { judges: Object.fromEntries(judges.map((j) => [clip(j.label, LABEL_CHARS), round2(j.judgement.score)])) } : {},
209
+ execs: a.checks.length,
112
210
  artifacts: any ? `${r.record.runId}/${any.path.split("/").slice(0, 3).join("/")}` : null
113
211
  };
114
212
  }
@@ -155,7 +253,7 @@ async function buildDigestKeepingDropped(input) {
155
253
  cases: f.ran === f.cases ? f.cases : `${f.ran} of ${f.cases}`,
156
254
  rates: f.rates.map((x) => ({
157
255
  cell: cellTag(r.record.runId, member.key, x.cell),
158
- passRate: familyRateLabel(x)
256
+ passAt1: familyRateLabel(x)
159
257
  })),
160
258
  lifts: f.lifts.map((l) => ({
161
259
  cell: cellTag(r.record.runId, member.key, l.variant),
@@ -188,16 +286,27 @@ async function buildDigestKeepingDropped(input) {
188
286
  medianToolCalls: row.tools_median,
189
287
  medianAgentS: row.agent_s_median,
190
288
  ...row.tokens_median != null ? { medianTokens: row.tokens_median } : {},
289
+ ...row.workspace_calls_median != null ? { medianCallsByClass: Object.fromEntries(TOOL_CLASSES.flatMap((k) => {
290
+ const m = row[`${k}_calls_median`];
291
+ return m ? [[k, m]] : [];
292
+ })) } : {},
191
293
  ...row.control_key ? { vsControl: {
192
- toolCalls: `${row.tools_median} vs ${row.control_tools_median} (×${Number(row.tools_ratio).toFixed(2)})`,
193
- agentS: `${row.agent_s_median} vs ${row.control_agent_s_median}`,
294
+ n: `${row.n} vs ${row.control_n}`,
295
+ toolCalls: `${row.tools_median} vs ${row.control_tools_median} (${ratioText(row.tools_ratio)})`,
296
+ agentS: `${row.agent_s_median} vs ${row.control_agent_s_median} (${ratioText(row.agent_s_ratio)})`,
194
297
  p: row.tools_p,
195
298
  verdict: row.verdict,
299
+ timeVerdict: row.time_verdict,
196
300
  ...row.tokens_verdict ? {
197
- tokens: `${row.tokens_median} vs ${row.control_tokens_median} (×${Number(row.tokens_ratio).toFixed(2)})`,
301
+ tokens: `${formatTokens(row.tokens_median)} vs ${formatTokens(row.control_tokens_median)} (${ratioText(row.tokens_ratio)})`,
198
302
  tokensP: row.tokens_p,
199
303
  tokensVerdict: row.tokens_verdict
200
304
  } : {},
305
+ ...Math.min(Number(row.n), Number(row.control_n)) >= 3 ? { separated: {
306
+ tools: row.separated === 1,
307
+ agentS: row.time_separated === 1,
308
+ ...row.tokens_separated != null ? { tokens: row.tokens_separated === 1 } : {}
309
+ } } : {},
201
310
  ...row.tokens_note ? { unreportedUsage: row.tokens_note } : {}
202
311
  } } : {}
203
312
  }))
@@ -215,7 +324,7 @@ async function buildDigestKeepingDropped(input) {
215
324
  OR (tier = 'observed' AND run_id IN (${runList}) AND eval_key IN (${evalList}))
216
325
  OR tier = 'not_measured'
217
326
  ORDER BY CASE tier WHEN 'pooled' THEN 0 WHEN 'controlled' THEN 1 WHEN 'observed' THEN 2 ELSE 3 END,
218
- factor, level, eval_key`).filter((f) => f.tier !== "pooled" || f.factor !== "environment" || harnesses.includes(f.context));
327
+ factor, level, eval_key`).filter((f) => f.tier !== "pooled" || f.factor !== "environment" || f.context !== null && harnesses.includes(f.context));
219
328
  for (const f of factors) {
220
329
  if (!base && (f.tier === "pooled" || f.tier === "observed")) continue;
221
330
  if (f.tier === "not_measured") {
@@ -295,6 +404,51 @@ async function buildDigestKeepingDropped(input) {
295
404
  firstReadAtLines: [...c.lines].sort((a, b) => a - b)
296
405
  }))
297
406
  });
407
+ const classRows = q(`SELECT t.run_id, a.eval_key, a.cell_key, a.n, t.class, COUNT(*) AS calls
408
+ FROM tool_calls t JOIN attempts a ON a.run_id = t.run_id AND a.key = t.attempt_key
409
+ WHERE t.run_id IN (${runList}) AND a.eval_key IN (${evalList}) AND a.outcome IN ('pass', 'fail')
410
+ GROUP BY t.run_id, a.key, t.class ORDER BY t.run_id, a.eval_key, a.cell_key, a.n`);
411
+ const fileRows = q(`SELECT run_id, eval_key, cell_key, path, COUNT(*) AS attempts, SUM(reads > 0) AS read
412
+ FROM skill_files WHERE run_id IN (${runList}) AND eval_key IN (${evalList})
413
+ GROUP BY run_id, eval_key, cell_key, path ORDER BY run_id, eval_key, cell_key, path`);
414
+ const useOf = /* @__PURE__ */ new Map();
415
+ const useEntry = (row) => {
416
+ const id = `${row.run_id}\0${row.eval_key}\0${row.cell_key}`;
417
+ const entry = useOf.get(id) ?? {
418
+ classes: /* @__PURE__ */ new Map(),
419
+ files: []
420
+ };
421
+ useOf.set(id, entry);
422
+ return entry;
423
+ };
424
+ for (const r of classRows) {
425
+ const entry = useEntry(r);
426
+ const per = entry.classes.get(r.class) ?? /* @__PURE__ */ new Map();
427
+ per.set(r.n, r.calls);
428
+ entry.classes.set(r.class, per);
429
+ }
430
+ for (const r of fileRows) useEntry(r).files.push(`${r.path} ${r.read}/${r.attempts}`);
431
+ if (classRows.length) {
432
+ const attemptNs = /* @__PURE__ */ new Map();
433
+ for (const r of classRows) {
434
+ const id = `${r.run_id}\0${r.eval_key}\0${r.cell_key}`;
435
+ attemptNs.set(id, [.../* @__PURE__ */ new Set([...attemptNs.get(id) ?? [], r.n])]);
436
+ }
437
+ fact("context-use", {
438
+ note: "Tool calls per counted attempt by class (context: a placed skill, rules or MCP tool; dependency: node_modules, site-packages, vendor, --help; web; verify: a check command or test/build/lint; workspace: the rest), a heuristic. files: each placed file, opened in k/n attempts.",
439
+ cells: [...useOf].map(([id, u]) => {
440
+ const [runId, evalKey, cellKey] = id.split("\0");
441
+ const ns = (attemptNs.get(id) ?? []).sort((a, b) => a - b);
442
+ return {
443
+ run: short.get(runId),
444
+ eval: tagOf(evalKey),
445
+ cell: cellTag(runId, evalKey, cellKey),
446
+ perAttempt: Object.fromEntries([...u.classes].map(([k, per]) => [k, ns.map((n) => per.get(n) ?? 0).join(" ")])),
447
+ ...u.files.length ? { files: u.files } : {}
448
+ };
449
+ })
450
+ });
451
+ }
298
452
  const pooled = /* @__PURE__ */ new Map();
299
453
  for (const r of runs) for (const e of r.record.evals) {
300
454
  if (!evalKeys.has(e.key)) continue;
@@ -319,46 +473,59 @@ async function buildDigestKeepingDropped(input) {
319
473
  })),
320
474
  saturated
321
475
  });
322
- const judged = runs.flatMap((r) => r.record.evals.filter((e) => evalKeys.has(e.key)).flatMap((e) => e.attempts.flatMap((a) => a.judgements.map((j) => ({
323
- r,
324
- a,
325
- j
326
- })))));
476
+ const differing = /* @__PURE__ */ new Map();
477
+ for (const r of runs) for (const e of r.record.evals) {
478
+ if (!evalKeys.has(e.key)) continue;
479
+ const criteria = criteriaOf(e, (cell) => cellTag(r.record.runId, e.key, cell));
480
+ if (!criteria) continue;
481
+ differing.set(`${r.record.runId}\0${e.key}`, new Set(criteria.rows.map((x) => x.label)));
482
+ fact("criteria", {
483
+ run: short.get(r.record.runId),
484
+ eval: tagOf(e.key),
485
+ note: "Each check (expect label) per cell: passed/counted, then the mean judge score for a judge.",
486
+ ...criteria
487
+ });
488
+ }
489
+ const judged = runs.flatMap((r) => r.record.evals.filter((e) => evalKeys.has(e.key)).flatMap((e) => e.attempts.flatMap((a) => a.judgements)));
327
490
  if (judged.length) fact("judge", {
328
- models: [...new Set(judged.map(({ j }) => j.resolvedModel ?? j.model))],
329
- threshold: [...new Set(judged.map(({ j }) => j.threshold))],
491
+ models: [...new Set(judged.map((j) => j.resolvedModel ?? j.model))],
492
+ threshold: [...new Set(judged.map((j) => j.threshold))],
330
493
  verdicts: judged.length,
331
- pass: judged.filter(({ j }) => j.verdict === "pass").length,
332
- scoresAtLeast098: judged.filter(({ j }) => j.score >= .98).length,
333
- nearThreshold: judged.filter(({ j }) => Math.abs(j.score - j.threshold) <= .1).length,
334
- failures: judged.filter(({ j }) => j.verdict === "fail").map(({ r, a, j }) => ({
335
- attempt: idOf.get(`${r.record.runId}\0${a.key}`),
336
- score: j.score
337
- })),
494
+ pass: judged.filter((j) => j.verdict === "pass").length,
495
+ scoresAtLeast098: judged.filter((j) => j.score >= .98).length,
496
+ nearThreshold: judged.filter((j) => Math.abs(j.score - j.threshold) <= .1).length,
338
497
  reasons: "not recorded"
339
498
  });
340
- const failures = runs.slice().reverse().flatMap((r) => r.record.evals.filter((e) => evalKeys.has(e.key)).flatMap((e) => e.attempts.filter((a) => a.outcome === "fail" || a.outcome === "infra_error").map((a) => ({
499
+ const failures = roundRobin(runs.slice().reverse().flatMap((r) => r.record.evals.filter((e) => evalKeys.has(e.key)).flatMap((e) => e.attempts.filter((a) => a.outcome === "fail" || a.outcome === "infra_error").map((a) => ({
341
500
  r,
342
501
  e,
343
502
  a
344
- }))));
345
- for (const { r, e, a } of failures.slice(0, 8)) {
346
- const j = a.judgements.find((x) => x.verdict === "fail");
503
+ })))), ({ r, e, a }) => `${r.record.runId}\0${e.key}\0${a.cell}`);
504
+ const cellsSeen = /* @__PURE__ */ new Set();
505
+ const failureFacts = frame === "study" ? failures.filter(({ r, e, a }) => {
506
+ const id = `${r.record.runId}\0${e.key}\0${a.cell}`;
507
+ return !cellsSeen.has(id) && !!cellsSeen.add(id);
508
+ }) : failures.slice(0, 8);
509
+ for (const { r, e, a } of failureFacts) {
510
+ const failed = failedLabels(a);
511
+ const judges = labelledJudgements(a).filter((j) => j.judgement.verdict === "fail");
347
512
  fact("failure", {
348
513
  attempt: idOf.get(`${r.record.runId}\0${a.key}`),
349
514
  outcome: a.outcome,
350
515
  errorKind: a.error?.kind ?? null,
351
516
  message: a.error ? clip(a.error.message.split("\n")[0] ?? "", 300) : null,
352
517
  gated: e.cells.find((c) => c.key === a.cell)?.gate !== "none",
353
- ...j ? { judge: {
354
- question: j.question,
355
- score: j.score,
356
- threshold: j.threshold
357
- } } : {},
358
- failingChecks: a.checks.map((c, i) => ({
359
- check: i + 1,
518
+ ...failed.length ? { failed } : {},
519
+ ...judges.length ? { judges: judges.map((j) => ({
520
+ label: clip(j.label, LABEL_CHARS),
521
+ question: clip(j.judgement.question, 300),
522
+ score: j.judgement.score,
523
+ threshold: j.judgement.threshold
524
+ })) } : {},
525
+ failingExecs: a.checks.map((c, i) => ({
526
+ exec: i + 1,
360
527
  exit: c.exitCode,
361
- command: c.command
528
+ command: clip(c.command, 300)
362
529
  })).filter((c) => c.exit !== 0)
363
530
  });
364
531
  }
@@ -411,11 +578,14 @@ async function buildDigestKeepingDropped(input) {
411
578
  for (const a of e.answers ?? []) {
412
579
  const ties = a.votes.filter((v) => v.winner === "tie").length;
413
580
  const reasons = sampleReasons(a.votes);
581
+ const splits = splitsLabel(pairTallies(a.votes));
582
+ const headToHead = headToHeadLines(a.votes);
414
583
  fact("compare-question", {
415
584
  run: short.get(r.record.runId),
416
585
  eval: tagOf(e.key),
417
586
  question: clip(a.question, 120),
418
587
  model: a.resolvedModel ?? a.model,
588
+ shows: questionShows(a.stateOptions ?? DEFAULT_QUESTION_STATE, a.artifacts),
419
589
  votes: a.votes.length,
420
590
  ties,
421
591
  ...a.rates.length ? { rates: a.rates.map((x) => ({
@@ -424,6 +594,8 @@ async function buildDigestKeepingDropped(input) {
424
594
  wins: x.wins,
425
595
  n: x.n
426
596
  })) } : {},
597
+ ...splits ? { splits } : {},
598
+ ...headToHead.length ? { headToHead } : {},
427
599
  ...a.error ? { error: clip(a.error, 200) } : {},
428
600
  ...a.votes.length === 0 && a.error === void 0 ? { note: "no pairs to judge: attempts that failed their checks are left out" } : {},
429
601
  ...reasons.length ? { reasons } : {}
@@ -432,6 +604,47 @@ async function buildDigestKeepingDropped(input) {
432
604
  }
433
605
  for (const r of runs) for (const e of r.record.evals) {
434
606
  if (!evalKeys.has(e.key)) continue;
607
+ const tag = (key) => cellTag(r.record.runId, e.key, key);
608
+ const contrasts = contrastsOf(e);
609
+ for (const x of contrasts) {
610
+ const apart = x.checks.filter((k) => k.verdict === "discriminates" || k.verdict === "mixed");
611
+ const ef = x.effort;
612
+ fact("contrast", {
613
+ run: short.get(r.record.runId),
614
+ eval: tagOf(e.key),
615
+ a: tag(x.a),
616
+ b: tag(x.b),
617
+ ...x.lift ? {
618
+ passRate: `${x.lift.variant.pass}/${x.lift.variant.counted} vs ${x.lift.control.pass}/${x.lift.control.counted}`,
619
+ lift: digestLift(x.lift.variant.counted, x.lift.control.counted, x.lift.points, x.lift.interval.lo, x.lift.interval.hi),
620
+ liftVerdict: digestLiftVerdict(x.lift.variant.counted, x.lift.control.counted, x.lift.withinNoise)
621
+ } : {},
622
+ checks: apart.map((k) => ({
623
+ label: clip(k.label, LABEL_CHARS),
624
+ a: `${k.a.pass}/${k.a.pass + k.a.fail + k.a.notRun}`,
625
+ b: `${k.b.pass}/${k.b.pass + k.b.fail + k.b.notRun}`,
626
+ verdict: k.verdict
627
+ })),
628
+ sameOnBoth: x.checks.length - apart.length,
629
+ ...ef ? { effort: {
630
+ n: `${ef.variant.n} vs ${ef.control.n}`,
631
+ toolCalls: `${ef.variant.tools.median} vs ${ef.control.tools.median} (${ratioText(ef.toolsRatio)})`,
632
+ agentS: `${round1(ef.variant.agentMs.median / 1e3)} vs ${round1(ef.control.agentMs.median / 1e3)} (${ratioText(ef.agentMsRatio)})`,
633
+ verdict: ef.verdict,
634
+ timeVerdict: ef.timeVerdict,
635
+ ...ef.tokensVerdict && ef.variant.tokens && ef.control.tokens ? {
636
+ tokens: `${formatTokens(ef.variant.tokens.median)} vs ${formatTokens(ef.control.tokens.median)} (${ratioText(ef.tokensRatio)})`,
637
+ tokensVerdict: ef.tokensVerdict
638
+ } : {},
639
+ ...Math.min(ef.variant.n, ef.control.n) >= 3 ? { separated: {
640
+ tools: ef.separated,
641
+ agentS: ef.timeSeparated,
642
+ ...ef.tokensSeparated !== null ? { tokens: ef.tokensSeparated } : {}
643
+ } } : {}
644
+ } } : {}
645
+ });
646
+ }
647
+ if (contrasts.length) continue;
435
648
  for (const c of e.cells) {
436
649
  const rows = (c.checks ?? []).filter((k) => k.control && k.verdict);
437
650
  if (!rows.length) continue;
@@ -474,18 +687,29 @@ async function buildDigestKeepingDropped(input) {
474
687
  } catch {}
475
688
  return [];
476
689
  };
477
- for (const { r, e, a } of failures.slice(0, 3)) {
690
+ const discriminating = ({ r, e, a }) => failedLabels(a).some((l) => differing.get(`${r.record.runId}\0${e.key}`)?.has(l));
691
+ const perCell = /* @__PURE__ */ new Map();
692
+ for (const f of failures) {
693
+ const id = `${f.r.record.runId}\0${f.e.key}\0${f.a.cell}`;
694
+ const prev = perCell.get(id);
695
+ if (!prev || !discriminating(prev) && discriminating(f)) perCell.set(id, f);
696
+ }
697
+ for (const [i, { r, e, a }] of [...perCell.values()].slice(0, 6).entries()) {
478
698
  const id = idOf.get(`${r.record.runId}\0${a.key}`);
479
699
  const lines = await lastText(r.record.runId, a);
480
- const j = a.judgements.find((x) => x.verdict === "fail");
481
- if (j) lines.push(`judge question: ${j.question}`, `judge score: ${j.score} (threshold ${j.threshold})`);
482
- for (const [i, c] of a.checks.entries()) {
700
+ const judges = labelledJudgements(a).filter((j) => j.judgement.verdict === "fail");
701
+ for (const { label, judgement: j } of judges) lines.push(`judge ${clip(label, LABEL_CHARS)}: ${j.question}`, `judge score: ${j.score} (threshold ${j.threshold})`);
702
+ for (const x of a.assertions ?? []) {
703
+ if (x.status === "pass" || /(^|\.)toPass$/.test(x.matcher)) continue;
704
+ lines.push(`check ${x.status}: ${clip(x.label, LABEL_CHARS)}: ${clip(x.message ?? "", 300)}`);
705
+ }
706
+ for (const [n, c] of a.checks.entries()) {
483
707
  if (c.exitCode === 0 || !c.log) continue;
484
708
  const log = await readFile(join(r.dir, r.record.runId, ...c.log.path.split("/")), "utf8").catch(() => "");
485
- lines.push(`check ${i + 1} (exit ${c.exitCode}) ${c.command}:`, ...log.trimEnd().split("\n").slice(-15));
709
+ lines.push(`exec ${n + 1} (exit ${c.exitCode}) ${c.command}:`, ...log.trimEnd().split("\n").slice(-15));
486
710
  }
487
- add(`attempt:${id}`, `a failing attempt: its final message${j ? " and the judge question it failed" : ""}`, lines, 1);
488
- if (j) {
711
+ add(`attempt:${id}`, `a failing attempt of ${cellTag(r.record.runId, e.key, a.cell)}: its final message${judges.length ? " and the judge questions it failed" : ""}`, lines, 1);
712
+ if (judges[0] && i < 3) {
489
713
  const twin = e.attempts.find((x) => x.cell === a.cell && x.outcome === "pass");
490
714
  if (twin) add(`attempt:${idOf.get(`${r.record.runId}\0${twin.key}`)}`, `the passing twin of ${id} (same cell): its final message`, await lastText(r.record.runId, twin), 2);
491
715
  }
@@ -505,13 +729,14 @@ async function buildDigestKeepingDropped(input) {
505
729
  }
506
730
  }
507
731
  const digest = {
508
- digestVersion: 8,
732
+ digestVersion: 10,
509
733
  scope: {
510
734
  kind: "run",
511
735
  head: short.get(head.record.runId),
512
736
  base: base ? "r1" : null,
513
737
  evals: input.evalFilter
514
738
  },
739
+ frame,
515
740
  runs: Object.fromEntries(runs.map((r) => [short.get(r.record.runId), {
516
741
  runId: r.record.runId,
517
742
  commit: r.record.git?.sha.slice(0, 7) ?? null,
@@ -640,7 +865,7 @@ function renderText(doc) {
640
865
  }
641
866
  //#endregion
642
867
  //#region src/analysis/validate.ts
643
- const CHECK = /^(.+):check(\d+)$/;
868
+ const EXEC = /^(.+):exec(\d+)$/;
644
869
  const LINE = /^(E\d+):L(\d+)$/;
645
870
  const TRANSCRIPT = /^transcript:(.+)#L(\d+)$/;
646
871
  const normal = (s) => s.replace(/\s+/g, " ").trim().toLowerCase();
@@ -657,21 +882,21 @@ function citations(digest) {
657
882
  if (ids.has(c)) return factText.get(c) ?? evidenceText.get(c) ?? JSON.stringify(digest.attempts[c]);
658
883
  const line = LINE.exec(c);
659
884
  if (line) {
660
- const [, id, n] = line;
885
+ const [, id = "", n = ""] = line;
661
886
  if (!lines.get(id)?.has(Number(n))) return null;
662
887
  return digest.evidence.find((e) => e.id === id)?.lines.find((l) => l.startsWith(`L${n} `)) ?? null;
663
888
  }
664
889
  const transcript = TRANSCRIPT.exec(c);
665
890
  if (transcript) {
666
- const [, attempt, n] = transcript;
891
+ const [, attempt = "", n = ""] = transcript;
667
892
  for (const id of evidenceOf(attempt)) if (lines.get(id)?.has(Number(n))) return resolve(`${id}:L${n}`);
668
893
  return null;
669
894
  }
670
- const check = CHECK.exec(c);
671
- if (check) {
672
- const [, attempt, n] = check;
895
+ const exec = EXEC.exec(c);
896
+ if (exec) {
897
+ const [, attempt = "", n = ""] = exec;
673
898
  const a = digest.attempts[attempt];
674
- return a && Number(n) >= 1 && Number(n) <= a.checks ? JSON.stringify(a) : null;
899
+ return a && Number(n) >= 1 && Number(n) <= a.execs ? JSON.stringify(a) : null;
675
900
  }
676
901
  return null;
677
902
  };
@@ -679,7 +904,7 @@ function citations(digest) {
679
904
  }
680
905
  const ANY_NUMBER = /[−-]?\d+(?:\.\d+)?/g;
681
906
  const FRACTION = /(\d+)\/(\d+)/g;
682
- const ATTEMPT_CITE = /:check\d+$|:L\d+$/;
907
+ const ATTEMPT_CITE = /:exec\d+$|:L\d+$/;
683
908
  /** A decimal in [0, 1]: the form a judge score or threshold takes in the digest. */
684
909
  const looksLikeScore = (raw) => {
685
910
  if (!raw.includes(".")) return false;
@@ -691,23 +916,24 @@ const addScore = (scores, n) => {
691
916
  };
692
917
  /**
693
918
  * Recorded judge scores (and thresholds) on the cited attempt, fact or evidence. The digest stores
694
- * them as `attempt.judge`, `judge: { score, threshold }` on a failure, and `judge score:` lines.
919
+ * them as an attempt's `judges`, a failure's `judges: [{ score, threshold }]`, a criteria row's mean
920
+ * scores, and `judge score:` lines.
695
921
  */
696
922
  function citedJudgeScores(cites, digest) {
697
923
  const scores = [];
698
924
  for (const cite of cites) {
699
925
  const id = cite.trim().replace(/^\[|\]$/g, "").replace(ATTEMPT_CITE, "");
700
- addScore(scores, digest.attempts[id]?.judge);
926
+ for (const s of Object.values(digest.attempts[id]?.judges ?? {})) addScore(scores, s);
701
927
  const fact = digest.facts.find((f) => f.id === id);
702
928
  if (fact) {
703
- const j = fact.judge;
704
- if (typeof j === "number") addScore(scores, j);
705
- else if (j && typeof j === "object") {
706
- addScore(scores, j.score);
707
- addScore(scores, j.threshold);
929
+ if (Array.isArray(fact.judges)) for (const row of fact.judges) {
930
+ if (!row || typeof row !== "object") continue;
931
+ addScore(scores, row.score);
932
+ addScore(scores, row.threshold);
708
933
  }
709
- if (Array.isArray(fact.failures)) {
710
- for (const row of fact.failures) if (row && typeof row === "object") addScore(scores, row.score);
934
+ if (Array.isArray(fact.rows)) for (const row of fact.rows) for (const v of Object.values(row?.cells ?? {})) {
935
+ const mean = / · (\d+(?:\.\d+)?)$/.exec(String(v));
936
+ if (mean) addScore(scores, Number(mean[1]));
711
937
  }
712
938
  if (Array.isArray(fact.threshold)) for (const t of fact.threshold) addScore(scores, t);
713
939
  }
@@ -881,8 +1107,8 @@ async function load(config, entry) {
881
1107
  bytes
882
1108
  };
883
1109
  }
884
- /** The model's input: the digest as JSON, after the project's own instructions. */
885
- const promptOf = (d) => `${d.instructions ? `PROJECT INSTRUCTIONS: ${d.instructions}\n\n` : ""}DIGEST:\n${JSON.stringify(d)}`;
1110
+ /** The model's input: the project's own instructions, which set the question, then the digest as JSON. */
1111
+ const promptOf = (d) => `${d.instructions ? `PROJECT INSTRUCTIONS (the question this analysis answers): ${d.instructions}\n\n` : ""}DIGEST:\n${JSON.stringify(d)}`;
886
1112
  /** `--context`: the same digest and rules, for the user's own coding agent. */
887
1113
  function contextMarkdown(d, head, base) {
888
1114
  return [
@@ -890,6 +1116,13 @@ function contextMarkdown(d, head, base) {
890
1116
  "",
891
1117
  "Analyse this reeval run for the engineer who wrote the evals. The digest below holds facts reeval computed (F…), evidence excerpts (E…, transcript lines as L<n>) and the attempts table. Cite those ids for every claim, keep to the verdicts in the facts, and suggest at most 5 concrete actions, each verified with a reeval command from the CLI list.",
892
1118
  "",
1119
+ ...d.frame === "study" ? ["This run is a study: every cell is ungated (gate: 'none'), so it measures how the arms differ. Failing attempts are data, not a failed gate.", ""] : [],
1120
+ ...d.instructions ? [
1121
+ "## Project instructions (the question this analysis answers)",
1122
+ "",
1123
+ d.instructions,
1124
+ ""
1125
+ ] : [],
893
1126
  "## How reeval decided each verdict",
894
1127
  "",
895
1128
  ...RULES.map((r) => `- ${r}`),
@@ -921,14 +1154,14 @@ function citedSummary(d, cites) {
921
1154
  for (const c of cites) {
922
1155
  const fact = d.facts.find((f) => f.id === c);
923
1156
  const evidence = d.evidence.find((e) => e.id === c || c.startsWith(`${e.id}:`));
924
- const attempt = d.attempts[c.replace(/:check\d+$/, "")];
1157
+ const attempt = d.attempts[c.replace(/:exec\d+$/, "")];
925
1158
  if (fact) {
926
1159
  const { id: _id, ...rest } = fact;
927
1160
  out[c] = clip(JSON.stringify(rest), 400);
928
1161
  } else if (evidence) {
929
1162
  const line = /:L(\d+)$/.exec(c);
930
1163
  out[c] = line ? clip(evidence.lines.find((l) => l.startsWith(`L${line[1]} `)) ?? evidence.ref, 400) : `${evidence.ref}: ${evidence.why}`;
931
- } else if (attempt) out[c] = `${attempt.runId} · ${attempt.attempt} · ${attempt.outcome} · ${attempt.tools} tool calls`;
1164
+ } else if (attempt) out[c] = `${attempt.runId} · ${attempt.attempt} · ${attempt.outcome} · ${attempt.tools} tool calls${attempt.checks ? ` · checks ${attempt.checks}` : ""}`;
932
1165
  }
933
1166
  return out;
934
1167
  }
@@ -996,7 +1229,7 @@ async function prepareAnalysis(config, head, base, evalFilter) {
996
1229
  };
997
1230
  }
998
1231
  const docBase = async (config, p) => ({
999
- kind: "es-analysis",
1232
+ kind: "reeval-analysis",
1000
1233
  schemaVersion: 1,
1001
1234
  scope: p.scope,
1002
1235
  anchor: p.head.runId,
@@ -1146,4 +1379,4 @@ async function analyzeCommand(ctx, args) {
1146
1379
  //#endregion
1147
1380
  export { failedAnalysis as a, defaultBase as i, analyzeCommand as n, prepareAnalysis as o, contextMarkdown as r, promptOf as s, analyseDigest as t };
1148
1381
 
1149
- //# sourceMappingURL=command-DUT5l13I.js.map
1382
+ //# sourceMappingURL=command-Bge8F7Ko.js.map