@hona/openeval 0.2.2 → 0.3.1

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 (214) hide show
  1. package/JUDGING.md +135 -23
  2. package/README.md +71 -9
  3. package/package.json +7 -6
  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 +48 -16
  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 +8 -1
  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/containers/runtime/package.json +2 -2
  22. package/src/infra/containers/runtime/server.mjs +1 -1
  23. package/src/infra/evidence/index.ts +39 -2
  24. package/src/infra/evidence/tool-calls.ts +5 -2
  25. package/src/infra/judging/agent.ts +3 -2
  26. package/src/infra/judging/code-result.ts +102 -0
  27. package/src/infra/judging/code-source.ts +96 -0
  28. package/src/infra/judging/code-worker.ts +26 -0
  29. package/src/infra/judging/code.ts +97 -0
  30. package/src/infra/judging/contract.ts +82 -64
  31. package/src/infra/judging/evidence-tool.ts +3 -1
  32. package/src/infra/judging/index.ts +14 -0
  33. package/src/infra/judging/judge-agent.md +24 -18
  34. package/src/infra/judging/observer.ts +8 -7
  35. package/src/infra/judging/submission.ts +8 -8
  36. package/src/infra/judging/tools.ts +9 -9
  37. package/src/infra/opencode/host.ts +1 -1
  38. package/src/infra/opencode/read-recording.ts +6 -1
  39. package/src/infra/opencode/version.ts +2 -0
  40. package/src/infra/recording/index.ts +240 -0
  41. package/src/infra/recording/metrics.ts +193 -0
  42. package/src/infra/sqlite/index.ts +29 -19
  43. package/src/judge-context.ts +141 -0
  44. package/src/judgment.ts +26 -17
  45. package/src/types.ts +36 -17
  46. package/src/view.ts +40 -14
  47. package/viewer/THIRD_PARTY_LICENSES.md +2 -2
  48. package/viewer/assets/{abnfDiagram-VCTEODGH-B1kcYgQG.js → abnfDiagram-VCTEODGH-Ck7reUId.js} +1 -1
  49. package/viewer/assets/{angular-html-DrYCUiZv.js → angular-html-DzRW817u.js} +1 -1
  50. package/viewer/assets/{angular-ts-BgjwQn-Z.js → angular-ts-Dwpo5JSv.js} +1 -1
  51. package/viewer/assets/{apl-DlHqe8o4.js → apl-bt59SDvg.js} +1 -1
  52. package/viewer/assets/{arc-C4nf7ZoY.js → arc-Dwbl2Pkh.js} +1 -1
  53. package/viewer/assets/architecture-7GRP2DOG-BZpt0zSq.js +1 -0
  54. package/viewer/assets/{architectureDiagram-5GKGNRK7-BIWoe0fO.js → architectureDiagram-5GKGNRK7-BcmO-Qqp.js} +1 -1
  55. package/viewer/assets/{astro-BrlHnIh9.js → astro-B3siF1pJ.js} +1 -1
  56. package/viewer/assets/{blade-DOcerOiW.js → blade-BevF_cYv.js} +1 -1
  57. package/viewer/assets/{blockDiagram-I7D4REHJ-C3x13a9m.js → blockDiagram-I7D4REHJ-MzX9_xf9.js} +1 -1
  58. package/viewer/assets/{c-BMbThxEo.js → c-gavBjOcY.js} +1 -1
  59. package/viewer/assets/{c4Diagram-7LVT6UL2-BeWktchx.js → c4Diagram-7LVT6UL2-BbHHPJGg.js} +1 -1
  60. package/viewer/assets/channel-BnnBJr7O.js +1 -0
  61. package/viewer/assets/{chapel-k2cjkSmc.js → chapel-DgshBe1K.js} +1 -1
  62. package/viewer/assets/{chunk-4HAMMTFA-o6YtJsqE.js → chunk-4HAMMTFA-D1Gsg_qO.js} +1 -1
  63. package/viewer/assets/{chunk-75Z2AOVW-KohQa9Nw.js → chunk-75Z2AOVW-EfPG3FOY.js} +1 -1
  64. package/viewer/assets/{chunk-DU6HZSFF-C88wxc6m.js → chunk-DU6HZSFF-BxB0lceI.js} +1 -1
  65. package/viewer/assets/{chunk-F27PBJKO-mO4AP2as.js → chunk-F27PBJKO-DRBDr_-Q.js} +1 -1
  66. package/viewer/assets/{chunk-GMAD6QVW-DzQX2Cld.js → chunk-GMAD6QVW-AbIWvPs8.js} +1 -1
  67. package/viewer/assets/{chunk-GVQU2GXP-CS78RfJD.js → chunk-GVQU2GXP-aIYNUxo9.js} +1 -1
  68. package/viewer/assets/{chunk-IMKFNOWR-DxS42GUo.js → chunk-IMKFNOWR-BwpTTnl_.js} +1 -1
  69. package/viewer/assets/{chunk-L3NEJ4N5-DGo-uYLy.js → chunk-L3NEJ4N5-KtxD1mfg.js} +1 -1
  70. package/viewer/assets/{chunk-OSK3NFVY-BOcXQG16.js → chunk-OSK3NFVY-CinbAXbX.js} +1 -1
  71. package/viewer/assets/{chunk-P2QGCYS3-B7GnZdIQ.js → chunk-P2QGCYS3-Dst8DZSR.js} +1 -1
  72. package/viewer/assets/{chunk-POPQ4Y6H-DgBcYHog.js → chunk-POPQ4Y6H-DqvBdud7.js} +1 -1
  73. package/viewer/assets/{chunk-PWAF6VOD-DpEq6qHA.js → chunk-PWAF6VOD-Cl2eG05g.js} +1 -1
  74. package/viewer/assets/{chunk-SHT3W25Y-CrOGxKM2.js → chunk-SHT3W25Y-D9FbZ836.js} +1 -1
  75. package/viewer/assets/{chunk-SVP7TREG-4HY7Fljj.js → chunk-SVP7TREG-_4n_lRpO.js} +1 -1
  76. package/viewer/assets/{chunk-TICWLB2K-B1Rl31EC.js → chunk-TICWLB2K-DUXjjJlY.js} +1 -1
  77. package/viewer/assets/{chunk-XXDRQBXY-CK8giEW-.js → chunk-XXDRQBXY-BdRoSapX.js} +1 -1
  78. package/viewer/assets/classDiagram-ZZMXUADV-F9J3BKRU.js +1 -0
  79. package/viewer/assets/classDiagram-v2-VYDZK3BY-F9J3BKRU.js +1 -0
  80. package/viewer/assets/{cobol-CupUwvw9.js → cobol-D5zqvXzY.js} +1 -1
  81. package/viewer/assets/{coffee-C17pkozF.js → coffee-SCAyVn9N.js} +1 -1
  82. package/viewer/assets/{cose-bilkent-JH36ORCC-V1OmrmCv.js → cose-bilkent-JH36ORCC-B5uDWB-J.js} +1 -1
  83. package/viewer/assets/{cpp-BJwVQVXg.js → cpp-RUQ97EK5.js} +1 -1
  84. package/viewer/assets/{crystal-BF-oCN-L.js → crystal-FauNVdkE.js} +1 -1
  85. package/viewer/assets/{css-BMgkVI3c.js → css-DuzOk7di.js} +1 -1
  86. package/viewer/assets/{cynefin-OW5HDTMX-BEjY_gsc.js → cynefin-OW5HDTMX-D0N8Dm6P.js} +1 -1
  87. package/viewer/assets/{cynefinDiagram-5FMLGOSQ-bfSYgr6z.js → cynefinDiagram-5FMLGOSQ-IGGiqH_Y.js} +1 -1
  88. package/viewer/assets/{dagre-GXQ25YYZ-VtwTgGfa.js → dagre-GXQ25YYZ-PoopsFcY.js} +1 -1
  89. package/viewer/assets/{diagram-S7CK7UJ4-CHaAAyW7.js → diagram-S7CK7UJ4-D6GuIlRD.js} +1 -1
  90. package/viewer/assets/{diagram-UQ7AKVKN-CjL65-As.js → diagram-UQ7AKVKN-Cj8lu7Hi.js} +1 -1
  91. package/viewer/assets/{diagram-VSXAHHWV-Cnxrk1TJ.js → diagram-VSXAHHWV-bI4-SjAp.js} +1 -1
  92. package/viewer/assets/{diagram-VX7I27RA-D78jPXr7.js → diagram-VX7I27RA-jWvTT618.js} +1 -1
  93. package/viewer/assets/{diagram-Z3DM3KII-DKjnOaF2.js → diagram-Z3DM3KII-D6Vcvcr8.js} +1 -1
  94. package/viewer/assets/{dist-BTYPW0dz.js → dist-Cn65YNrn.js} +1 -1
  95. package/viewer/assets/{ebnfDiagram-PWID7BFC-7XiXh5Lx.js → ebnfDiagram-PWID7BFC-y-ZxfP2H.js} +1 -1
  96. package/viewer/assets/{edge-B34N_HjN.js → edge-Bc0EBQ7y.js} +1 -1
  97. package/viewer/assets/{elixir-CQzWMyKD.js → elixir-BmxsT0oc.js} +1 -1
  98. package/viewer/assets/{elm-BNJiG-wg.js → elm-BrTAZ55m.js} +1 -1
  99. package/viewer/assets/{erDiagram-RLTQ6QDP-YPFEgZxU.js → erDiagram-RLTQ6QDP-Wa1tikbb.js} +1 -1
  100. package/viewer/assets/{erb-D5Rm3UNa.js → erb-B60HRxmg.js} +1 -1
  101. package/viewer/assets/eventmodeling-NTZA5JFV-BNvBHnQf.js +1 -0
  102. package/viewer/assets/flowDiagram-HODETNUW-zGgqOVuO.js +1 -0
  103. package/viewer/assets/{ganttDiagram-EL5Y4UJY-ergSGtTP.js → ganttDiagram-EL5Y4UJY-DjskXB68.js} +1 -1
  104. package/viewer/assets/{git-rebase-BpIMZIRG.js → git-rebase-CK9f68l3.js} +1 -1
  105. package/viewer/assets/{gitGraph-4MIJSDKK-CZt4REVj.js → gitGraph-4MIJSDKK-CvRhO7Ae.js} +1 -1
  106. package/viewer/assets/{gitGraphDiagram-WWUBYQGX-h9QMzC2r.js → gitGraphDiagram-WWUBYQGX-Bg_OLNL1.js} +1 -1
  107. package/viewer/assets/{glimmer-js-SeSwns5_.js → glimmer-js-CVc7keaR.js} +1 -1
  108. package/viewer/assets/{glimmer-ts-BExI5tTz.js → glimmer-ts-DYraWlmH.js} +1 -1
  109. package/viewer/assets/{glsl-CXikKw2b.js → glsl-BpYswgfh.js} +1 -1
  110. package/viewer/assets/{graphql-6GpQIInt.js → graphql-C3iDzxap.js} +1 -1
  111. package/viewer/assets/{hack-i7rizvpB.js → hack-D8oEoipZ.js} +1 -1
  112. package/viewer/assets/{haml-C68gmkTf.js → haml-BJb-BQAN.js} +1 -1
  113. package/viewer/assets/{handlebars-BBn_c0Xt.js → handlebars-wB54lHaB.js} +1 -1
  114. package/viewer/assets/{html-BObmAZQA.js → html-HIvKkSZ3.js} +1 -1
  115. package/viewer/assets/{html-derivative-BjMuR1LM.js → html-derivative-CDavbmdn.js} +1 -1
  116. package/viewer/assets/{http-BJBk8gt0.js → http-DEgShh0-.js} +1 -1
  117. package/viewer/assets/{hurl-D7obCYfg.js → hurl-D8wvJcyh.js} +1 -1
  118. package/viewer/assets/{index-FMtYXcX7.js → index-Ck3NBCVJ.js} +9 -7
  119. package/viewer/assets/{index-Wz0qQyIk.css → index-DAuO1BM4.css} +1 -1
  120. package/viewer/assets/{info-A6RAGUB7-CrzitQIU.js → info-A6RAGUB7-DL3H6Iqn.js} +1 -1
  121. package/viewer/assets/{infoDiagram-27XIBGKW-D2CgRDxu.js → infoDiagram-27XIBGKW-DSLzhrL8.js} +1 -1
  122. package/viewer/assets/{ishikawaDiagram-5VMMS53U-BhnQMHOo.js → ishikawaDiagram-5VMMS53U-B-ycXUrd.js} +1 -1
  123. package/viewer/assets/{java-5VJU_EW8.js → java-C5iWdXOl.js} +1 -1
  124. package/viewer/assets/{javascript-r8UgndxQ.js → javascript-PMSXGhX1.js} +1 -1
  125. package/viewer/assets/{jinja-BY2ibHG5.js → jinja-CJ_l63gX.js} +1 -1
  126. package/viewer/assets/{jison-C_7YxymZ.js → jison-DGaZyJAT.js} +1 -1
  127. package/viewer/assets/{journeyDiagram-3NMN7TZE-DSBzKQEa.js → journeyDiagram-3NMN7TZE-2p56tZPm.js} +1 -1
  128. package/viewer/assets/{json-8e1WlJYD.js → json-CCQ1eo9o.js} +1 -1
  129. package/viewer/assets/{jsx-BYp5GD4Y.js → jsx-DeLT99JL.js} +1 -1
  130. package/viewer/assets/{julia-Bkob1uVX.js → julia-DODLsulx.js} +1 -1
  131. package/viewer/assets/{just-CUnSjty-.js → just-B_Nvjvhv.js} +1 -1
  132. package/viewer/assets/{kanban-definition-UXKFOSKX-CotbrQue.js → kanban-definition-UXKFOSKX-B42fPx4K.js} +1 -1
  133. package/viewer/assets/{latex-UdE3ivqk.js → latex-CCjy2I9z.js} +1 -1
  134. package/viewer/assets/{line-DDh6a6hz.js → line-DGK8UZYe.js} +1 -1
  135. package/viewer/assets/{linear-BxMsCbKb.js → linear-LxXu6wOl.js} +1 -1
  136. package/viewer/assets/{liquid-WL4MvEIT.js → liquid-C2tknZP0.js} +1 -1
  137. package/viewer/assets/{lua-CtOubZta.js → lua-D6UzQw5Z.js} +1 -1
  138. package/viewer/assets/{marko-C0GSQJi3.js → marko-CGd5W4Hn.js} +1 -1
  139. package/viewer/assets/{mdc-DUivddFc.js → mdc-Bp5z92Vo.js} +1 -1
  140. package/viewer/assets/{mermaid-parser.core-FhKE_uv2.js → mermaid-parser.core-xGBt_sNt.js} +3 -3
  141. package/viewer/assets/{mermaid.core-BSOWwyvd.js → mermaid.core-D1TUMBuT.js} +4 -4
  142. package/viewer/assets/{mindmap-definition-YA3MSWOX-tsLZ_Opn.js → mindmap-definition-YA3MSWOX-BY9cVMtI.js} +1 -1
  143. package/viewer/assets/{nginx-B__INAtC.js → nginx-DAsqAd3h.js} +1 -1
  144. package/viewer/assets/{nim-UEY12GJF.js → nim-COOJz623.js} +1 -1
  145. package/viewer/assets/{org-DDIZsz95.js → org-CBV1qqrA.js} +1 -1
  146. package/viewer/assets/{packet-AYTQ26CC-CqdJnqfo.js → packet-AYTQ26CC-61q5HcB3.js} +1 -1
  147. package/viewer/assets/{pegDiagram-XKGWAZYB-BJs7qu7m.js → pegDiagram-XKGWAZYB-DLEkmimO.js} +1 -1
  148. package/viewer/assets/{perl-D5KwNZt7.js → perl-6SV_ayGd.js} +1 -1
  149. package/viewer/assets/{php-BEs7d_Dk.js → php-BUb-Io9m.js} +1 -1
  150. package/viewer/assets/{pie-WAS4IAKB-lgzqBWqy.js → pie-WAS4IAKB-DgijP3YA.js} +1 -1
  151. package/viewer/assets/{pieDiagram-E7YTZNPT-Cxe9LnnE.js → pieDiagram-E7YTZNPT-Cp20J80-.js} +1 -1
  152. package/viewer/assets/{pug-B0dsfQOV.js → pug-D5s94d1b.js} +1 -1
  153. package/viewer/assets/{qml-XPIhrIzf.js → qml-D8g4NGVo.js} +1 -1
  154. package/viewer/assets/{quadrantDiagram-AXDQQJYC-D5JGwC11.js → quadrantDiagram-AXDQQJYC-Djsc9xpm.js} +1 -1
  155. package/viewer/assets/{r-C6hQdpIM.js → r-DXvz5K4A.js} +1 -1
  156. package/viewer/assets/{radar-RG4KPBEZ-B7JRLhUA.js → radar-RG4KPBEZ-BCmoUpe8.js} +1 -1
  157. package/viewer/assets/{railroad-74A4TZTK-Df7ZQBLn.js → railroad-74A4TZTK-DZ0SYESf.js} +1 -1
  158. package/viewer/assets/railroad-abnf-HS5TGJTU-C2CQDbu6.js +1 -0
  159. package/viewer/assets/railroad-ebnf-LZEXJU2U-6ssJubZr.js +1 -0
  160. package/viewer/assets/railroad-peg-WCYAUIDC-UOxDGPyg.js +1 -0
  161. package/viewer/assets/{railroadDiagram-O6MQD6OU-DZJzpmP8.js → railroadDiagram-O6MQD6OU-DmD4JR_t.js} +1 -1
  162. package/viewer/assets/{razor-C3KSUuOw.js → razor-D9CjUAvE.js} +1 -1
  163. package/viewer/assets/{regexp-n-T936Rk.js → regexp-CnuLvLnC.js} +1 -1
  164. package/viewer/assets/{requirementDiagram-BXWQKSXE-Be9lEFrk.js → requirementDiagram-BXWQKSXE-BTci7X6J.js} +1 -1
  165. package/viewer/assets/{rst-fVnHDyXD.js → rst-Chdv5DuC.js} +1 -1
  166. package/viewer/assets/{ruby-DuRgxlXF.js → ruby-DXQkNv8k.js} +1 -1
  167. package/viewer/assets/{sankeyDiagram-P5KCCOFB-BsgKAEBN.js → sankeyDiagram-P5KCCOFB-BaHSMANQ.js} +1 -1
  168. package/viewer/assets/{sas-C0WA2OFa.js → sas-B6S0Oq1H.js} +1 -1
  169. package/viewer/assets/{scss-CQDZ4smR.js → scss-BnFPXH54.js} +1 -1
  170. package/viewer/assets/{sequenceDiagram-WJ2MYXX4-BkUDWL0D.js → sequenceDiagram-WJ2MYXX4-BUk21g1t.js} +1 -1
  171. package/viewer/assets/{shellscript-CE84G0GP.js → shellscript-Brdg8vyE.js} +1 -1
  172. package/viewer/assets/{shellsession-BdJvdaqL.js → shellsession-Df33UGC7.js} +1 -1
  173. package/viewer/assets/{soy-BSxOREC0.js → soy-DE83qari.js} +1 -1
  174. package/viewer/assets/{sql-D4MN9uRI.js → sql-C838IanB.js} +1 -1
  175. package/viewer/assets/{src-BT_kESTA.js → src-tvfSkCy9.js} +1 -1
  176. package/viewer/assets/{stata-B6nXAaGV.js → stata-BjrFc6Ob.js} +1 -1
  177. package/viewer/assets/{stateDiagram-D77RDMKH-C80wp8xG.js → stateDiagram-D77RDMKH-B7yRJv9-.js} +1 -1
  178. package/viewer/assets/stateDiagram-v2-MP3YSRHH-BCwhllSg.js +1 -0
  179. package/viewer/assets/{surrealql-fVjZmhV3.js → surrealql-BQl2P64c.js} +1 -1
  180. package/viewer/assets/{svelte-DnBQ5p7d.js → svelte-WhVuP9VM.js} +1 -1
  181. package/viewer/assets/{swimlanes-42K2YHIH-Cff6yT8e.js → swimlanes-42K2YHIH-on6wyUF5.js} +1 -1
  182. package/viewer/assets/swimlanesDiagram-VR7AAH4N-D0QyhouX.js +8 -0
  183. package/viewer/assets/{templ-TCx51Uts.js → templ-GlyHWfam.js} +1 -1
  184. package/viewer/assets/{tex-CF6SMAQ_.js → tex-Wu25UU_Z.js} +1 -1
  185. package/viewer/assets/{timeline-definition-24CTP7MA-Cje7BvaN.js → timeline-definition-24CTP7MA-DsgJtBig.js} +1 -1
  186. package/viewer/assets/{treeView-Q6P3EWNA-D-QLY3IO.js → treeView-Q6P3EWNA-Bae2q_db.js} +1 -1
  187. package/viewer/assets/{treemap-WGGIJYW6-BCHcTa4N.js → treemap-WGGIJYW6-BJsxvsBb.js} +1 -1
  188. package/viewer/assets/{ts-tags-BqLRnADX.js → ts-tags-C6TgXLV6.js} +1 -1
  189. package/viewer/assets/{tsx-D7KpDX0b.js → tsx-DVoPHges.js} +1 -1
  190. package/viewer/assets/{twig-CEZLObpN.js → twig-CKzx4A42.js} +1 -1
  191. package/viewer/assets/{typescript-DAbIDLbf.js → typescript-DvXz8u_k.js} +1 -1
  192. package/viewer/assets/{typst-CqN7-whv.js → typst-BcepwfpV.js} +1 -1
  193. package/viewer/assets/{vennDiagram-4TSXK5OY-Bz20rx02.js → vennDiagram-4TSXK5OY-CKUR4uY_.js} +1 -1
  194. package/viewer/assets/{vue-kTxN6wdc.js → vue-Bqzme_T-.js} +1 -1
  195. package/viewer/assets/{vue-html-DQmvvKbd.js → vue-html-DZHKNOUy.js} +1 -1
  196. package/viewer/assets/{vue-vine-Did3qTVW.js → vue-vine-azvFs0P6.js} +1 -1
  197. package/viewer/assets/{wardley-WFR3VGLG-CpXaqOit.js → wardley-WFR3VGLG-Ddsu3qLB.js} +1 -1
  198. package/viewer/assets/{wardleyDiagram-VM6X3IG4-Cz06jHpA.js → wardleyDiagram-VM6X3IG4-CCHx9UX4.js} +1 -1
  199. package/viewer/assets/{xml-te2hFcAA.js → xml-BZNC4g25.js} +1 -1
  200. package/viewer/assets/{xsl-X4fuKSVl.js → xsl-DXEWaWc5.js} +1 -1
  201. package/viewer/assets/{xychartDiagram-S5SC5T6Z-BXCw0sfu.js → xychartDiagram-S5SC5T6Z-CkoTq405.js} +1 -1
  202. package/viewer/assets/{yaml-NHtDSZab.js → yaml-DLY3wDEk.js} +1 -1
  203. package/viewer/index.html +2 -2
  204. package/viewer/assets/architecture-7GRP2DOG-Be250VKZ.js +0 -1
  205. package/viewer/assets/channel-DtULXRee.js +0 -1
  206. package/viewer/assets/classDiagram-ZZMXUADV-Bmqu01Xf.js +0 -1
  207. package/viewer/assets/classDiagram-v2-VYDZK3BY-Bmqu01Xf.js +0 -1
  208. package/viewer/assets/eventmodeling-NTZA5JFV-CJCg5f6p.js +0 -1
  209. package/viewer/assets/flowDiagram-HODETNUW-BFzq4Zvs.js +0 -1
  210. package/viewer/assets/railroad-abnf-HS5TGJTU-Z8q3QVTf.js +0 -1
  211. package/viewer/assets/railroad-ebnf-LZEXJU2U-BWoRkG3W.js +0 -1
  212. package/viewer/assets/railroad-peg-WCYAUIDC-BzoV1cN7.js +0 -1
  213. package/viewer/assets/stateDiagram-v2-MP3YSRHH-CYdsKKlz.js +0 -1
  214. package/viewer/assets/swimlanesDiagram-VR7AAH4N-niTUGjMT.js +0 -8
@@ -0,0 +1,193 @@
1
+ import type { EvidenceRef, ToolCall } from "../../types";
2
+ import type {
3
+ RecordedEvent,
4
+ RunMetrics,
5
+ ToolMetrics,
6
+ } from "../../judge-context";
7
+ import { mergeRuntime, runtimeMs, type RuntimeInterval } from "../../runtime";
8
+
9
+ const toolsSummary = (tools: ToolCall[]): ToolMetrics => {
10
+ const succeeded = tools.filter((call) => call.status === "succeeded").length;
11
+ const failed = tools.filter((call) => call.status === "failed").length;
12
+ return {
13
+ calls: tools.length,
14
+ succeeded,
15
+ failed,
16
+ unfinished: tools.length - succeeded - failed,
17
+ errorRate: succeeded + failed ? failed / (succeeded + failed) : null,
18
+ };
19
+ };
20
+
21
+ /** Measurements use deduplicated native records, never scored criterion values. */
22
+ export function measureRecording(
23
+ supplied: RecordedEvent[],
24
+ tools: ToolCall[],
25
+ evidence: EvidenceRef,
26
+ ): RunMetrics {
27
+ const events = [
28
+ ...new Map(
29
+ supplied.map((item) => [
30
+ "id" in item.event ? item.event.id : String(item.sequence),
31
+ item.event,
32
+ ]),
33
+ ).values(),
34
+ ].sort(
35
+ (a, b) =>
36
+ ("created" in a ? a.created : 0) - ("created" in b ? b.created : 0),
37
+ );
38
+ const count = (type: string) =>
39
+ events.filter((event) => event.type === type).length;
40
+ const tokens = {
41
+ input: 0,
42
+ output: 0,
43
+ reasoning: 0,
44
+ cache: { read: 0, write: 0 },
45
+ };
46
+ let reportedUSD = 0,
47
+ usageRecords = 0,
48
+ usageComplete = true,
49
+ costComplete = true;
50
+ const intervals: RuntimeInterval[] = [],
51
+ starts = new Map<string, number>();
52
+ const executions: RuntimeInterval[] = [],
53
+ executionStarts = new Map<string, number>();
54
+ const created = new Set<string>();
55
+ const sessions = new Set<string>(),
56
+ sequences = new Map<string, number[]>();
57
+ for (const event of events) {
58
+ if (!("data" in event)) continue;
59
+ const data = event.data as Record<string, unknown>;
60
+ if (typeof data.sessionID === "string") sessions.add(data.sessionID);
61
+ if (event.type === "session.created") created.add(event.data.sessionID);
62
+ if (event.type === "session.execution.started")
63
+ executionStarts.set(event.data.sessionID, event.created);
64
+ if (
65
+ [
66
+ "session.execution.succeeded",
67
+ "session.execution.failed",
68
+ "session.execution.interrupted",
69
+ ].includes(event.type) &&
70
+ typeof data.sessionID === "string" &&
71
+ "created" in event
72
+ ) {
73
+ const start = executionStarts.get(data.sessionID);
74
+ if (start !== undefined) executions.push({ start, end: event.created });
75
+ executionStarts.delete(data.sessionID);
76
+ }
77
+ if ("durable" in event) {
78
+ const values = sequences.get(event.durable.aggregateID) ?? [];
79
+ values.push(event.durable.seq);
80
+ sequences.set(event.durable.aggregateID, values);
81
+ }
82
+ const key = `${data.sessionID}:${data.assistantMessageID ?? "compaction"}`;
83
+ if (
84
+ event.type === "session.step.started" ||
85
+ event.type === "session.compaction.started"
86
+ )
87
+ starts.set(key, event.created);
88
+ if (
89
+ [
90
+ "session.step.ended",
91
+ "session.step.failed",
92
+ "session.compaction.ended",
93
+ "session.compaction.failed",
94
+ ].includes(event.type)
95
+ ) {
96
+ const start = starts.get(key);
97
+ if (start !== undefined && "created" in event)
98
+ intervals.push({ start, end: event.created });
99
+ starts.delete(key);
100
+ }
101
+ if (
102
+ ![
103
+ "session.step.ended",
104
+ "session.step.failed",
105
+ "session.usage.recorded",
106
+ ].includes(event.type)
107
+ )
108
+ continue;
109
+ usageRecords++;
110
+ if (typeof data.cost === "number" && Number.isFinite(data.cost))
111
+ reportedUSD += data.cost;
112
+ else costComplete = false;
113
+ const usage = data.tokens as typeof tokens | undefined;
114
+ if (
115
+ !usage ||
116
+ ![
117
+ usage.input,
118
+ usage.output,
119
+ usage.reasoning,
120
+ usage.cache?.read,
121
+ usage.cache?.write,
122
+ ].every(Number.isFinite)
123
+ ) {
124
+ usageComplete = false;
125
+ continue;
126
+ }
127
+ tokens.input += usage.input;
128
+ tokens.output += usage.output;
129
+ tokens.reasoning += usage.reasoning;
130
+ tokens.cache.read += usage.cache.read;
131
+ tokens.cache.write += usage.cache.write;
132
+ }
133
+ const measuredTokens = usageRecords && usageComplete ? tokens : null;
134
+ const cost = usageRecords && costComplete ? reportedUSD : null;
135
+ const clock = events.reduce(
136
+ (latest, event) =>
137
+ "created" in event ? Math.max(latest, event.created) : latest,
138
+ 0,
139
+ );
140
+ const modelActiveMs = runtimeMs(mergeRuntime(intervals), clock);
141
+ const complete =
142
+ sequences.size > 0 &&
143
+ starts.size === 0 &&
144
+ executionStarts.size === 0 &&
145
+ [...sessions].every((id) => created.has(id)) &&
146
+ [...sequences.values()].every((values) => {
147
+ const sorted = [...new Set(values)].sort((a, b) => a - b);
148
+ return sorted.every(
149
+ (value, index) => index === 0 || value === sorted[index - 1] + 1,
150
+ );
151
+ });
152
+ return {
153
+ version: 1,
154
+ scope: "candidate",
155
+ complete,
156
+ sessions: sessions.size,
157
+ requests: {
158
+ started: count("session.step.started"),
159
+ succeeded: count("session.step.ended"),
160
+ failed: count("session.step.failed"),
161
+ retries: count("session.retry.scheduled"),
162
+ },
163
+ tokens: measuredTokens,
164
+ cost: { usd: cost, reportedUSD, complete: cost !== null },
165
+ tools: {
166
+ ...toolsSummary(tools),
167
+ byName: Object.fromEntries(
168
+ [...new Set(tools.map((call) => call.name))]
169
+ .sort()
170
+ .map((name) => [
171
+ name,
172
+ toolsSummary(tools.filter((call) => call.name === name)),
173
+ ]),
174
+ ),
175
+ },
176
+ compactions: {
177
+ started: count("session.compaction.started"),
178
+ completed: count("session.compaction.ended"),
179
+ failed: count("session.compaction.failed"),
180
+ },
181
+ timing: {
182
+ elapsedMs: executions.length
183
+ ? runtimeMs(mergeRuntime(executions), clock)
184
+ : null,
185
+ modelActiveMs,
186
+ outputTokensPerSecond:
187
+ measuredTokens && modelActiveMs > 0
188
+ ? (measuredTokens.output * 1000) / modelActiveMs
189
+ : null,
190
+ },
191
+ evidence,
192
+ };
193
+ }
@@ -5,7 +5,7 @@ import { mkdirSync, existsSync } from "node:fs";
5
5
  import { dirname, resolve } from "node:path";
6
6
  import { randomUUID } from "node:crypto";
7
7
  import * as tables from "./schema";
8
- import { isScored, JUDGE_PROTOCOL, metricMean } from "../../judgment";
8
+ import { isScored, JUDGE_PROTOCOL, criterionMean } from "../../judgment";
9
9
  import type {
10
10
  BenchmarkRun,
11
11
  EvalRun,
@@ -19,7 +19,7 @@ import type {
19
19
  } from "../../types";
20
20
 
21
21
  const APPLICATION_ID = 0x4f455632;
22
- const SCHEMA_VERSION = 4;
22
+ const SCHEMA_VERSION = 5;
23
23
  const timestamp = () => new Date().toISOString();
24
24
 
25
25
  /** One owner for run selection and append-only finalized execution records. */
@@ -257,13 +257,16 @@ export class Results {
257
257
  }
258
258
  startJudge(input: JudgeRunInput) {
259
259
  if (
260
- !input.agent ||
261
- !input.metrics.length ||
260
+ (!input.code &&
261
+ (!input.agent || !input.model || !input.criteria.length)) ||
262
+ (!!input.rubric &&
263
+ (!input.agent || !input.model || !input.criteria.length)) ||
264
+ !["llm", "code", "hybrid"].includes(input.kind) ||
262
265
  !input.runtimeHash ||
263
266
  input.protocol !== JUDGE_PROTOCOL
264
267
  )
265
268
  throw new Error(
266
- "Judge inputs must use the current agent, metrics, runtime, and protocol",
269
+ "Judge inputs must include their code or LLM configuration, criteria, runtime, and protocol",
267
270
  );
268
271
  const value: JudgeRun = {
269
272
  id: `judge_${randomUUID()}`,
@@ -301,21 +304,28 @@ export class Results {
301
304
  const saved = this.judgeRun(value.id);
302
305
  if (!saved || saved.state !== "running")
303
306
  throw new Error("Judge run is not running");
304
- if (
305
- value.state === "completed" &&
306
- (!value.judgment ||
307
- !Array.isArray(value.judgment.metrics) ||
308
- value.judgment.metrics.length !== value.input.metrics.length ||
309
- new Set(value.judgment.metrics.map((metric) => metric.id)).size !==
310
- value.input.metrics.length ||
311
- value.judgment.metrics.some(
312
- (metric) =>
313
- !value.input.metrics.some((declared) => declared.id === metric.id),
307
+ if (value.state === "completed") {
308
+ const expected = [
309
+ ...value.input.criteria.map((criterion) => criterion.id),
310
+ ...Object.keys(value.code?.scores ?? {}),
311
+ ];
312
+ const scores = value.judgment?.scores;
313
+ if (
314
+ !scores ||
315
+ Array.isArray(scores) ||
316
+ new Set(expected).size !== expected.length ||
317
+ Object.keys(scores).length !== expected.length ||
318
+ expected.some((id) => !Object.hasOwn(scores, id)) ||
319
+ Object.values(scores).some(
320
+ (score) => score.value !== null && !isScored(score.value),
314
321
  ) ||
315
- value.judgment.value !== metricMean(value.judgment.metrics) ||
316
- (value.judgment.value !== null && !isScored(value.judgment.value)))
317
- )
318
- throw new Error("A completed judge run requires a valid judgment");
322
+ value.judgment!.value !== criterionMean(scores) ||
323
+ (value.input.code && value.code?.state !== "completed")
324
+ )
325
+ throw new Error(
326
+ "A completed judge run requires a valid, complete judgment",
327
+ );
328
+ }
319
329
  if (
320
330
  value.state === "completed" &&
321
331
  this.evalRun(value.input.evalRunId)?.evidence?.hash !==
@@ -0,0 +1,141 @@
1
+ import type { Database } from "bun:sqlite";
2
+ import type { OpenCode } from "@opencode/sdk";
3
+ import type {
4
+ SessionInfo,
5
+ SessionMessageInfo,
6
+ SessionTransferData,
7
+ } from "@opencode/client";
8
+ import type {
9
+ EvalRun,
10
+ EvidenceRef,
11
+ OpenCodeStreamEvent,
12
+ ToolCall,
13
+ Cost,
14
+ Accounting,
15
+ } from "./types";
16
+
17
+ export type JsonValue =
18
+ | null
19
+ | boolean
20
+ | number
21
+ | string
22
+ | JsonValue[]
23
+ | { [key: string]: JsonValue };
24
+ export type ScoreValue = boolean | number | null;
25
+
26
+ /** Code judges are ordinary functions. Only an optional scores map has grading semantics. */
27
+ export type JudgeFunction = (
28
+ context: JudgeContext,
29
+ ) => JsonValue | Promise<JsonValue>;
30
+
31
+ export type ToolMetrics = {
32
+ calls: number;
33
+ succeeded: number;
34
+ failed: number;
35
+ unfinished: number;
36
+ /** Failed / (succeeded + failed); null when there are no terminal calls. */
37
+ errorRate: number | null;
38
+ };
39
+ export type RunMetrics = {
40
+ version: 1;
41
+ scope: "candidate";
42
+ /** False for constructed controls or incomplete durable execution history. */
43
+ complete: boolean;
44
+ sessions: number;
45
+ requests: {
46
+ started: number;
47
+ succeeded: number;
48
+ failed: number;
49
+ retries: number;
50
+ };
51
+ tokens: Accounting["tokens"] | null;
52
+ cost: Cost;
53
+ tools: ToolMetrics & { byName: Record<string, ToolMetrics> };
54
+ compactions: { started: number; completed: number; failed: number };
55
+ timing: {
56
+ elapsedMs: number | null;
57
+ modelActiveMs: number;
58
+ /** Output tokens / model-active seconds; overlapping requests count once. */
59
+ outputTokensPerSecond: number | null;
60
+ };
61
+ evidence: EvidenceRef;
62
+ };
63
+
64
+ export type RecordedEvent = {
65
+ sequence: number;
66
+ time: string;
67
+ event: OpenCodeStreamEvent;
68
+ };
69
+ export type RecordedMessage = {
70
+ sessionID: string;
71
+ message: SessionMessageInfo;
72
+ };
73
+ export type RecordedFile = {
74
+ path: string;
75
+ bytes: number;
76
+ sha256?: string;
77
+ symlink?: string;
78
+ };
79
+ export type Revision = "initial" | "final";
80
+
81
+ export interface JudgeContext {
82
+ /** Missing response text is normalized to an empty string. */
83
+ readonly response: { readonly text: string };
84
+ readonly prompt: string;
85
+ /** Null for constructed evidence that did not execute a candidate. */
86
+ readonly run: Readonly<EvalRun> | null;
87
+ readonly metrics: Readonly<RunMetrics>;
88
+ readonly recording: {
89
+ readonly evidence: EvidenceRef;
90
+ readonly sessionID: string | null;
91
+ readonly coverage: "recorded-session" | "recorded-prefix";
92
+ events(filter?: { sessionID?: string; type?: string }): RecordedEvent[];
93
+ tools(filter?: { sessionID?: string; name?: string }): ToolCall[];
94
+ sessions(): Promise<SessionInfo[]>;
95
+ /** Full projected history, including messages before compaction. */
96
+ messages(sessionID?: string): Promise<RecordedMessage[]>;
97
+ export(sessionID?: string): Promise<SessionTransferData>;
98
+ };
99
+ readonly workspace: {
100
+ files(revision?: Revision): RecordedFile[];
101
+ read(path: string, revision?: Revision): Promise<Uint8Array>;
102
+ text(path: string, revision?: Revision): Promise<string>;
103
+ diff(
104
+ path: string,
105
+ ): Promise<{ initial: string | null; final: string | null }>;
106
+ /** Restore a disposable snapshot for author-owned verification commands. */
107
+ materialize(revision?: Revision): Promise<string>;
108
+ };
109
+ readonly native: {
110
+ readonly version: string | null;
111
+ readonly readerVersion: string;
112
+ /** Read-only SQL access to a verified, disposable native database copy. */
113
+ database(): Promise<Database>;
114
+ /** The pinned OpenCode API/SDK over a separate disposable database copy. */
115
+ sdk(): Promise<OpenCode.Interface>;
116
+ schema(): Promise<typeof import("@opencode/schema")>;
117
+ };
118
+ }
119
+
120
+ /** Frozen judging source and dependency identity, kept in host-side run records. */
121
+ export type CodeJudgeDefinition = {
122
+ file: string;
123
+ hash: string;
124
+ source: string;
125
+ sourceMap: string;
126
+ dependencies: Record<string, string>;
127
+ };
128
+ export type CodeJudgeExecution = {
129
+ state: "completed" | "failed" | "timed_out";
130
+ startedAt: string;
131
+ completedAt: string;
132
+ elapsedMs: number;
133
+ /** Original JSON, before boolean score normalization. */
134
+ output?: JsonValue;
135
+ scores?: Record<string, number | null>;
136
+ metrics?: RunMetrics;
137
+ error?: string;
138
+ sourceHash: string;
139
+ stdout: string;
140
+ stderr: string;
141
+ };
package/src/judgment.ts CHANGED
@@ -1,40 +1,49 @@
1
- import type { MetricDefinition, MetricJudgment } from "./types";
1
+ import type { CriterionDefinition, CriterionScore } from "./types";
2
2
 
3
- export const JUDGE_PROTOCOL = 3;
3
+ export const JUDGE_PROTOCOL = 4;
4
4
  export const isScored = (value: unknown): value is number =>
5
5
  typeof value === "number" &&
6
6
  Number.isFinite(value) &&
7
7
  value >= 0 &&
8
8
  value <= 1;
9
9
 
10
- /** Every rubric explicitly declares its metrics. */
11
- export function rubricMetrics(rubric: string): MetricDefinition[] {
12
- const metrics = [
13
- ...rubric.matchAll(/^## Metric: ([a-z][a-z0-9_]*)[ \t]*[—–-][ \t]*(.+)$/gm),
10
+ /** The author declares Markdown criteria; code functions return their own scores. */
11
+ export function rubricCriteria(rubric: string): CriterionDefinition[] {
12
+ if (/^## Metric:/m.test(rubric))
13
+ throw new Error("Use ## Criterion: id — Label for rubric declarations");
14
+ const criteria = [
15
+ ...rubric.matchAll(
16
+ /^## Criterion: ([a-z][a-z0-9_]*)[ \t]*[—–-][ \t]*(.+)$/gm,
17
+ ),
14
18
  ].map((match) => ({
15
19
  id: match[1],
16
20
  name: match[2].trim(),
17
21
  }));
18
- if (new Set(metrics.map((metric) => metric.id)).size !== metrics.length)
19
- throw new Error("Metric IDs must be unique within judge.md");
20
22
  if (
21
- !metrics.length ||
22
- metrics.some((metric) => !metric.name) ||
23
- metrics.length !== (rubric.match(/^## Metric:/gm)?.length ?? 0)
23
+ new Set(criteria.map((criterion) => criterion.id)).size !== criteria.length
24
+ )
25
+ throw new Error("Criterion IDs must be unique within judge.md");
26
+ if (
27
+ !criteria.length ||
28
+ criteria.some((criterion) => !criterion.name) ||
29
+ criteria.length !== (rubric.match(/^## Criterion:/gm)?.length ?? 0)
24
30
  )
25
31
  throw new Error(
26
- "Declare every metric as ## Metric: id — Label in judge.md",
32
+ "Declare every criterion as ## Criterion: id — Label in judge.md",
27
33
  );
28
- return metrics;
34
+ return criteria;
29
35
  }
30
36
 
31
37
  /** Equal weighting within an eval; no task-specific policy is implemented here.
32
38
  * https://arxiv.org/html/2607.07946#S5.SS3 (equal task weighting)
33
39
  */
34
- export function metricMean(
35
- metrics: readonly Pick<MetricJudgment, "value">[],
40
+ export function criterionMean(
41
+ scores: Readonly<Record<string, Pick<CriterionScore, "value">>>,
36
42
  ): number | null {
37
- return metrics.length && metrics.every((metric) => isScored(metric.value))
38
- ? metrics.reduce((sum, metric) => sum + metric.value!, 0) / metrics.length
43
+ const criteria = Object.values(scores);
44
+ return criteria.length &&
45
+ criteria.every((criterion) => isScored(criterion.value))
46
+ ? criteria.reduce((sum, criterion) => sum + criterion.value!, 0) /
47
+ criteria.length
39
48
  : null;
40
49
  }
package/src/types.ts CHANGED
@@ -4,6 +4,11 @@ import type {
4
4
  ConfigEntry,
5
5
  AgentInfo,
6
6
  } from "@opencode/client";
7
+ import type {
8
+ CodeJudgeDefinition,
9
+ CodeJudgeExecution,
10
+ RunMetrics,
11
+ } from "./judge-context";
7
12
  export type OpenCodeStreamEvent = OpenCodeEvent | SessionLogItem;
8
13
 
9
14
  export const CANDIDATE_TIMEOUT_MS = 45 * 60 * 1000;
@@ -13,18 +18,22 @@ export type ProviderDefinitions = NonNullable<
13
18
  Extract<ConfigEntry, { type: "document" }>["info"]["providers"]
14
19
  >;
15
20
  export type SessionState =
16
- "running" | "completed" | "stopped" | "failed" | "timed_out";
21
+ | "running"
22
+ | "completed"
23
+ | "stopped"
24
+ | "failed"
25
+ | "timed_out";
17
26
  export type Stage = "candidate" | "judge";
18
27
 
19
28
  export type Judge = {
20
- model: ModelRef;
29
+ model?: ModelRef;
21
30
  timeoutMs?: number;
22
31
  websearch?: "exa" | false;
23
32
  };
24
33
  export type Benchmark = {
25
34
  name?: string;
26
35
  models: readonly ModelRef[];
27
- judge: Judge;
36
+ judge?: Judge;
28
37
  repetitions?: number;
29
38
  concurrency?: number;
30
39
  candidate?: {
@@ -48,7 +57,8 @@ export type MonitorPolicy = {
48
57
  export type Eval = {
49
58
  /** Let the host judge stop execution once the criterion is conclusively decided. */
50
59
  earlyStop?:
51
- boolean | (Partial<MonitorPolicy> & { onlyModels?: readonly ModelRef[] });
60
+ | boolean
61
+ | (Partial<MonitorPolicy> & { onlyModels?: readonly ModelRef[] });
52
62
  workspace?: {
53
63
  repository?: string;
54
64
  /** Readable file overlays committed in order to the named refs, on the host. */
@@ -69,15 +79,17 @@ export type EvalDefinition = {
69
79
  settings: Eval;
70
80
  sourceHash: string;
71
81
  judgeHash: string;
72
- /** Declared by `## Metric: id — Label` headings in judge.md. */
73
- metrics: MetricDefinition[];
82
+ /** Criteria declared in judge.md; code-defined IDs are discovered from results. */
83
+ criteria: CriterionDefinition[];
84
+ /** A frozen, bundled code judge; never sent to the candidate. */
85
+ code?: CodeJudgeDefinition;
74
86
  name: string;
75
87
  };
76
88
  export type BenchmarkDefinition = {
77
89
  name: string;
78
90
  directory: string;
79
91
  models: ModelRef[];
80
- judge: Required<Judge>;
92
+ judge: { model?: ModelRef; timeoutMs: number; websearch: "exa" | false };
81
93
  repetitions: number;
82
94
  concurrency: number;
83
95
  candidate: {
@@ -113,6 +125,7 @@ export type SessionArchive = {
113
125
  };
114
126
  export type ToolCall = {
115
127
  id: string;
128
+ sessionID?: string;
116
129
  name: string;
117
130
  assistantMessageId: string;
118
131
  status: "preparing" | "called" | "succeeded" | "failed";
@@ -186,44 +199,49 @@ export type EvalRun = {
186
199
  elapsedMs?: number;
187
200
  evidence?: EvidenceRef;
188
201
  session?: SessionArchive;
202
+ /** Candidate-only observations, independent of rubric scores. */
203
+ metrics?: RunMetrics;
189
204
  error?: string;
190
205
  replaces?: string;
191
206
  stop?: EvalStop;
192
207
  };
193
- export type MetricDefinition = { id: string; name: string };
208
+ export type CriterionDefinition = { id: string; name: string };
194
209
  export type EvidenceCitation = (
195
210
  | { kind: "response" }
196
- | { kind: "tool" | "message" | "event"; id: string }
211
+ | { kind: "recording" }
212
+ | { kind: "tool" | "message" | "event" | "metric"; id: string }
197
213
  | { kind: "artifact"; path: string; revision: "initial" | "final" }
198
214
  ) & { quote?: string; offset?: number };
199
- export type MetricJudgment = {
200
- id: string;
201
- value: 0 | 1 | null;
215
+ export type CriterionScore = {
216
+ value: number | null;
202
217
  reason: string;
203
218
  evidence: EvidenceCitation[];
204
219
  sources?: string[];
220
+ source: "judge.md" | "judge.ts";
205
221
  };
206
- /** value is the equal-weight metric mean, or null if any metric is unknown. */
222
+ /** value is the equal-weight criterion mean, or null if any score is unknown. */
207
223
  export type Judgment = {
208
224
  value: number | null;
209
225
  reason: string;
210
- metrics: MetricJudgment[];
226
+ scores: Record<string, CriterionScore>;
211
227
  };
212
228
  export type JudgeRunInput = {
213
229
  evalRunId: string;
214
230
  evidence: EvidenceRef;
215
231
  rubric: string;
216
232
  /** Shared native agent profile used for this judgment. */
217
- agent: Pick<AgentInfo, "id" | "mode" | "description" | "permissions"> & {
233
+ agent?: Pick<AgentInfo, "id" | "mode" | "description" | "permissions"> & {
218
234
  system: string;
219
235
  };
220
- model: ModelRef;
236
+ model?: ModelRef;
237
+ kind: "llm" | "code" | "hybrid";
238
+ code?: CodeJudgeDefinition;
221
239
  judgeHash: string;
222
240
  timeoutMs: number;
223
241
  websearch: "exa" | false;
224
242
  mode: "monitor" | "final";
225
243
  runtimeHash: string;
226
- metrics: MetricDefinition[];
244
+ criteria: CriterionDefinition[];
227
245
  protocol: number;
228
246
  monitor?: MonitorPolicy;
229
247
  };
@@ -237,6 +255,7 @@ export type JudgeRun = {
237
255
  archiveStartedAt?: string;
238
256
  judgment?: Judgment;
239
257
  session?: SessionArchive;
258
+ code?: CodeJudgeExecution;
240
259
  error?: string;
241
260
  activity?: "watching" | "queued" | "checking" | "finalizing";
242
261
  decisionCheckId?: string;