@hona/openeval 0.2.2 → 0.3.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 (211) hide show
  1. package/JUDGING.md +134 -23
  2. package/README.md +67 -9
  3. package/package.json +3 -2
  4. package/src/app/cost-plan.ts +20 -16
  5. package/src/app/eval-state.ts +2 -1
  6. package/src/app/grade-recording.ts +72 -0
  7. package/src/app/input-fingerprints.ts +22 -8
  8. package/src/app/judge-evidence.ts +26 -11
  9. package/src/app/judge-run.ts +36 -19
  10. package/src/app/load-benchmark.ts +46 -15
  11. package/src/app/read-results.ts +35 -2
  12. package/src/app/read-run.ts +23 -2
  13. package/src/app/rejudge.ts +2 -1
  14. package/src/app/run-benchmark.ts +4 -0
  15. package/src/app/run-eval-pipeline.ts +2 -1
  16. package/src/app/run-eval.ts +13 -0
  17. package/src/app/scores.ts +76 -34
  18. package/src/app/serve-results.ts +2 -0
  19. package/src/evidence.ts +4 -1
  20. package/src/index.ts +15 -3
  21. package/src/infra/evidence/index.ts +39 -2
  22. package/src/infra/evidence/tool-calls.ts +5 -2
  23. package/src/infra/judging/agent.ts +3 -2
  24. package/src/infra/judging/code-result.ts +102 -0
  25. package/src/infra/judging/code-source.ts +96 -0
  26. package/src/infra/judging/code-worker.ts +26 -0
  27. package/src/infra/judging/code.ts +97 -0
  28. package/src/infra/judging/contract.ts +82 -64
  29. package/src/infra/judging/evidence-tool.ts +3 -1
  30. package/src/infra/judging/index.ts +14 -0
  31. package/src/infra/judging/judge-agent.md +24 -18
  32. package/src/infra/judging/observer.ts +8 -7
  33. package/src/infra/judging/submission.ts +8 -8
  34. package/src/infra/judging/tools.ts +9 -9
  35. package/src/infra/opencode/host.ts +1 -1
  36. package/src/infra/opencode/read-recording.ts +6 -1
  37. package/src/infra/opencode/version.ts +1 -0
  38. package/src/infra/recording/index.ts +244 -0
  39. package/src/infra/recording/metrics.ts +193 -0
  40. package/src/infra/sqlite/index.ts +29 -19
  41. package/src/judge-context.ts +141 -0
  42. package/src/judgment.ts +26 -17
  43. package/src/types.ts +36 -17
  44. package/src/view.ts +40 -14
  45. package/viewer/assets/{abnfDiagram-VCTEODGH-B1kcYgQG.js → abnfDiagram-VCTEODGH-rgmalTBh.js} +1 -1
  46. package/viewer/assets/{angular-html-DrYCUiZv.js → angular-html-CcaajvLj.js} +1 -1
  47. package/viewer/assets/{angular-ts-BgjwQn-Z.js → angular-ts-COx6AtG2.js} +1 -1
  48. package/viewer/assets/{apl-DlHqe8o4.js → apl-lBEnC_vz.js} +1 -1
  49. package/viewer/assets/{arc-C4nf7ZoY.js → arc-BQ0cQOwK.js} +1 -1
  50. package/viewer/assets/architecture-7GRP2DOG-DcUKSnYa.js +1 -0
  51. package/viewer/assets/{architectureDiagram-5GKGNRK7-BIWoe0fO.js → architectureDiagram-5GKGNRK7-_XIJP-LV.js} +1 -1
  52. package/viewer/assets/{astro-BrlHnIh9.js → astro-Ca8FrXna.js} +1 -1
  53. package/viewer/assets/{blade-DOcerOiW.js → blade-B07ZVjUX.js} +1 -1
  54. package/viewer/assets/{blockDiagram-I7D4REHJ-C3x13a9m.js → blockDiagram-I7D4REHJ-BdcDRYB-.js} +1 -1
  55. package/viewer/assets/{c-BMbThxEo.js → c-4MsqXzJK.js} +1 -1
  56. package/viewer/assets/{c4Diagram-7LVT6UL2-BeWktchx.js → c4Diagram-7LVT6UL2-E3nvwqBd.js} +1 -1
  57. package/viewer/assets/channel-CViXUg9J.js +1 -0
  58. package/viewer/assets/{chapel-k2cjkSmc.js → chapel-BlwR_8zu.js} +1 -1
  59. package/viewer/assets/{chunk-4HAMMTFA-o6YtJsqE.js → chunk-4HAMMTFA-DN_vtpqx.js} +1 -1
  60. package/viewer/assets/{chunk-75Z2AOVW-KohQa9Nw.js → chunk-75Z2AOVW-DWMGmicp.js} +1 -1
  61. package/viewer/assets/{chunk-DU6HZSFF-C88wxc6m.js → chunk-DU6HZSFF-D2RGHn75.js} +1 -1
  62. package/viewer/assets/{chunk-F27PBJKO-mO4AP2as.js → chunk-F27PBJKO-wfQZ5Ilx.js} +1 -1
  63. package/viewer/assets/{chunk-GMAD6QVW-DzQX2Cld.js → chunk-GMAD6QVW-DrlfUg7k.js} +1 -1
  64. package/viewer/assets/{chunk-GVQU2GXP-CS78RfJD.js → chunk-GVQU2GXP-BHoRLKIU.js} +1 -1
  65. package/viewer/assets/{chunk-IMKFNOWR-DxS42GUo.js → chunk-IMKFNOWR-mxLyQhYU.js} +1 -1
  66. package/viewer/assets/{chunk-L3NEJ4N5-DGo-uYLy.js → chunk-L3NEJ4N5-IpGl-pvp.js} +1 -1
  67. package/viewer/assets/{chunk-OSK3NFVY-BOcXQG16.js → chunk-OSK3NFVY-t0yN50X6.js} +1 -1
  68. package/viewer/assets/{chunk-P2QGCYS3-B7GnZdIQ.js → chunk-P2QGCYS3-BPBYYOcK.js} +1 -1
  69. package/viewer/assets/{chunk-POPQ4Y6H-DgBcYHog.js → chunk-POPQ4Y6H-DIOcv86B.js} +1 -1
  70. package/viewer/assets/{chunk-PWAF6VOD-DpEq6qHA.js → chunk-PWAF6VOD-CqVB-mzq.js} +1 -1
  71. package/viewer/assets/{chunk-SHT3W25Y-CrOGxKM2.js → chunk-SHT3W25Y-DwOEgFIr.js} +1 -1
  72. package/viewer/assets/{chunk-SVP7TREG-4HY7Fljj.js → chunk-SVP7TREG-Dfg1jHc3.js} +1 -1
  73. package/viewer/assets/{chunk-TICWLB2K-B1Rl31EC.js → chunk-TICWLB2K-DE6tQNRu.js} +1 -1
  74. package/viewer/assets/{chunk-XXDRQBXY-CK8giEW-.js → chunk-XXDRQBXY-Bu8dW06M.js} +1 -1
  75. package/viewer/assets/classDiagram-ZZMXUADV-O1Zm0_p8.js +1 -0
  76. package/viewer/assets/classDiagram-v2-VYDZK3BY-O1Zm0_p8.js +1 -0
  77. package/viewer/assets/{cobol-CupUwvw9.js → cobol-BS_DrT-b.js} +1 -1
  78. package/viewer/assets/{coffee-C17pkozF.js → coffee-Clk97ecB.js} +1 -1
  79. package/viewer/assets/{cose-bilkent-JH36ORCC-V1OmrmCv.js → cose-bilkent-JH36ORCC-B3xA8n2e.js} +1 -1
  80. package/viewer/assets/{cpp-BJwVQVXg.js → cpp-aunMdKLY.js} +1 -1
  81. package/viewer/assets/{crystal-BF-oCN-L.js → crystal-B1oihgG5.js} +1 -1
  82. package/viewer/assets/{css-BMgkVI3c.js → css-ClOubSVo.js} +1 -1
  83. package/viewer/assets/{cynefin-OW5HDTMX-BEjY_gsc.js → cynefin-OW5HDTMX-DdEeq9jN.js} +1 -1
  84. package/viewer/assets/{cynefinDiagram-5FMLGOSQ-bfSYgr6z.js → cynefinDiagram-5FMLGOSQ-BwHCV_5V.js} +1 -1
  85. package/viewer/assets/{dagre-GXQ25YYZ-VtwTgGfa.js → dagre-GXQ25YYZ-BkuWRmq-.js} +1 -1
  86. package/viewer/assets/{diagram-S7CK7UJ4-CHaAAyW7.js → diagram-S7CK7UJ4-C5WGyCny.js} +1 -1
  87. package/viewer/assets/{diagram-UQ7AKVKN-CjL65-As.js → diagram-UQ7AKVKN-mdununKH.js} +1 -1
  88. package/viewer/assets/{diagram-VSXAHHWV-Cnxrk1TJ.js → diagram-VSXAHHWV-CpuvU9Ij.js} +1 -1
  89. package/viewer/assets/{diagram-VX7I27RA-D78jPXr7.js → diagram-VX7I27RA-CcLmTPwv.js} +1 -1
  90. package/viewer/assets/{diagram-Z3DM3KII-DKjnOaF2.js → diagram-Z3DM3KII-DWCnKyKY.js} +1 -1
  91. package/viewer/assets/{dist-BTYPW0dz.js → dist-1DE7d697.js} +1 -1
  92. package/viewer/assets/{ebnfDiagram-PWID7BFC-7XiXh5Lx.js → ebnfDiagram-PWID7BFC-9M_-_M-B.js} +1 -1
  93. package/viewer/assets/{edge-B34N_HjN.js → edge-NsPpWeFX.js} +1 -1
  94. package/viewer/assets/{elixir-CQzWMyKD.js → elixir-CXZ4zQTn.js} +1 -1
  95. package/viewer/assets/{elm-BNJiG-wg.js → elm-DVXugwZs.js} +1 -1
  96. package/viewer/assets/{erDiagram-RLTQ6QDP-YPFEgZxU.js → erDiagram-RLTQ6QDP-B2j6iCkZ.js} +1 -1
  97. package/viewer/assets/{erb-D5Rm3UNa.js → erb-h8ybsnSQ.js} +1 -1
  98. package/viewer/assets/eventmodeling-NTZA5JFV-CpMf6avu.js +1 -0
  99. package/viewer/assets/flowDiagram-HODETNUW-DIKEcF1k.js +1 -0
  100. package/viewer/assets/{ganttDiagram-EL5Y4UJY-ergSGtTP.js → ganttDiagram-EL5Y4UJY-CR2QLJ-I.js} +1 -1
  101. package/viewer/assets/{git-rebase-BpIMZIRG.js → git-rebase-CT9f4kn8.js} +1 -1
  102. package/viewer/assets/{gitGraph-4MIJSDKK-CZt4REVj.js → gitGraph-4MIJSDKK-DGw-0dqe.js} +1 -1
  103. package/viewer/assets/{gitGraphDiagram-WWUBYQGX-h9QMzC2r.js → gitGraphDiagram-WWUBYQGX-BW112jVV.js} +1 -1
  104. package/viewer/assets/{glimmer-js-SeSwns5_.js → glimmer-js-B17pi1gL.js} +1 -1
  105. package/viewer/assets/{glimmer-ts-BExI5tTz.js → glimmer-ts-CNmwRbOn.js} +1 -1
  106. package/viewer/assets/{glsl-CXikKw2b.js → glsl-By4kbzYa.js} +1 -1
  107. package/viewer/assets/{graphql-6GpQIInt.js → graphql-BrDJs0bG.js} +1 -1
  108. package/viewer/assets/{hack-i7rizvpB.js → hack-NosEIqRi.js} +1 -1
  109. package/viewer/assets/{haml-C68gmkTf.js → haml-B-GQD8Zj.js} +1 -1
  110. package/viewer/assets/{handlebars-BBn_c0Xt.js → handlebars-1vSTccT5.js} +1 -1
  111. package/viewer/assets/{html-BObmAZQA.js → html-BBEodwWE.js} +1 -1
  112. package/viewer/assets/{html-derivative-BjMuR1LM.js → html-derivative-ClDEAvlc.js} +1 -1
  113. package/viewer/assets/{http-BJBk8gt0.js → http-I0uH89QQ.js} +1 -1
  114. package/viewer/assets/{hurl-D7obCYfg.js → hurl-JU97iWqA.js} +1 -1
  115. package/viewer/assets/{index-FMtYXcX7.js → index-CXBRQlCH.js} +5 -5
  116. package/viewer/assets/{index-Wz0qQyIk.css → index-D6HZB4Yz.css} +1 -1
  117. package/viewer/assets/{info-A6RAGUB7-CrzitQIU.js → info-A6RAGUB7-aRrZ0_i2.js} +1 -1
  118. package/viewer/assets/{infoDiagram-27XIBGKW-D2CgRDxu.js → infoDiagram-27XIBGKW-BnD3mUdL.js} +1 -1
  119. package/viewer/assets/{ishikawaDiagram-5VMMS53U-BhnQMHOo.js → ishikawaDiagram-5VMMS53U-u-wcafFg.js} +1 -1
  120. package/viewer/assets/{java-5VJU_EW8.js → java-BxAxXJLN.js} +1 -1
  121. package/viewer/assets/{javascript-r8UgndxQ.js → javascript-DNepMMwm.js} +1 -1
  122. package/viewer/assets/{jinja-BY2ibHG5.js → jinja-CfKdKg9T.js} +1 -1
  123. package/viewer/assets/{jison-C_7YxymZ.js → jison-C62ElGA9.js} +1 -1
  124. package/viewer/assets/{journeyDiagram-3NMN7TZE-DSBzKQEa.js → journeyDiagram-3NMN7TZE-E6uhr_fk.js} +1 -1
  125. package/viewer/assets/{json-8e1WlJYD.js → json-DSQqeQzH.js} +1 -1
  126. package/viewer/assets/{jsx-BYp5GD4Y.js → jsx-CpZi9Ceb.js} +1 -1
  127. package/viewer/assets/{julia-Bkob1uVX.js → julia-CypyJgFE.js} +1 -1
  128. package/viewer/assets/{just-CUnSjty-.js → just-_p8XAy70.js} +1 -1
  129. package/viewer/assets/{kanban-definition-UXKFOSKX-CotbrQue.js → kanban-definition-UXKFOSKX-Blo6hDj7.js} +1 -1
  130. package/viewer/assets/{latex-UdE3ivqk.js → latex-Blby6_jP.js} +1 -1
  131. package/viewer/assets/{line-DDh6a6hz.js → line-CQc5Trjj.js} +1 -1
  132. package/viewer/assets/{linear-BxMsCbKb.js → linear-BjWjnaEC.js} +1 -1
  133. package/viewer/assets/{liquid-WL4MvEIT.js → liquid-x3m9Bx2x.js} +1 -1
  134. package/viewer/assets/{lua-CtOubZta.js → lua-Da9XAgwV.js} +1 -1
  135. package/viewer/assets/{marko-C0GSQJi3.js → marko-Gu1d_h3t.js} +1 -1
  136. package/viewer/assets/{mdc-DUivddFc.js → mdc-CM0pUbEe.js} +1 -1
  137. package/viewer/assets/{mermaid-parser.core-FhKE_uv2.js → mermaid-parser.core-DR191xUW.js} +3 -3
  138. package/viewer/assets/{mermaid.core-BSOWwyvd.js → mermaid.core-DnwMH2U1.js} +4 -4
  139. package/viewer/assets/{mindmap-definition-YA3MSWOX-tsLZ_Opn.js → mindmap-definition-YA3MSWOX-KrnPcZeq.js} +1 -1
  140. package/viewer/assets/{nginx-B__INAtC.js → nginx-DAKCD0HY.js} +1 -1
  141. package/viewer/assets/{nim-UEY12GJF.js → nim-BvNTuhqF.js} +1 -1
  142. package/viewer/assets/{org-DDIZsz95.js → org-B-tOc6Cc.js} +1 -1
  143. package/viewer/assets/{packet-AYTQ26CC-CqdJnqfo.js → packet-AYTQ26CC-Cl2KBEou.js} +1 -1
  144. package/viewer/assets/{pegDiagram-XKGWAZYB-BJs7qu7m.js → pegDiagram-XKGWAZYB--GvmNzTl.js} +1 -1
  145. package/viewer/assets/{perl-D5KwNZt7.js → perl-RyNpCOE-.js} +1 -1
  146. package/viewer/assets/{php-BEs7d_Dk.js → php-D5gke6Nh.js} +1 -1
  147. package/viewer/assets/{pie-WAS4IAKB-lgzqBWqy.js → pie-WAS4IAKB-RfZPDbVI.js} +1 -1
  148. package/viewer/assets/{pieDiagram-E7YTZNPT-Cxe9LnnE.js → pieDiagram-E7YTZNPT-BbcD9IEY.js} +1 -1
  149. package/viewer/assets/{pug-B0dsfQOV.js → pug-CSZdPWzF.js} +1 -1
  150. package/viewer/assets/{qml-XPIhrIzf.js → qml-CCUSNo18.js} +1 -1
  151. package/viewer/assets/{quadrantDiagram-AXDQQJYC-D5JGwC11.js → quadrantDiagram-AXDQQJYC-DHP-nbSh.js} +1 -1
  152. package/viewer/assets/{r-C6hQdpIM.js → r-Cl6F5Lf8.js} +1 -1
  153. package/viewer/assets/{radar-RG4KPBEZ-B7JRLhUA.js → radar-RG4KPBEZ-DdfC1yOQ.js} +1 -1
  154. package/viewer/assets/{railroad-74A4TZTK-Df7ZQBLn.js → railroad-74A4TZTK-MHxcKgVS.js} +1 -1
  155. package/viewer/assets/railroad-abnf-HS5TGJTU-yEJXYTCu.js +1 -0
  156. package/viewer/assets/railroad-ebnf-LZEXJU2U-CEc058YK.js +1 -0
  157. package/viewer/assets/railroad-peg-WCYAUIDC-0iFSHGbV.js +1 -0
  158. package/viewer/assets/{railroadDiagram-O6MQD6OU-DZJzpmP8.js → railroadDiagram-O6MQD6OU-sxdxPqy-.js} +1 -1
  159. package/viewer/assets/{razor-C3KSUuOw.js → razor-hm0vLE-h.js} +1 -1
  160. package/viewer/assets/{regexp-n-T936Rk.js → regexp-BhIot3VY.js} +1 -1
  161. package/viewer/assets/{requirementDiagram-BXWQKSXE-Be9lEFrk.js → requirementDiagram-BXWQKSXE-CrZXt7Yu.js} +1 -1
  162. package/viewer/assets/{rst-fVnHDyXD.js → rst-C3giCu1C.js} +1 -1
  163. package/viewer/assets/{ruby-DuRgxlXF.js → ruby-B6fOYc5V.js} +1 -1
  164. package/viewer/assets/{sankeyDiagram-P5KCCOFB-BsgKAEBN.js → sankeyDiagram-P5KCCOFB-BVK_LjzN.js} +1 -1
  165. package/viewer/assets/{sas-C0WA2OFa.js → sas-a9NUQlsy.js} +1 -1
  166. package/viewer/assets/{scss-CQDZ4smR.js → scss-ChVMSp7G.js} +1 -1
  167. package/viewer/assets/{sequenceDiagram-WJ2MYXX4-BkUDWL0D.js → sequenceDiagram-WJ2MYXX4-B4E1wY9a.js} +1 -1
  168. package/viewer/assets/{shellscript-CE84G0GP.js → shellscript-Dxbnxou2.js} +1 -1
  169. package/viewer/assets/{shellsession-BdJvdaqL.js → shellsession-DWcRFAj_.js} +1 -1
  170. package/viewer/assets/{soy-BSxOREC0.js → soy-C-D-pvKx.js} +1 -1
  171. package/viewer/assets/{sql-D4MN9uRI.js → sql-W7nl9Rxy.js} +1 -1
  172. package/viewer/assets/{src-BT_kESTA.js → src-C_D1vmKd.js} +1 -1
  173. package/viewer/assets/{stata-B6nXAaGV.js → stata-BWq3CAeQ.js} +1 -1
  174. package/viewer/assets/{stateDiagram-D77RDMKH-C80wp8xG.js → stateDiagram-D77RDMKH-Dc8nXUDp.js} +1 -1
  175. package/viewer/assets/stateDiagram-v2-MP3YSRHH-SMxxOURe.js +1 -0
  176. package/viewer/assets/{surrealql-fVjZmhV3.js → surrealql-BkXUcx4E.js} +1 -1
  177. package/viewer/assets/{svelte-DnBQ5p7d.js → svelte-CowGUt9l.js} +1 -1
  178. package/viewer/assets/{swimlanes-42K2YHIH-Cff6yT8e.js → swimlanes-42K2YHIH-BtZAMLQ7.js} +1 -1
  179. package/viewer/assets/swimlanesDiagram-VR7AAH4N-C_XphOba.js +8 -0
  180. package/viewer/assets/{templ-TCx51Uts.js → templ-ejLYfFxc.js} +1 -1
  181. package/viewer/assets/{tex-CF6SMAQ_.js → tex-McefVK6r.js} +1 -1
  182. package/viewer/assets/{timeline-definition-24CTP7MA-Cje7BvaN.js → timeline-definition-24CTP7MA-TvSh-paH.js} +1 -1
  183. package/viewer/assets/{treeView-Q6P3EWNA-D-QLY3IO.js → treeView-Q6P3EWNA-BRIxIFdd.js} +1 -1
  184. package/viewer/assets/{treemap-WGGIJYW6-BCHcTa4N.js → treemap-WGGIJYW6-CeY__ApH.js} +1 -1
  185. package/viewer/assets/{ts-tags-BqLRnADX.js → ts-tags-D8LHJIWj.js} +1 -1
  186. package/viewer/assets/{tsx-D7KpDX0b.js → tsx-BkPshBHh.js} +1 -1
  187. package/viewer/assets/{twig-CEZLObpN.js → twig-CmfWCxbk.js} +1 -1
  188. package/viewer/assets/{typescript-DAbIDLbf.js → typescript-DnVmzADb.js} +1 -1
  189. package/viewer/assets/{typst-CqN7-whv.js → typst-BpEOIbiv.js} +1 -1
  190. package/viewer/assets/{vennDiagram-4TSXK5OY-Bz20rx02.js → vennDiagram-4TSXK5OY-Ba-jimVX.js} +1 -1
  191. package/viewer/assets/{vue-html-DQmvvKbd.js → vue-html-C-XYg42q.js} +1 -1
  192. package/viewer/assets/{vue-vine-Did3qTVW.js → vue-vine-DK68dTen.js} +1 -1
  193. package/viewer/assets/{vue-kTxN6wdc.js → vue-zII4ln6o.js} +1 -1
  194. package/viewer/assets/{wardley-WFR3VGLG-CpXaqOit.js → wardley-WFR3VGLG-e2A2dYzM.js} +1 -1
  195. package/viewer/assets/{wardleyDiagram-VM6X3IG4-Cz06jHpA.js → wardleyDiagram-VM6X3IG4-D2Rq1FsU.js} +1 -1
  196. package/viewer/assets/{xml-te2hFcAA.js → xml-Cc-dIbaq.js} +1 -1
  197. package/viewer/assets/{xsl-X4fuKSVl.js → xsl-C7A6UsbO.js} +1 -1
  198. package/viewer/assets/{xychartDiagram-S5SC5T6Z-BXCw0sfu.js → xychartDiagram-S5SC5T6Z-De55Qsdg.js} +1 -1
  199. package/viewer/assets/{yaml-NHtDSZab.js → yaml-BJLNLIRM.js} +1 -1
  200. package/viewer/index.html +2 -2
  201. package/viewer/assets/architecture-7GRP2DOG-Be250VKZ.js +0 -1
  202. package/viewer/assets/channel-DtULXRee.js +0 -1
  203. package/viewer/assets/classDiagram-ZZMXUADV-Bmqu01Xf.js +0 -1
  204. package/viewer/assets/classDiagram-v2-VYDZK3BY-Bmqu01Xf.js +0 -1
  205. package/viewer/assets/eventmodeling-NTZA5JFV-CJCg5f6p.js +0 -1
  206. package/viewer/assets/flowDiagram-HODETNUW-BFzq4Zvs.js +0 -1
  207. package/viewer/assets/railroad-abnf-HS5TGJTU-Z8q3QVTf.js +0 -1
  208. package/viewer/assets/railroad-ebnf-LZEXJU2U-BWoRkG3W.js +0 -1
  209. package/viewer/assets/railroad-peg-WCYAUIDC-BzoV1cN7.js +0 -1
  210. package/viewer/assets/stateDiagram-v2-MP3YSRHH-CYdsKKlz.js +0 -1
  211. package/viewer/assets/swimlanesDiagram-VR7AAH4N-niTUGjMT.js +0 -8
@@ -1,22 +1,20 @@
1
1
  import { resolve, relative } from "node:path";
2
2
  import type { EvalRun, JudgeRun } from "../types";
3
3
  import type { ExecutionContext } from "./context";
4
- import { executeJudge } from "../infra/judging";
4
+ import { gradeRecording } from "./grade-recording";
5
5
  import { errorMessage } from "../infra/files";
6
6
  import { canJudgeEval } from "./eval-state";
7
7
  import { JUDGE_PROTOCOL } from "../judgment";
8
8
  import { JUDGE_AGENT } from "../infra/judging/agent";
9
9
 
10
- /** A new judge session references existing evidence and becomes active only after success. */
10
+ /** A new grading execution becomes active only after all present judges succeed. */
11
11
  export async function judgeEvalRun(
12
12
  context: ExecutionContext,
13
13
  candidate: EvalRun,
14
14
  monitoring: Pick<JudgeRun, "monitorError" | "monitorErrorAt"> = {},
15
15
  ): Promise<JudgeRun> {
16
16
  if (!canJudgeEval(candidate))
17
- throw new Error(
18
- "Judging requires finalized evidence from a completed, stopped, or timed-out eval run",
19
- );
17
+ throw new Error("Judging requires finalized candidate evidence");
20
18
  const slot = context.results.slot(candidate.slotId)!;
21
19
  const definition = context.definition.evals.find(
22
20
  (item) => item.id === slot.evalId,
@@ -25,20 +23,22 @@ export async function judgeEvalRun(
25
23
  evalRunId: candidate.id,
26
24
  evidence: candidate.evidence,
27
25
  rubric: definition.judge,
28
- agent: JUDGE_AGENT,
29
- model: context.definition.judge.model,
26
+ agent: definition.judge ? JUDGE_AGENT : undefined,
27
+ model: definition.judge ? context.definition.judge.model : undefined,
28
+ kind: definition.code ? (definition.judge ? "hybrid" : "code") : "llm",
29
+ code: definition.code,
30
30
  judgeHash: slot.judgeHash,
31
31
  timeoutMs: context.definition.judge.timeoutMs,
32
32
  websearch: context.definition.judge.websearch,
33
33
  mode: "final",
34
34
  runtimeHash: context.runtime.judgeHash,
35
35
  protocol: JUDGE_PROTOCOL,
36
- metrics: definition.metrics,
36
+ criteria: definition.criteria,
37
37
  });
38
38
  const directory = resolve(context.directory, "judge-runs", run.id);
39
39
  let completed: JudgeRun;
40
40
  try {
41
- const { result, session, judgment } = await executeJudge(
41
+ const graded = await gradeRecording(
42
42
  {
43
43
  ...run.input,
44
44
  evidence: {
@@ -46,6 +46,14 @@ export async function judgeEvalRun(
46
46
  directory: resolve(context.directory, run.input.evidence.directory),
47
47
  },
48
48
  },
49
+ {
50
+ evidence: {
51
+ ...candidate.evidence,
52
+ directory: resolve(context.directory, candidate.evidence.directory),
53
+ },
54
+ run: candidate,
55
+ runDirectory: context.directory,
56
+ },
49
57
  directory,
50
58
  (event) => {
51
59
  const record = {
@@ -61,16 +69,25 @@ export async function judgeEvalRun(
61
69
  completed = {
62
70
  ...run,
63
71
  ...monitoring,
64
- state: result.state,
65
- judgment,
66
- session: {
67
- ...session,
68
- database: relative(
69
- context.directory,
70
- resolve(directory, session.database),
71
- ),
72
- },
73
- error: result.error,
72
+ state: graded.state,
73
+ judgment: graded.judgment,
74
+ code: graded.code
75
+ ? {
76
+ ...graded.code,
77
+ stdout: relative(context.directory, graded.code.stdout),
78
+ stderr: relative(context.directory, graded.code.stderr),
79
+ }
80
+ : undefined,
81
+ session: graded.session
82
+ ? {
83
+ ...graded.session,
84
+ database: relative(
85
+ context.directory,
86
+ resolve(directory, graded.session.database),
87
+ ),
88
+ }
89
+ : undefined,
90
+ error: graded.error,
74
91
  completedAt: new Date().toISOString(),
75
92
  elapsedMs: Date.now() - Date.parse(run.startedAt),
76
93
  };
@@ -9,7 +9,8 @@ import type {
9
9
  ModelRef,
10
10
  } from "../types";
11
11
  import { CANDIDATE_TIMEOUT_MS } from "../types";
12
- import { rubricMetrics } from "../judgment";
12
+ import { rubricCriteria } from "../judgment";
13
+ import { compileCodeJudge } from "../infra/judging/code-source";
13
14
  import { monitorPolicy } from "./monitor-policy";
14
15
  import {
15
16
  fingerprint,
@@ -41,9 +42,14 @@ async function declaration<T>(path: string): Promise<T> {
41
42
  async function loadEval(directory: string): Promise<EvalDefinition> {
42
43
  const id = basename(directory),
43
44
  prompt = Bun.file(resolve(directory, "prompt.md")),
44
- judge = Bun.file(resolve(directory, "judge.md"));
45
- if (!(await prompt.exists()) || !(await judge.exists()))
46
- throw new Error(`${id} requires prompt.md and judge.md`);
45
+ judge = Bun.file(resolve(directory, "judge.md")),
46
+ codeFile = resolve(directory, "judge.ts");
47
+ const hasMarkdown = await judge.exists(),
48
+ hasCode = await Bun.file(codeFile).exists();
49
+ if (!(await prompt.exists()) || (!hasMarkdown && !hasCode))
50
+ throw new Error(
51
+ `${id} requires prompt.md and at least one of judge.md or judge.ts`,
52
+ );
47
53
  const settings = (await Bun.file(resolve(directory, "eval.ts")).exists())
48
54
  ? await declaration<Eval>(resolve(directory, "eval.ts"))
49
55
  : {};
@@ -56,6 +62,10 @@ async function loadEval(directory: string): Promise<EvalDefinition> {
56
62
  )
57
63
  throw new Error(`${id}/eval.ts has unsupported settings`);
58
64
  monitorPolicy(settings.earlyStop);
65
+ if (hasCode && settings.earlyStop)
66
+ throw new Error(
67
+ `${id}: judge.ts grades finalized recordings; earlyStop requires a Markdown-only judge`,
68
+ );
59
69
  const source: unknown[] = [];
60
70
  if (settings.workspace) {
61
71
  const workspace = settings.workspace;
@@ -157,9 +167,10 @@ async function loadEval(directory: string): Promise<EvalDefinition> {
157
167
  throw new Error(`${id}: preparation requires argv`);
158
168
  }
159
169
  const promptText = await prompt.text(),
160
- judgeText = await judge.text();
161
- if (!promptText.trim() || !judgeText.trim())
170
+ judgeText = hasMarkdown ? await judge.text() : "";
171
+ if (!promptText.trim() || (hasMarkdown && !judgeText.trim()))
162
172
  throw new Error(`${id}: prompt and judge must not be empty`);
173
+ const code = hasCode ? await compileCodeJudge(codeFile) : undefined;
163
174
  return {
164
175
  id,
165
176
  directory,
@@ -170,8 +181,9 @@ async function loadEval(directory: string): Promise<EvalDefinition> {
170
181
  settings: { workspace: settings.workspace, prepare: settings.prepare },
171
182
  source,
172
183
  }),
173
- judgeHash: hash(judgeText),
174
- metrics: rubricMetrics(judgeText),
184
+ judgeHash: fingerprint({ rubric: judgeText, code: code?.hash }),
185
+ criteria: hasMarkdown ? rubricCriteria(judgeText) : [],
186
+ ...(code ? { code } : {}),
175
187
  name: /^# (.+)$/m.exec(judgeText)?.[1] ?? id,
176
188
  };
177
189
  }
@@ -187,10 +199,9 @@ export async function loadBenchmark(
187
199
  if (
188
200
  !definition ||
189
201
  !Array.isArray(definition.models) ||
190
- !definition.models.length ||
191
- !definition.judge
202
+ !definition.models.length
192
203
  )
193
- throw new Error("benchmark.ts requires models and a judge");
204
+ throw new Error("benchmark.ts requires models");
194
205
  if (
195
206
  Object.keys(definition).some(
196
207
  (key) =>
@@ -207,6 +218,18 @@ export async function loadBenchmark(
207
218
  )
208
219
  throw new Error("benchmark.ts contains unsupported settings");
209
220
  const models = definition.models.map(modelRef);
221
+ if (
222
+ definition.judge !== undefined &&
223
+ (!definition.judge ||
224
+ typeof definition.judge !== "object" ||
225
+ Array.isArray(definition.judge) ||
226
+ Object.keys(definition.judge).some(
227
+ (key) => !["model", "timeoutMs", "websearch"].includes(key),
228
+ ))
229
+ )
230
+ throw new Error(
231
+ "judge must be an object with model, timeoutMs, or websearch settings",
232
+ );
210
233
  if (new Set(models).size !== models.length)
211
234
  throw new Error("Benchmark contains duplicate models");
212
235
  const timeoutMs = positive(
@@ -224,6 +247,8 @@ export async function loadBenchmark(
224
247
  const evals = await Promise.all(
225
248
  directories.map((entry) => loadEval(resolve(evalRoot, entry.name))),
226
249
  );
250
+ if (evals.some((item) => item.judge) && !definition.judge?.model)
251
+ throw new Error("A benchmark containing judge.md requires judge.model");
227
252
  const concurrency = positive(definition.concurrency, 10, "Concurrency");
228
253
  if (concurrency < 2 && evals.some((item) => item.settings.earlyStop))
229
254
  throw new Error(
@@ -234,7 +259,7 @@ export async function loadBenchmark(
234
259
  throw new Error("Container engine must be docker or podman");
235
260
  for (const search of [
236
261
  definition.candidate?.websearch,
237
- definition.judge.websearch,
262
+ definition.judge?.websearch,
238
263
  ])
239
264
  if (search !== undefined && search !== false && search !== "exa")
240
265
  throw new Error("Websearch must be exa or false");
@@ -253,9 +278,15 @@ export async function loadBenchmark(
253
278
  : {}),
254
279
  },
255
280
  judge: {
256
- model: modelRef(definition.judge.model),
257
- timeoutMs: positive(definition.judge.timeoutMs, 600_000, "Judge timeout"),
258
- websearch: definition.judge.websearch ?? "exa",
281
+ ...(definition.judge?.model
282
+ ? { model: modelRef(definition.judge.model) }
283
+ : {}),
284
+ timeoutMs: positive(
285
+ definition.judge?.timeoutMs,
286
+ 600_000,
287
+ "Judge timeout",
288
+ ),
289
+ websearch: definition.judge?.websearch ?? "exa",
259
290
  },
260
291
  container: {
261
292
  engine,
@@ -26,6 +26,7 @@ import {
26
26
  } from "../runtime";
27
27
  import { canJudgeEval } from "./eval-state";
28
28
  import { CandidateEvidence, type EvidenceQuery } from "../infra/evidence";
29
+ import { contained } from "../infra/files";
29
30
 
30
31
  const scheduled = (slot: Slot, benchmark: BenchmarkRun, now: number) =>
31
32
  benchmark.state === "running" &&
@@ -33,6 +34,8 @@ const scheduled = (slot: Slot, benchmark: BenchmarkRun, now: number) =>
33
34
  benchmark.scheduledSlotIds.includes(slot.id);
34
35
 
35
36
  const costOf = (run: EvalRun | JudgeRun, results?: Results): Cost => {
37
+ if ("evalRunId" in run.input && run.input.kind === "code")
38
+ return { usd: 0, reportedUSD: 0, complete: true };
36
39
  const usd = run.session?.accounting?.costUSD;
37
40
  return {
38
41
  usd: usd ?? null,
@@ -162,6 +165,21 @@ export class ResultReader {
162
165
  using results = await this.database(benchmarkId);
163
166
  const judge = results.judgeRun(judgeRunId);
164
167
  if (!judge) throw new Error("Unknown judge run");
168
+ const candidate = results.evalRun(judge.input.evalRunId);
169
+ const criteria = new Map(
170
+ judge.input.criteria.map((criterion) => [criterion.id, criterion]),
171
+ );
172
+ for (const id of Object.keys(judge.judgment?.scores ?? {}))
173
+ if (!criteria.has(id))
174
+ criteria.set(id, { id, name: id.replaceAll("_", " ") });
175
+ const log = async (path?: string) =>
176
+ path
177
+ ? (
178
+ await Bun.file(contained(dirname(results.path), path))
179
+ .text()
180
+ .catch(() => "")
181
+ ).slice(0, 40_000)
182
+ : undefined;
165
183
  return {
166
184
  judge: {
167
185
  id: judge.id,
@@ -172,8 +190,15 @@ export class ResultReader {
172
190
  monitorErrorAt: judge.monitorErrorAt,
173
191
  monitorLimit: judge.monitorLimit,
174
192
  judgment: judge.judgment,
193
+ code: judge.code,
194
+ error: judge.error,
175
195
  },
176
- metrics: judge.input.metrics,
196
+ kind: judge.input.kind,
197
+ criteria: [...criteria.values()],
198
+ metrics: candidate?.metrics ?? judge.code?.metrics,
199
+ codeSource: judge.input.code?.source,
200
+ codeStdout: await log(judge.code?.stdout),
201
+ codeStderr: await log(judge.code?.stderr),
177
202
  stop: results.evalRun(judge.input.evalRunId)?.stop,
178
203
  checks: results.judgeChecks(judgeRunId).map((check) => {
179
204
  const start = timestampMs(check.executionStartedAt);
@@ -421,6 +446,7 @@ function stageState(
421
446
  runtime,
422
447
  cost: costOf(run, results),
423
448
  message: run.error,
449
+ ...("kind" in run.input ? { kind: run.input.kind } : {}),
424
450
  };
425
451
  }
426
452
 
@@ -470,6 +496,13 @@ function liveRun(
470
496
  evalStage.status,
471
497
  );
472
498
  const judgeStage: StageState = {
499
+ kind: benchmark.definition.evals.find((item) => item.id === slot.evalId)
500
+ ?.code
501
+ ? benchmark.definition.evals.find((item) => item.id === slot.evalId)
502
+ ?.judge
503
+ ? "hybrid"
504
+ : "code"
505
+ : "llm",
473
506
  ...stageState(
474
507
  judge,
475
508
  stale,
@@ -486,7 +519,7 @@ function liveRun(
486
519
  ...(judge?.state === "completed"
487
520
  ? {
488
521
  score: judge.judgment?.value ?? null,
489
- metrics: judge.judgment?.metrics,
522
+ scores: judge.judgment?.scores,
490
523
  }
491
524
  : {}),
492
525
  };
@@ -4,6 +4,8 @@ import { CandidateEvidence } from "../infra/evidence";
4
4
  import type { EvidenceRef, Judgment } from "../types";
5
5
  import type { EvidenceView } from "../evidence";
6
6
  import { validateCitations } from "../infra/judging/contract";
7
+ import { openRecording } from "../infra/recording";
8
+ import { tmpdir } from "node:os";
7
9
 
8
10
  /** Read-only records for maintenance clients. Finalized evidence remains authoritative. */
9
11
  export function readBenchmarkRun(directory: string) {
@@ -29,7 +31,26 @@ export async function readEvidence(
29
31
  return (await CandidateEvidence.open(ref.directory, ref.hash)).view(ref);
30
32
  }
31
33
 
32
- /** Reference integrity only; interpretation of task facts stays in judge.md. */
34
+ /** Open all recorded data with lazy native readers; dispose after inspection. */
35
+ export async function readRecording(directory: string, evalRunId: string) {
36
+ using results = new Results(resolve(directory, "runner.db"), true);
37
+ const run = results.evalRun(evalRunId);
38
+ if (!run?.evidence)
39
+ throw new Error("Select an EvalRun with finalized evidence");
40
+ return openRecording(
41
+ {
42
+ run,
43
+ runDirectory: resolve(directory),
44
+ evidence: {
45
+ ...run.evidence,
46
+ directory: resolve(directory, run.evidence.directory),
47
+ },
48
+ },
49
+ process.platform === "win32" ? "C:/tmp/opencode" : tmpdir(),
50
+ );
51
+ }
52
+
53
+ /** Reference integrity only; interpretation of task facts stays in the judges. */
33
54
  export async function verifyJudgmentEvidence(
34
55
  judgment: Judgment,
35
56
  reference: EvidenceRef,
@@ -38,6 +59,6 @@ export async function verifyJudgmentEvidence(
38
59
  await validateCitations(judgment, evidence);
39
60
  return {
40
61
  hash: evidence.checkpoint.hash,
41
- metrics: judgment.metrics.length,
62
+ criteria: Object.keys(judgment.scores).length,
42
63
  };
43
64
  }
@@ -57,7 +57,8 @@ export async function judgeRuns(
57
57
  ...evalDefinition,
58
58
  judge: updated.judge,
59
59
  judgeHash: updated.judgeHash,
60
- metrics: updated.metrics,
60
+ criteria: updated.criteria,
61
+ code: updated.code,
61
62
  name: updated.name,
62
63
  }
63
64
  : evalDefinition;
@@ -20,6 +20,7 @@ import { judgeEvalRun } from "./judge-run";
20
20
  import type { ExecutionContext } from "./context";
21
21
  import { canJudgeEval } from "./eval-state";
22
22
  import { isScored } from "../judgment";
23
+ import { benchmarkScores } from "./scores";
23
24
  import { CostBudget, estimateWork } from "./cost-plan";
24
25
 
25
26
  export type RunBenchmarkOptions = {
@@ -79,6 +80,9 @@ export function finishBenchmark(context: ExecutionContext) {
79
80
  judges.some(
80
81
  (run) => run.id === slot.judgeRunId && isScored(run.judgment?.value),
81
82
  ),
83
+ ) &&
84
+ benchmarkScores(context.definition, slots, judges).every(
85
+ (score) => score.percentage !== null,
82
86
  );
83
87
  const currentInputs = planBenchmark(
84
88
  context.definition,
@@ -67,6 +67,7 @@ export async function runEvalPipeline(
67
67
  evalRunId: candidate!.id,
68
68
  evidence: saved,
69
69
  rubric: definition.judge,
70
+ kind: "llm",
70
71
  agent: JUDGE_AGENT,
71
72
  model: context.definition.judge.model,
72
73
  judgeHash: slot.judgeHash,
@@ -75,7 +76,7 @@ export async function runEvalPipeline(
75
76
  mode: "monitor",
76
77
  runtimeHash: context.runtime.judgeHash,
77
78
  protocol: JUDGE_PROTOCOL,
78
- metrics: definition.metrics,
79
+ criteria: definition.criteria,
79
80
  monitor: policy,
80
81
  });
81
82
  return saved;
@@ -3,6 +3,8 @@ import type { Slot, EvalRun } from "../types";
3
3
  import type { ExecutionContext } from "./context";
4
4
  import { executeCandidate } from "../infra/containers/candidate";
5
5
  import type { EvidenceFeed } from "../evidence";
6
+ import { CandidateEvidence } from "../infra/evidence";
7
+ import { measureRecording } from "../infra/recording/metrics";
6
8
 
7
9
  /** The normal candidate use case: record its inputs, execute, finalize its evidence. */
8
10
  export async function runEval(
@@ -88,6 +90,17 @@ export async function runEval(
88
90
  }
89
91
  : undefined,
90
92
  };
93
+ if (completed.evidence) {
94
+ const evidence = await CandidateEvidence.open(
95
+ resolve(context.directory, completed.evidence.directory),
96
+ completed.evidence.hash,
97
+ );
98
+ completed.metrics = measureRecording(
99
+ evidence.rawEvents(),
100
+ evidence.toolCalls(),
101
+ completed.evidence,
102
+ );
103
+ }
91
104
  context.results.finishEval(completed);
92
105
  return completed;
93
106
  }
package/src/app/scores.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { BenchmarkDefinition, JudgeRun, Slot } from "../types";
2
2
  import { modelScore } from "../view";
3
+ import { isScored } from "../judgment";
3
4
 
4
5
  /** Scores are derived from a single selection snapshot; every eval has equal weight. */
5
6
  export function benchmarkScores(
@@ -9,46 +10,87 @@ export function benchmarkScores(
9
10
  evalId?: string,
10
11
  ) {
11
12
  const index = new Map(judges.map((run) => [run.id, run]));
13
+ const evals = definition.evals.filter(
14
+ (item) => !evalId || item.id === evalId,
15
+ );
16
+ const definitions = new Map(
17
+ evals.map((item) => {
18
+ const criteria = new Map(
19
+ item.criteria.map((criterion) => [criterion.id, criterion]),
20
+ );
21
+ for (const slot of slots.filter(
22
+ (slot) => slot.active && slot.evalId === item.id,
23
+ )) {
24
+ const judgment = slot.judgeRunId
25
+ ? index.get(slot.judgeRunId)?.judgment
26
+ : undefined;
27
+ for (const id of Object.keys(judgment?.scores ?? {}))
28
+ if (!criteria.has(id))
29
+ criteria.set(id, { id, name: id.replaceAll("_", " ") });
30
+ }
31
+ return [item.id, [...criteria.values()]];
32
+ }),
33
+ );
12
34
  return definition.models.map((model) =>
13
35
  modelScore(
14
36
  model,
15
- definition.evals
16
- .filter((item) => !evalId || item.id === evalId)
17
- .flatMap((item) => {
18
- const metrics = item.metrics;
19
- const selected = slots.filter(
20
- (slot) =>
21
- slot.active && slot.evalId === item.id && slot.model === model,
37
+ evals.flatMap((item) => {
38
+ const criteria = definitions.get(item.id)!;
39
+ const selected = slots.filter(
40
+ (slot) =>
41
+ slot.active && slot.evalId === item.id && slot.model === model,
42
+ );
43
+ return criteria.map((criterion) => {
44
+ const values = selected
45
+ .map(
46
+ (slot) =>
47
+ (slot.judgeRunId
48
+ ? index.get(slot.judgeRunId)?.judgment?.scores
49
+ : undefined)?.[criterion.id]?.value,
50
+ )
51
+ .filter(isScored);
52
+ const scoredSum = values.reduce<number>(
53
+ (sum, value) => sum + value,
54
+ 0,
22
55
  );
23
- return metrics.map((metric) => {
24
- const values = selected
25
- .map(
56
+ return {
57
+ eval: item.id,
58
+ criterion: criterion.id,
59
+ name: criterion.name,
60
+ value:
61
+ values.length === definition.repetitions
62
+ ? scoredSum / definition.repetitions
63
+ : null,
64
+ scored: values.length,
65
+ expected: definition.repetitions,
66
+ passed: values.filter((value) => value === 1).length,
67
+ scoredSum,
68
+ };
69
+ });
70
+ }),
71
+ evals.map((item) => item.id),
72
+ evals
73
+ .filter(
74
+ (item) =>
75
+ item.code &&
76
+ slots
77
+ .filter(
26
78
  (slot) =>
27
- (slot.judgeRunId
28
- ? index.get(slot.judgeRunId)?.judgment?.metrics
29
- : undefined
30
- )?.find((value) => value.id === metric.id)?.value,
79
+ slot.active &&
80
+ slot.evalId === item.id &&
81
+ slot.model === model,
31
82
  )
32
- .filter((value): value is 0 | 1 => value === 0 || value === 1);
33
- const scoredSum = values.reduce<number>(
34
- (sum, value) => sum + value,
35
- 0,
36
- );
37
- return {
38
- eval: item.id,
39
- metric: metric.id,
40
- name: metric.name,
41
- value:
42
- values.length === definition.repetitions
43
- ? scoredSum / definition.repetitions
44
- : null,
45
- scored: values.length,
46
- expected: definition.repetitions,
47
- passed: scoredSum,
48
- scoredSum,
49
- };
50
- });
51
- }),
83
+ .some((slot) => {
84
+ const judge = slot.judgeRunId
85
+ ? index.get(slot.judgeRunId)
86
+ : undefined;
87
+ return (
88
+ judge?.code?.state !== "completed" ||
89
+ judge.input.code?.hash !== item.code!.hash
90
+ );
91
+ }),
92
+ )
93
+ .map((item) => item.id),
52
94
  ),
53
95
  );
54
96
  }
@@ -66,6 +66,8 @@ export async function serveResults(options: {
66
66
  if (value !== null) query[key] = Number(value);
67
67
  }
68
68
  const revision = url.searchParams.get("revision");
69
+ if (url.searchParams.has("metric"))
70
+ query.metric = url.searchParams.get("metric")!;
69
71
  if (revision === "initial" || revision === "final")
70
72
  query.revision = revision;
71
73
  return Response.json(
package/src/evidence.ts CHANGED
@@ -11,7 +11,10 @@ export type EvidenceQuery = {
11
11
  | "tool"
12
12
  | "artifacts"
13
13
  | "artifact"
14
- | "diff";
14
+ | "diff"
15
+ | "metrics";
16
+ /** A dot-separated measurement path for the metrics query. */
17
+ metric?: string;
15
18
  sessionID?: string;
16
19
  type?: string;
17
20
  id?: string;
package/src/index.ts CHANGED
@@ -8,8 +8,8 @@ export type {
8
8
  EvalRun,
9
9
  JudgeRun,
10
10
  Judgment,
11
- MetricDefinition,
12
- MetricJudgment,
11
+ CriterionDefinition,
12
+ CriterionScore,
13
13
  EvidenceCitation,
14
14
  ToolCall,
15
15
  MonitorPolicy,
@@ -30,7 +30,18 @@ export type {
30
30
  JudgeSession,
31
31
  } from "./evidence";
32
32
  export { CANDIDATE_TIMEOUT_MS } from "./types";
33
- export { rubricMetrics, metricMean, isScored } from "./judgment";
33
+ export { rubricCriteria, criterionMean, isScored } from "./judgment";
34
+ export type {
35
+ JudgeContext,
36
+ JudgeFunction,
37
+ JsonValue,
38
+ ScoreValue,
39
+ RunMetrics,
40
+ ToolMetrics,
41
+ RecordedEvent,
42
+ RecordedMessage,
43
+ RecordedFile,
44
+ } from "./judge-context";
34
45
  export { loadBenchmark } from "./app/load-benchmark";
35
46
  export {
36
47
  runBenchmark,
@@ -47,6 +58,7 @@ export { judgeEvidence, recordEvidence } from "./app/judge-evidence";
47
58
  export {
48
59
  readBenchmarkRun,
49
60
  readEvidence,
61
+ readRecording,
50
62
  verifyJudgmentEvidence,
51
63
  } from "./app/read-run";
52
64
  export { snapshotBenchmarkRun } from "./app/snapshot-run";