evalkit-py 0.2.0.dev12__py3-none-any.whl

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 (371) hide show
  1. evalkit/__init__.py +0 -0
  2. evalkit/api/__init__.py +0 -0
  3. evalkit/api/access.py +74 -0
  4. evalkit/api/agents.py +159 -0
  5. evalkit/api/app.py +360 -0
  6. evalkit/api/auth.py +225 -0
  7. evalkit/api/cli_dist.py +10 -0
  8. evalkit/api/datasets.py +169 -0
  9. evalkit/api/deps.py +79 -0
  10. evalkit/api/download.py +15 -0
  11. evalkit/api/evaluators.py +121 -0
  12. evalkit/api/experiments.py +616 -0
  13. evalkit/api/fixtures.py +95 -0
  14. evalkit/api/harness_check.py +48 -0
  15. evalkit/api/imports.py +180 -0
  16. evalkit/api/limits.py +84 -0
  17. evalkit/api/llm_providers.py +120 -0
  18. evalkit/api/mcp/__init__.py +0 -0
  19. evalkit/api/mcp/auth.py +100 -0
  20. evalkit/api/mcp/descriptions.py +336 -0
  21. evalkit/api/mcp/models.py +259 -0
  22. evalkit/api/mcp/server.py +101 -0
  23. evalkit/api/mcp/tools.py +844 -0
  24. evalkit/api/meta.py +19 -0
  25. evalkit/api/otel.py +350 -0
  26. evalkit/api/pull.py +197 -0
  27. evalkit/api/review.py +271 -0
  28. evalkit/api/runs.py +555 -0
  29. evalkit/api/server_keys.py +44 -0
  30. evalkit/api/tokens.py +51 -0
  31. evalkit/api/trace_imports.py +173 -0
  32. evalkit/api/trace_sources.py +49 -0
  33. evalkit/api/traces.py +196 -0
  34. evalkit/api/users.py +72 -0
  35. evalkit/api/workspaces.py +131 -0
  36. evalkit/bundled/contracts/atif-accepted.json +5 -0
  37. evalkit/bundled/contracts/custom-evaluator-api-v1.json +243 -0
  38. evalkit/bundled/contracts/harness-api-v1.json +938 -0
  39. evalkit/bundled/contracts/span-mapping-v1.json +314 -0
  40. evalkit/bundled/docs/concepts.md +26 -0
  41. evalkit/bundled/docs/config.md +38 -0
  42. evalkit/bundled/docs/harness-api.md +44 -0
  43. evalkit/bundled/docs/install.md +60 -0
  44. evalkit/bundled/docs/login.md +36 -0
  45. evalkit/bundled/docs/mappings.md +136 -0
  46. evalkit/bundled/docs/mcp.md +44 -0
  47. evalkit/bundled/docs/quickstart.md +142 -0
  48. evalkit/bundled/docs/sdk-runs.md +171 -0
  49. evalkit/bundled/docs/tracing.md +171 -0
  50. evalkit/bundled/docs/try-locally.md +288 -0
  51. evalkit/bundled/docs/workspaces.md +45 -0
  52. evalkit/bundled/skills/authoring-eval-cases/SKILL.md +387 -0
  53. evalkit/bundled/skills/authoring-eval-cases/references/overlays.md +83 -0
  54. evalkit/bundled/skills/authoring-eval-cases/references/tool-checks.md +71 -0
  55. evalkit/bundled/skills/connect-traces/SKILL.md +296 -0
  56. evalkit/bundled/skills/connect-traces/references/gen_ai.json +42 -0
  57. evalkit/bundled/skills/connect-traces/references/openinference.json +35 -0
  58. evalkit/bundled/skills/connect-traces/references/span-mapping-schema.md +88 -0
  59. evalkit/bundled/skills/eval-driven-development/SKILL.md +458 -0
  60. evalkit/bundled/skills/eval-driven-development/references/analyze-run.md +97 -0
  61. evalkit/bundled/skills/eval-driven-development/references/diagnose.md +130 -0
  62. evalkit/bundled/skills/eval-driven-development/references/synthesize-cases.md +87 -0
  63. evalkit/bundled/skills/eval-driven-development/references/synthesize.md +165 -0
  64. evalkit/bundled/skills/evalkit-deployment/SKILL.md +332 -0
  65. evalkit/bundled/skills/evalkit-deployment/config.example.yaml +49 -0
  66. evalkit/bundled/skills/evalkit-deployment/docker-compose.yml +51 -0
  67. evalkit/bundled/skills/evalkit-deployment/references/config-and-deploy.md +333 -0
  68. evalkit/bundled/skills/evalkit-deployment/references/harness-api.md +139 -0
  69. evalkit/bundled/skills/evalkit-deployment/try/.env.example +11 -0
  70. evalkit/bundled/skills/evalkit-deployment/try/agent.py +131 -0
  71. evalkit/bundled/skills/evalkit-deployment/try/cases/acme/balance-sheet/cases.yaml +25 -0
  72. evalkit/bundled/skills/evalkit-deployment/try/cases/acme/income-statement/cases.yaml +43 -0
  73. evalkit/bundled/skills/evalkit-deployment/try/config.yaml +17 -0
  74. evalkit/bundled/skills/evalkit-deployment/try/docker-compose.yml +82 -0
  75. evalkit/bundled/skills/evalkit-deployment/try/evalkit.yaml +4 -0
  76. evalkit/bundled/skills/evalkit-deployment/try/mapping.json +42 -0
  77. evalkit/bundled/skills/evalkit-deployment/try/run.py +33 -0
  78. evalkit/bundled/skills/evalkit-usage/SKILL.md +509 -0
  79. evalkit/bundled/skills/evalkit-usage/references/suite-fixtures.md +42 -0
  80. evalkit/bundled/ui/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  81. evalkit/bundled/ui/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  82. evalkit/bundled/ui/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  83. evalkit/bundled/ui/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  84. evalkit/bundled/ui/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  85. evalkit/bundled/ui/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  86. evalkit/bundled/ui/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  87. evalkit/bundled/ui/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  88. evalkit/bundled/ui/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  89. evalkit/bundled/ui/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  90. evalkit/bundled/ui/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  91. evalkit/bundled/ui/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  92. evalkit/bundled/ui/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  93. evalkit/bundled/ui/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  94. evalkit/bundled/ui/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  95. evalkit/bundled/ui/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  96. evalkit/bundled/ui/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  97. evalkit/bundled/ui/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  98. evalkit/bundled/ui/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  99. evalkit/bundled/ui/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  100. evalkit/bundled/ui/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  101. evalkit/bundled/ui/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  102. evalkit/bundled/ui/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  103. evalkit/bundled/ui/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  104. evalkit/bundled/ui/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  105. evalkit/bundled/ui/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  106. evalkit/bundled/ui/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  107. evalkit/bundled/ui/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  108. evalkit/bundled/ui/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  109. evalkit/bundled/ui/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  110. evalkit/bundled/ui/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  111. evalkit/bundled/ui/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  112. evalkit/bundled/ui/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  113. evalkit/bundled/ui/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  114. evalkit/bundled/ui/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  115. evalkit/bundled/ui/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  116. evalkit/bundled/ui/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  117. evalkit/bundled/ui/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  118. evalkit/bundled/ui/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  119. evalkit/bundled/ui/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  120. evalkit/bundled/ui/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  121. evalkit/bundled/ui/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  122. evalkit/bundled/ui/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  123. evalkit/bundled/ui/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  124. evalkit/bundled/ui/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  125. evalkit/bundled/ui/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  126. evalkit/bundled/ui/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  127. evalkit/bundled/ui/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  128. evalkit/bundled/ui/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  129. evalkit/bundled/ui/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  130. evalkit/bundled/ui/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  131. evalkit/bundled/ui/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  132. evalkit/bundled/ui/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  133. evalkit/bundled/ui/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  134. evalkit/bundled/ui/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  135. evalkit/bundled/ui/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  136. evalkit/bundled/ui/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  137. evalkit/bundled/ui/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  138. evalkit/bundled/ui/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  139. evalkit/bundled/ui/assets/abap-08VXUWAP.js +1 -0
  140. evalkit/bundled/ui/assets/apex-BWPQTe0t.js +1 -0
  141. evalkit/bundled/ui/assets/azcli-Bc_sGQ0U.js +1 -0
  142. evalkit/bundled/ui/assets/bat-i0X4ZdIN.js +1 -0
  143. evalkit/bundled/ui/assets/bicep-B5-_aFwp.js +2 -0
  144. evalkit/bundled/ui/assets/cameligo-DMUM7wLl.js +1 -0
  145. evalkit/bundled/ui/assets/clojure-Cm7r79vr.js +1 -0
  146. evalkit/bundled/ui/assets/codicon-DF1abBS2.ttf +0 -0
  147. evalkit/bundled/ui/assets/coffee-Ba7i2nA0.js +1 -0
  148. evalkit/bundled/ui/assets/cpp-C7h46wYY.js +1 -0
  149. evalkit/bundled/ui/assets/csharp-BKxtCVv1.js +1 -0
  150. evalkit/bundled/ui/assets/csp-bTuwJoIa.js +1 -0
  151. evalkit/bundled/ui/assets/css-DIMkf-bt.js +3 -0
  152. evalkit/bundled/ui/assets/css.worker-DwfUZ3fB.js +96 -0
  153. evalkit/bundled/ui/assets/cssMode-C97l1pbB.js +1 -0
  154. evalkit/bundled/ui/assets/cypher-CVaqCwHa.js +1 -0
  155. evalkit/bundled/ui/assets/dart-onAF5SnQ.js +1 -0
  156. evalkit/bundled/ui/assets/dockerfile-DZFCIeNp.js +1 -0
  157. evalkit/bundled/ui/assets/ecl-94qehhXe.js +1 -0
  158. evalkit/bundled/ui/assets/editor-DjpsE8to.css +1 -0
  159. evalkit/bundled/ui/assets/editor.api-NTesIxw5.js +908 -0
  160. evalkit/bundled/ui/assets/editor.worker-CRz__AKW.js +33 -0
  161. evalkit/bundled/ui/assets/elixir-6RTg0lbw.js +1 -0
  162. evalkit/bundled/ui/assets/flow9-C5_-GSwl.js +1 -0
  163. evalkit/bundled/ui/assets/freemarker2-BWqEFagp.js +3 -0
  164. evalkit/bundled/ui/assets/fsharp-C8Ef5oNN.js +1 -0
  165. evalkit/bundled/ui/assets/go-C-y9NEjX.js +1 -0
  166. evalkit/bundled/ui/assets/graphql-fmXr3nnJ.js +1 -0
  167. evalkit/bundled/ui/assets/handlebars-DkIF-whN.js +1 -0
  168. evalkit/bundled/ui/assets/hcl-CpzslTdj.js +1 -0
  169. evalkit/bundled/ui/assets/html-C_rpeQXJ.js +1 -0
  170. evalkit/bundled/ui/assets/html.worker-D9ugpX4y.js +509 -0
  171. evalkit/bundled/ui/assets/htmlMode-B0YIq3DF.js +1 -0
  172. evalkit/bundled/ui/assets/index-Cw-jBH6M.js +736 -0
  173. evalkit/bundled/ui/assets/index-DKtoQZtm.css +1 -0
  174. evalkit/bundled/ui/assets/ini-sBoK_t0W.js +1 -0
  175. evalkit/bundled/ui/assets/java-BEtHBSE6.js +1 -0
  176. evalkit/bundled/ui/assets/javascript-D4EGhYA6.js +1 -0
  177. evalkit/bundled/ui/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  178. evalkit/bundled/ui/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  179. evalkit/bundled/ui/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  180. evalkit/bundled/ui/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  181. evalkit/bundled/ui/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  182. evalkit/bundled/ui/assets/json.worker-CV9fqkUp.js +65 -0
  183. evalkit/bundled/ui/assets/jsonMode-pQjSfIH6.js +7 -0
  184. evalkit/bundled/ui/assets/julia-Bri6UV-V.js +1 -0
  185. evalkit/bundled/ui/assets/kotlin-BOotOW0E.js +1 -0
  186. evalkit/bundled/ui/assets/less-B9JPFI3C.js +2 -0
  187. evalkit/bundled/ui/assets/lexon-CfSJPG6W.js +1 -0
  188. evalkit/bundled/ui/assets/liquid-DbrvoYjD.js +1 -0
  189. evalkit/bundled/ui/assets/lspLanguageFeatures-D0B7cH6y.js +4 -0
  190. evalkit/bundled/ui/assets/lua-CsQS60Ue.js +1 -0
  191. evalkit/bundled/ui/assets/m3-D-oSqn_W.js +1 -0
  192. evalkit/bundled/ui/assets/markdown-Cimd5fb3.js +1 -0
  193. evalkit/bundled/ui/assets/mdx-B0HrujLR.js +1 -0
  194. evalkit/bundled/ui/assets/mips-CIPQ_RoX.js +1 -0
  195. evalkit/bundled/ui/assets/monacoEditor-DsoPncxW.js +68 -0
  196. evalkit/bundled/ui/assets/monacoEditor-n7clI0si.css +1 -0
  197. evalkit/bundled/ui/assets/msdax-DauUninz.js +1 -0
  198. evalkit/bundled/ui/assets/mysql-SOo6toE5.js +1 -0
  199. evalkit/bundled/ui/assets/objective-c-FvmIjYaQ.js +1 -0
  200. evalkit/bundled/ui/assets/pascal-DrH0SRf2.js +1 -0
  201. evalkit/bundled/ui/assets/pascaligo-D-ptJ9y-.js +1 -0
  202. evalkit/bundled/ui/assets/perl-oz_6vUea.js +1 -0
  203. evalkit/bundled/ui/assets/pgsql-DTj74zXo.js +1 -0
  204. evalkit/bundled/ui/assets/php-nr791fC2.js +1 -0
  205. evalkit/bundled/ui/assets/pla-CopQ2nXW.js +1 -0
  206. evalkit/bundled/ui/assets/postiats-43DmfD33.js +1 -0
  207. evalkit/bundled/ui/assets/powerquery-D3hlyOfw.js +1 -0
  208. evalkit/bundled/ui/assets/powershell-DmHpPYUd.js +1 -0
  209. evalkit/bundled/ui/assets/protobuf-C531GsRP.js +2 -0
  210. evalkit/bundled/ui/assets/pug-Z5eAx3Zn.js +1 -0
  211. evalkit/bundled/ui/assets/python-CieHVM9n.js +1 -0
  212. evalkit/bundled/ui/assets/qsharp-DkqhCAOL.js +1 -0
  213. evalkit/bundled/ui/assets/r-BwWrilGY.js +1 -0
  214. evalkit/bundled/ui/assets/razor-sLewSMyp.js +1 -0
  215. evalkit/bundled/ui/assets/redis-ClamHrr6.js +1 -0
  216. evalkit/bundled/ui/assets/redshift-DT7zqm-g.js +1 -0
  217. evalkit/bundled/ui/assets/restructuredtext-BYgofb2h.js +1 -0
  218. evalkit/bundled/ui/assets/ruby-DezsRK8O.js +1 -0
  219. evalkit/bundled/ui/assets/rust-DdL9SqIa.js +1 -0
  220. evalkit/bundled/ui/assets/sb-CcwsVR0C.js +1 -0
  221. evalkit/bundled/ui/assets/scala-DHpiXF5c.js +1 -0
  222. evalkit/bundled/ui/assets/scheme-BeGwcela.js +1 -0
  223. evalkit/bundled/ui/assets/scss-gp-XZpBa.js +3 -0
  224. evalkit/bundled/ui/assets/shell-CC2rA5mh.js +1 -0
  225. evalkit/bundled/ui/assets/solidity-BEEn4gHE.js +1 -0
  226. evalkit/bundled/ui/assets/sophia-CRfGWb83.js +1 -0
  227. evalkit/bundled/ui/assets/sparql-D_Lu-MrJ.js +1 -0
  228. evalkit/bundled/ui/assets/sql-NEE52Syq.js +1 -0
  229. evalkit/bundled/ui/assets/st-DbInun42.js +1 -0
  230. evalkit/bundled/ui/assets/swift-Bxkupp3x.js +1 -0
  231. evalkit/bundled/ui/assets/systemverilog-Bz4Y3fRF.js +1 -0
  232. evalkit/bundled/ui/assets/tcl-DISqw1ZD.js +1 -0
  233. evalkit/bundled/ui/assets/ts.worker-DIAQkoB3.js +67741 -0
  234. evalkit/bundled/ui/assets/tsMode-BcVQ1nu0.js +11 -0
  235. evalkit/bundled/ui/assets/twig-De2hgUGE.js +1 -0
  236. evalkit/bundled/ui/assets/typescript-CUvNWd9p.js +1 -0
  237. evalkit/bundled/ui/assets/typespec-B8J7ngcE.js +1 -0
  238. evalkit/bundled/ui/assets/vb-DV3o63ZY.js +1 -0
  239. evalkit/bundled/ui/assets/wgsl-DpFanUEy.js +298 -0
  240. evalkit/bundled/ui/assets/workers-CwpYQtzp.js +1 -0
  241. evalkit/bundled/ui/assets/xml-C1HnXMdF.js +1 -0
  242. evalkit/bundled/ui/assets/yaml-D7Ey3HQu.js +1 -0
  243. evalkit/bundled/ui/favicon.svg +6 -0
  244. evalkit/bundled/ui/index.html +14 -0
  245. evalkit/cli/__init__.py +0 -0
  246. evalkit/cli/admin_commands.py +590 -0
  247. evalkit/cli/client.py +67 -0
  248. evalkit/cli/init_server.py +165 -0
  249. evalkit/cli/local_run.py +195 -0
  250. evalkit/cli/main.py +1365 -0
  251. evalkit/cli/runs_commands.py +539 -0
  252. evalkit/cli/server_commands.py +130 -0
  253. evalkit/cli/skill_targets.py +43 -0
  254. evalkit/cli/tokens_commands.py +52 -0
  255. evalkit/cli/traces_commands.py +332 -0
  256. evalkit/cli/update.py +85 -0
  257. evalkit/client/__init__.py +0 -0
  258. evalkit/client/agents.py +25 -0
  259. evalkit/client/api.py +193 -0
  260. evalkit/client/blob.py +104 -0
  261. evalkit/client/connection.py +88 -0
  262. evalkit/client/evaluators.py +11 -0
  263. evalkit/client/sessions.py +17 -0
  264. evalkit/client/store.py +139 -0
  265. evalkit/client/summary.py +46 -0
  266. evalkit/client/sync.py +198 -0
  267. evalkit/config.py +227 -0
  268. evalkit/contracts/__init__.py +0 -0
  269. evalkit/contracts/atif.py +115 -0
  270. evalkit/contracts/cases.py +456 -0
  271. evalkit/contracts/custom_evaluator.py +58 -0
  272. evalkit/contracts/enums.py +86 -0
  273. evalkit/contracts/esf.py +120 -0
  274. evalkit/contracts/harness.py +281 -0
  275. evalkit/contracts/notes.json +4 -0
  276. evalkit/contracts/notes.py +7 -0
  277. evalkit/contracts/settings.py +41 -0
  278. evalkit/core/__init__.py +0 -0
  279. evalkit/core/access.py +75 -0
  280. evalkit/core/agents.py +65 -0
  281. evalkit/core/blob.py +46 -0
  282. evalkit/core/capabilities.py +36 -0
  283. evalkit/core/costmap.py +90 -0
  284. evalkit/core/custom_eval.py +50 -0
  285. evalkit/core/data/cost_map.json +81546 -0
  286. evalkit/core/endpoints.py +31 -0
  287. evalkit/core/evaluators/__init__.py +29 -0
  288. evalkit/core/evaluators/base.py +121 -0
  289. evalkit/core/evaluators/gauges.py +84 -0
  290. evalkit/core/evaluators/presentation.py +166 -0
  291. evalkit/core/evaluators/response_time.py +21 -0
  292. evalkit/core/evaluators/rubrics.py +494 -0
  293. evalkit/core/evaluators/tool_trajectory.py +187 -0
  294. evalkit/core/evaluators/trajectory_rubrics.py +198 -0
  295. evalkit/core/fixtures.py +57 -0
  296. evalkit/core/harness.py +227 -0
  297. evalkit/core/harness_check.py +191 -0
  298. evalkit/core/importer.py +257 -0
  299. evalkit/core/judge.py +78 -0
  300. evalkit/core/lint.py +265 -0
  301. evalkit/core/overlays.py +76 -0
  302. evalkit/core/paths.py +25 -0
  303. evalkit/core/promotion.py +94 -0
  304. evalkit/core/pull.py +198 -0
  305. evalkit/core/python_eval.py +59 -0
  306. evalkit/core/remote_evaluators.py +32 -0
  307. evalkit/core/review.py +220 -0
  308. evalkit/core/run_digest.py +421 -0
  309. evalkit/core/runner.py +995 -0
  310. evalkit/core/scorecard.py +255 -0
  311. evalkit/core/traces/__init__.py +0 -0
  312. evalkit/core/traces/convert.py +336 -0
  313. evalkit/core/traces/importer.py +113 -0
  314. evalkit/core/traces/mapping.py +385 -0
  315. evalkit/core/traces/poll.py +38 -0
  316. evalkit/core/traces/raw.py +21 -0
  317. evalkit/core/traces/sessions.py +172 -0
  318. evalkit/core/traces/settle.py +14 -0
  319. evalkit/core/traces/sources/__init__.py +19 -0
  320. evalkit/core/traces/sources/base.py +25 -0
  321. evalkit/core/traces/sources/phoenix.py +121 -0
  322. evalkit/core/trajectory.py +248 -0
  323. evalkit/core/workspace.py +30 -0
  324. evalkit/credentials.py +119 -0
  325. evalkit/db/__init__.py +0 -0
  326. evalkit/db/agents.py +289 -0
  327. evalkit/db/alembic/env.py +90 -0
  328. evalkit/db/alembic/script.py.mako +28 -0
  329. evalkit/db/alembic/versions/0011_baseline.py +1002 -0
  330. evalkit/db/alembic/versions/0012_ticket_token_kind.py +27 -0
  331. evalkit/db/alembic/versions/0013_keys_and_llm_providers.py +67 -0
  332. evalkit/db/cases.py +608 -0
  333. evalkit/db/crypto.py +12 -0
  334. evalkit/db/evaluators.py +156 -0
  335. evalkit/db/experiments.py +363 -0
  336. evalkit/db/fixture_blobs.py +91 -0
  337. evalkit/db/keys.py +78 -0
  338. evalkit/db/llm_providers.py +176 -0
  339. evalkit/db/locks.py +6 -0
  340. evalkit/db/mappings.py +168 -0
  341. evalkit/db/models.py +567 -0
  342. evalkit/db/promotion.py +271 -0
  343. evalkit/db/rekey.py +46 -0
  344. evalkit/db/review.py +250 -0
  345. evalkit/db/review_state.py +50 -0
  346. evalkit/db/runs.py +533 -0
  347. evalkit/db/scorecard.py +300 -0
  348. evalkit/db/session.py +71 -0
  349. evalkit/db/sessions.py +90 -0
  350. evalkit/db/spans.py +360 -0
  351. evalkit/db/store.py +209 -0
  352. evalkit/db/tokens.py +100 -0
  353. evalkit/db/trace_imports.py +308 -0
  354. evalkit/db/trace_sources.py +131 -0
  355. evalkit/db/users.py +186 -0
  356. evalkit/db/workspaces.py +232 -0
  357. evalkit/paths.py +33 -0
  358. evalkit/sdk/__init__.py +29 -0
  359. evalkit/sdk/binding.py +69 -0
  360. evalkit/sdk/evaluators.py +56 -0
  361. evalkit/sdk/runner.py +957 -0
  362. evalkit/sdk/tracing.py +166 -0
  363. evalkit/store/__init__.py +0 -0
  364. evalkit/store/base.py +354 -0
  365. evalkit/store/blob.py +69 -0
  366. evalkit/version.py +44 -0
  367. evalkit_py-0.2.0.dev12.dist-info/METADATA +205 -0
  368. evalkit_py-0.2.0.dev12.dist-info/RECORD +371 -0
  369. evalkit_py-0.2.0.dev12.dist-info/WHEEL +4 -0
  370. evalkit_py-0.2.0.dev12.dist-info/entry_points.txt +2 -0
  371. evalkit_py-0.2.0.dev12.dist-info/licenses/LICENSE +661 -0
@@ -0,0 +1,387 @@
1
+ ---
2
+ name: authoring-eval-cases
3
+ description: Authors evalkit eval cases — interviews the stakeholder in plain domain language, verifies ground truth, anchors dates, and writes blackbox YAML cases asserted as answer rubrics (plus trajectory rubrics and presentation checks where they matter). Use when creating or editing eval cases, turning a described scenario or production issue into a case, or reviewing case quality.
4
+ ---
5
+
6
+ # Authoring eval cases
7
+
8
+ A case is a contract: a realistic input plus what any observer could check
9
+ about a correct response. Cases are **blackbox** — no tool names, skill names,
10
+ or any harness vocabulary anywhere in the case; that is what keeps a case
11
+ portable across harnesses, and `evalkit lint` enforces it as an error on the
12
+ question and every rubric. Checks that do know the harness's internals go in
13
+ evaluator config, never in that text:
14
+
15
+ - The built-in tool checks (`required_tools_called`, `tool_trajectory_match`)
16
+ go straight in the case when it lives in the client's own harness-specific
17
+ dataset, or in an overlay on a portable case. See
18
+ [`references/tool-checks.md`](references/tool-checks.md).
19
+ - Checks scored by the client's own Custom Evaluator API endpoints go in an
20
+ overlay. See [`references/overlays.md`](references/overlays.md).
21
+
22
+ ## Terms
23
+
24
+ | Term | Meaning |
25
+ |---|---|
26
+ | Case | One eval question: input, expected behaviour, evaluator config. One YAML document. |
27
+ | Dataset | A named set of cases in the evalkit store; a YAML file or directory syncs into one. |
28
+ | Split | A selectable subset of a dataset, built from case tags. |
29
+ | Rubric | One typed sentence in `answer_rubrics` asserting something a correct answer contains. |
30
+ | Rubric type | `factual_retrieval`, `derived_computation`, or `analysis_interpretation`; drives the per-type rates. |
31
+ | Source | The attribution a `factual_retrieval` rubric requires; graded on its own citation axis, never in the content score. |
32
+ | Trajectory rubric | One sentence in `trajectory_rubrics.rubrics`: a checkpoint — an intermediate value or a process step — the recorded trajectory or final answer must show. |
33
+ | Overlay | A client extension of a case by id, attaching custom-evaluator config or the built-in tool checks — see `references/overlays.md`. |
34
+ | Tool check | A built-in evaluator over the recorded tool calls: `required_tools_called` or `tool_trajectory_match` — see `references/tool-checks.md`. |
35
+ | Judge | The LLM an evaluator uses to grade; configured on the deployment, never in the case. |
36
+ | Red / green case | Red: the case fails against the current agent; green: it passes. For a capability gap red is the expected starting state — ship it red. |
37
+
38
+ ## Interviewing the case author
39
+
40
+ Route here when the case originates from a stakeholder description or a
41
+ high-level intent — the author knows the domain and the correct behaviour, not
42
+ the agent's internals. The same protocol serves a developer authoring
43
+ in-session and a relayed exchange (e.g. a chat thread via a bot): every
44
+ clarifying round is a plain message, so the flow works headlessly.
45
+
46
+ Fill every slot below before writing YAML. Ask clarifying questions in batches
47
+ of at most 3 per round, in plain domain language — never mention tools,
48
+ skills, or agent internals to the author (a rule of this protocol, not a
49
+ general conversational rule). Stop asking when the slots are full, not before.
50
+
51
+ | Slot | Becomes | Notes |
52
+ |---|---|---|
53
+ | The scenario, in the author's words | — | The raw material for everything below. |
54
+ | A realistic user phrasing | `input.question` | Derive it FROM the scenario and play it back for confirmation — authors are not expected to produce verbatim input. |
55
+ | A date anchor in the input | part of `input.question` | Whenever the answer is time-sensitive, anchor the question itself ("as of 30 September 2025") so pinned ground truth cannot drift under the case. |
56
+ | What a correct answer contains | `answer_rubrics` | Concrete values (or the correct honest negative), dated — see the rubric sections below. |
57
+ | The intermediate values and visible steps the work should show | `trajectory_rubrics` | Checkpoint sentences — see below. |
58
+ | Presentation requirements, if any | `presentation_judge` | Units shown, columns present, an artifact relayed rather than restated. |
59
+ | A latency bound, if the case has one | `max_response_time` | Seconds; settable file-wide via `defaults.max_response_time`. |
60
+
61
+ For agents that return a structured `output` (classifiers, taggers,
62
+ extractors) instead of prose: `answer_rubrics` still works, since the judge
63
+ reads the output as JSON text, so a rubric like "The label is EVENT" can be
64
+ graded. Skip `presentation_judge`, because layout and units mean nothing for
65
+ JSON. Exact field checks belong in a custom evaluator that reads
66
+ `run.output`.
67
+
68
+ ## Ground-truth verification
69
+
70
+ Do not accept vague expectations. Verify the values yourself from whatever
71
+ verified data source is available in the session (the client's data tools,
72
+ primary documents):
73
+
74
+ 1. Query the relevant data for the case's anchored date.
75
+ 2. Show the author the concrete values ("I see revenue of X and margin of Y
76
+ for that quarter — is that what the agent should show?").
77
+ 3. Pin the confirmed values as rubrics with the as-of date.
78
+
79
+ When no verified source in the session can produce the values, ask the author
80
+ for the exact numbers — a number the author supplies and stands behind is
81
+ verified ground truth; a model-asserted one never is. If neither you nor the
82
+ author can produce the values, tag the case `needs-ground-truth`, keep the
83
+ expectation as written, and keep the case out of the main runs — never soften
84
+ a case to make it passable.
85
+
86
+ ## Writing answer rubrics
87
+
88
+ `answer_rubrics` is the output evaluator: everything the answer must contain,
89
+ one flat list of typed sentences. Field shapes are validated by `evalkit lint`;
90
+ the sections below are about judgement — what to assert, which type it is, and
91
+ how to phrase it.
92
+
93
+ ```yaml
94
+ evaluators:
95
+ output:
96
+ answer_rubrics:
97
+ rubrics:
98
+ - rubric: "States that the company's actual Q3 FY2024 non-GAAP gross margin was 28.1%."
99
+ type: factual_retrieval
100
+ source: "Q3 FY2024 results"
101
+ - rubric: "Calculates that the company beat its guidance midpoint by 160 bps (±10 bps),
102
+ measuring against the 26.5% midpoint rather than the endpoints of the range."
103
+ type: derived_computation
104
+ ```
105
+
106
+ `source` is optional and only valid on `factual_retrieval`. `type` is required.
107
+ There is no `points`, no `tolerance` field, and no judge model override — the
108
+ judge comes from the deployment config.
109
+
110
+ ### Assert only what the question asks
111
+
112
+ A rubric holds the answer to the question as asked, not to the author's
113
+ unstated wishes. An expectation the question never expressed belongs in a
114
+ rubric only when it is an obvious implication of the ask or carries strong
115
+ convention (a "compare YoY" question implies both years' figures). Anything
116
+ else is the rubric unfairly penalizing a reasonable answer — if the
117
+ expectation matters, put it in the question.
118
+
119
+ ### Answer rubric types
120
+
121
+ | `type` | The assertion is about |
122
+ |---|---|
123
+ | `factual_retrieval` | anything stated in a source: a value, entity, date, category, classification, or a statement attributed to someone |
124
+ | `derived_computation` | a figure the answer works out rather than looks up, and the method or scope behind it |
125
+ | `analysis_interpretation` | what the figures show — a trend, a ranking, a cause, a driver, a comparison |
126
+
127
+ Apply in order and stop at the first that fits:
128
+
129
+ 1. Is the assertion **quoted from a source** — some document, filing,
130
+ transcript or feed states it, and the work is retrieval plus faithful
131
+ reproduction? → `factual_retrieval`
132
+ 2. Otherwise the answer **produced** it, and no source contains this sentence:
133
+ - a figure it computed, or the method or scope behind one →
134
+ `derived_computation`
135
+ - a statement about what the figures show → `analysis_interpretation`
136
+
137
+ This split is the one that tells you where to look when a case fails: it
138
+ separates "the data never arrived" from "the reasoning was wrong". An
139
+ assertion about **how the answer displays** something — a table, an ordering,
140
+ a unit label — is not an answer rubric at all; it goes under
141
+ `presentation_judge` (see below).
142
+
143
+ ### An `analysis_interpretation` rubric is a reading of the facts, not an opinion
144
+
145
+ Every rubric of this type has one right answer, worked out from facts the
146
+ answer already has: given four quarterly beats, exactly one is the largest.
147
+ Where a question has more than one reasonable answer, **no rubric says which
148
+ answer to reach.** A rubric asks that a point be weighed — "Weighs the FY27
149
+ refinancing wall against the current cash position" — not that the answer
150
+ conclude the bond is overvalued. If grading a rubric would mean the judge
151
+ picking a side in a real disagreement, don't write that rubric, in this type
152
+ or any other.
153
+
154
+ ### Numeric matching is lenient by default
155
+
156
+ A figure matches after unit conversion, and normal rounding of the rubric's
157
+ figure is accepted: against "3,172.6 million", an answer saying "3,173
158
+ million" or "3.17 billion" satisfies the rubric, while "3,180 million" is a
159
+ different figure, not a rounding. Write the plain correct value and let the
160
+ default do its work.
161
+
162
+ State an acceptance criterion in the sentence only when the case wants
163
+ something the default doesn't give — tighter ("exactly 3,172.6 million"),
164
+ wider ("±1 million"), or alternative ("either the standalone or the
165
+ consolidated figure", "any figure between X and Y"). A stated criterion
166
+ replaces the default, and stating it in the sentence keeps it visible to a
167
+ dataset reader.
168
+
169
+ ### How specific to make a `source`
170
+
171
+ `source` asserts that the answer credits the fact to that source. It is graded
172
+ on its own citation axis and never counted in the content score, because
173
+ getting a fact right says nothing about citing it.
174
+
175
+ Write it at the granularity the case cares about. An over-specific source
176
+ string creates failures that are not real: a rubric naming the "earnings
177
+ release" against an answer citing the "earnings call" is a different document,
178
+ so it scores `incorrect` even when the figure appears in both. Where several
179
+ disclosures are acceptable, name the set loosely — "any Q3 FY2024 disclosure".
180
+ Attach a `source` to every `factual_retrieval` rubric whose provenance the
181
+ case actually cares about, not to a token handful.
182
+
183
+ ### Methodology goes in the rubric text
184
+
185
+ A `derived_computation` rubric states its own method inline — the method
186
+ determines the value, so the figure already tests it. Where a case wants the
187
+ method stated explicitly (transparency the answer owes the reader, or two
188
+ methods give the same figure), that is its own `derived_computation` rubric.
189
+ A statement about what a source does or does not report ("X does not report
190
+ segment revenue") is itself a fact, so it is `factual_retrieval`.
191
+
192
+ ### One rubric, one assertion
193
+
194
+ Split anything a reader could grade two ways into two rubrics. A rubric may
195
+ pair two periods where the comparison is the point — that is one comparison,
196
+ not two facts. A rubric bundling a figure with an explanation of it is two
197
+ rubrics.
198
+
199
+ ### Honest negatives are ordinary rubrics
200
+
201
+ Where the correct answer *is* a negative the answer should state, write it as
202
+ a positive rubric: "States that the company does not report free cash flow."
203
+ That grades all three outcomes: claiming a reported figure is `incorrect`,
204
+ saying there is none is `satisfied`, ducking it is `absent`.
205
+
206
+ ### No harness vocabulary
207
+
208
+ The corpus is published independently of any agent, so a rubric never names a
209
+ tool, skill, server, data provider or any other implementation concept. Assert
210
+ what a correct answer contains, not how it was obtained.
211
+
212
+ ### What you get back
213
+
214
+ | Score | Meaning |
215
+ |---|---|
216
+ | `answer_rubric_score` | share of the case's rubrics satisfied — the case's published score, and what `collect --threshold` compares against |
217
+ | `answer_rubric_coverage` | share of rubrics the answer engaged at all |
218
+ | `answer_rubric_accuracy` | of the rubrics it engaged, the share it got right |
219
+ | `answer_rubric_<type>` × 3 | the same recall within one type; skips where the case has no rubrics of that type |
220
+ | `answer_rubric_citation` | of the facts the answer stated, the share correctly attributed |
221
+
222
+ Each rubric gets one of three verdicts — `satisfied`, `incorrect`, `absent` —
223
+ and so does each `source`. The explanation JSON carries the counts, the
224
+ per-type breakdown, the citation block and the full verdict list, which is
225
+ what makes a failure diagnosable: which rubrics were wrong versus silent, what
226
+ the answer said instead, and whether a stated fact was misattributed or merely
227
+ uncited.
228
+
229
+ Every corpus-level number is pooled over rubrics, not averaged over cases, so
230
+ a 16-rubric case carries 16 times the weight of a 1-rubric case. That is also
231
+ why there are no points: a weight only means something next to its siblings,
232
+ and pooling would add a "3" in one case to a "3" in another as though they
233
+ meant the same thing.
234
+
235
+ ## Presentation checks
236
+
237
+ How the answer displays its content — a table with named columns, an ordering,
238
+ units shown, an artifact relayed rather than restated — goes under
239
+ `presentation_judge`, never into `answer_rubrics`. Each entry is a property
240
+ the answer must have, phrased as the property rather than a description of
241
+ the answer having it ("A store count for each fiscal year FY2021–FY2025, as a
242
+ table or a labelled list"); `forbid` entries name properties the answer must
243
+ not have. Correctness of the figures stays in `answer_rubrics` — asserting
244
+ the same thing in both places reweights it rather than making the case
245
+ stricter.
246
+
247
+ ## Writing trajectory rubrics
248
+
249
+ `trajectory_rubrics.rubrics` is a flat list of sentences. Each is a checkpoint
250
+ the recorded trajectory or the final answer must show. The judge sees the
251
+ question, the rubrics, the full ATIF trajectory — tool calls, tool results,
252
+ subagents, and the agent's reasoning where the harness records it — and the
253
+ final answer, and marks each rubric satisfied or unsatisfied on positive
254
+ evidence, citing steps as `main:<step_id>` or `<trajectory_id>:<step_id>`. The
255
+ score is satisfied ÷ total. Order is not graded. The whole trajectory goes to
256
+ the judge in one call, nothing truncated.
257
+
258
+ ```yaml
259
+ evaluators:
260
+ trajectory:
261
+ trajectory_rubrics:
262
+ rubrics:
263
+ - "Retrieves Roku's FY2024 Platform revenue as $3,522,776,000."
264
+ - "Retrieves Roku's FY2023 Platform revenue as $2,994,105,000."
265
+ - "Retrieves the FY2023 restructuring expense inside Platform cost of revenue as $67,032,000."
266
+ - "Calculates FY2023 Platform cost of revenue excluding restructuring as $1,360,514,000."
267
+ - "Calculates FY2023 adjusted Platform gross margin as 45.44% (±0.005pp)."
268
+ - "Calculates FY2024 adjusted Platform gross margin as 46.46% (±0.005pp)."
269
+ - "Computes the margin change from the two adjusted margins, not from the reported ones."
270
+ - "Rounds the final figure to the nearest basis point."
271
+ ```
272
+
273
+ Two kinds of rubric share the list:
274
+
275
+ 1. **Checkpoints with a value** — every input the derivation retrieves and
276
+ every intermediate result it computes, each with its figure. The sentence
277
+ carries the subject, period, unit and value, and a band wherever rounding
278
+ is expected, exactly as an answer rubric does. "Retrieves FY2023 capital
279
+ expenditure as $3,100,000" — not "gathers the cash-flow data".
280
+ 2. **Process steps in plain language** — a step whose evidence is an action
281
+ or a method rather than a figure: "Reads the debt footnote of the 10-Q for
282
+ 27 September 2025", "Uses the guidance midpoint rather than the range
283
+ endpoints", "Rounds the final figure to the nearest basis point".
284
+
285
+ To decompose, work the derivation yourself: one rubric per input retrieved,
286
+ one per intermediate result, then the final figure. Ground-truth verification
287
+ covers every intermediate value the same way it covers the final ones — a
288
+ checkpoint figure you have not verified is a guess dressed as a rubric.
289
+
290
+ When an input is a series or a list — ten years of yields, forty trades, every
291
+ holding in a fund — do not write one rubric per point. Write spot checks: two
292
+ or three specific points with their values (the first, the last, and one that
293
+ is easy to get wrong), plus one rubric on the shape of the whole ("Retrieves
294
+ month-end 10-year G-sec yields for all 120 months from January 2016 to
295
+ December 2025"). A run that fetched the series passes the spot checks; a run
296
+ that fetched the wrong series or half of it fails them.
297
+
298
+ Specific-but-portable is the bar: naming *what* data (which company, which
299
+ metric, which period, which value) stays harness-agnostic — every harness
300
+ fetches data somehow and the recorded steps show it. Only naming *how* (tools,
301
+ skills, servers) breaks portability.
302
+
303
+ The final figure usually appears in both the answer rubrics and the trajectory
304
+ rubrics. That is fine: they are different evaluators in different buckets, one
305
+ asking what was delivered and the other how it was derived. Do not copy the
306
+ rest of the answer list across — the trajectory list is the derivation path.
307
+
308
+ Red flags: a rubric whose text is a dash-separated list of content ("— market
309
+ size, top players, risks, outlook") is several rubrics in disguise; a
310
+ checkpoint with no value where the derivation clearly has one; and an expected
311
+ answer containing values the user did not supply with no rubric saying where
312
+ each comes from.
313
+
314
+ ## Red cases
315
+
316
+ A red case on first run is a finding, not a mistake — for a capability gap,
317
+ red is the expected starting state. Ship it red.
318
+
319
+ ## Attaching files
320
+
321
+ When the question is about a document the agent must read, attach it as a
322
+ fixture rather than pasting its contents:
323
+
324
+ 1. Put the file in the `fixtures` directory named in `evalkit.yaml`, under a
325
+ flat, descriptive filename: the fixture `<key>`
326
+ (`meridian-balance-sheet-fy2025.csv`).
327
+ 2. Declare it once in the suite's `fixtures.yaml` with its `sha256`
328
+ (`shasum -a 256 <file>`) and a `context`: one or two sentences saying what
329
+ the file is, its period, its units and anything about its layout the agent
330
+ needs. This text is prepended to every question that uses the file, so the
331
+ question itself should not describe the file.
332
+ 3. Reference it from the case with `fixtures: [<key>]`. Several cases can
333
+ share one key.
334
+
335
+ Only the registry entry goes into git; the bytes live in the `fixtures`
336
+ directory named in `evalkit.yaml`. `evalkit run` and `evalkit sync` upload
337
+ them to the server, stored by `sha256`, and fail naming any key whose file is
338
+ missing or whose bytes do not match the registry `sha256`. Nobody uploads to
339
+ blob storage by hand. To replace a file, change the
340
+ bytes under the same key and update the `sha256`; the next run re-versions
341
+ every case that uses the key. If the old version matters for comparison, use
342
+ a new key instead.
343
+
344
+ ## Before sync
345
+
346
+ Run `evalkit lint <file-or-dir> --dataset <slug>` and fix every error (warnings
347
+ are advisory). `--dataset` is the dataset you will sync into; it lets the
348
+ server check case ids and overlay targets against every other dataset.
349
+ A jargon-leak error is fixed by rewording the case, never by renaming
350
+ internals. Then `evalkit run <dataset> --agent <agent>` syncs the directory
351
+ to your workspace and runs it; CI, logged in as `admin`, runs `evalkit sync
352
+ <dir> --workspace dev` (the team's shared workspace) on merge (see
353
+ `evalkit --help` for exact flags).
354
+
355
+ ## After sync
356
+
357
+ ```mermaid
358
+ stateDiagram-v2
359
+ [*] --> Unreviewed: sync
360
+ Unreviewed --> ReviewRequested: request review
361
+ ReviewRequested --> Approved: reviewer approves
362
+ ReviewRequested --> ChangesRequested: reviewer requests changes
363
+ ChangesRequested --> ReviewRequested: edit and re-sync
364
+ Approved --> Unreviewed: edit and re-sync
365
+ Approved --> ChangesRequested: reviewer requests changes
366
+ Approved --> [*]: promoted to the target workspace (if linked)
367
+ ```
368
+
369
+ Review applies to datasets in a shared workspace (e.g. `finance@dev`);
370
+ datasets in your personal workspace have no review state. Review never
371
+ filters a run: experiments run every case, whatever its state. In a shared
372
+ dataset a synced case starts Unreviewed. When the case is right, request review:
373
+ `evalkit review request finance@dev --case-id <id> --reviewer <user>`, or
374
+ use the case page in the UI. Reviewers are the
375
+ workspace's members with the reviewer role. A reviewer approves it or
376
+ requests changes with a comment; `evalkit review show <slug> <id>` prints the
377
+ state, changelog and comments. Editing an approved case makes it Unreviewed
378
+ again.
379
+
380
+ If an admin has linked the workspace to a promotion target (for example
381
+ `dev → prod`), approval is also the release: the approved version lands in
382
+ the same-named dataset of the target, already approved, with its overlays.
383
+ The target accepts no sync and no review decisions of its own, so a fix
384
+ always goes back through the source. The case page shows the twin in the
385
+ other workspace; see the evalkit-usage skill, "Promotion between workspaces".
386
+
387
+ For bugs, feature requests and feedback on evalkit, open an issue at https://github.com/inferedge-ai/evalkit/issues; questions go to https://github.com/inferedge-ai/evalkit/discussions.
@@ -0,0 +1,83 @@
1
+ # Whitebox enrichment via overlays
2
+
3
+ An on-demand flow — run it when the developer asks to enrich a case with
4
+ harness-specific assertions. Enrichment ADDS whitebox checks to a blackbox
5
+ case as an **overlay**: a YAML entry in the client's own cases directory
6
+ (`extends: <case-id>`) that extends a case in another suite by id and
7
+ attaches whitebox checks: evalkit's built-in tool checks under
8
+ `evaluators.trajectory`, or config for the client's Custom Evaluator API
9
+ endpoints under `evaluators.custom`.
10
+
11
+ ```yaml
12
+ overlays:
13
+ - extends: <case-id>
14
+ agents: [<agent name>]
15
+ tags: [<additive tags, optional>]
16
+ evaluators:
17
+ trajectory:
18
+ required_tools_called: { tools: [<real tool names>] }
19
+ tool_trajectory_match: { expected: [ ... ] }
20
+ custom:
21
+ <registered evaluator>: { ... }
22
+ ```
23
+
24
+ Set `agents` once for a whole file with `defaults:`:
25
+
26
+ ```yaml
27
+ defaults:
28
+ agents: [<agent name>]
29
+ overlays:
30
+ - extends: <case-id>
31
+ evaluators: { ... }
32
+ ```
33
+
34
+ Rules:
35
+
36
+ - `agents` is required. The overlay scores only runs of the agents it names;
37
+ every other agent runs the case without it. Agents match by name in any
38
+ workspace: `agents: [support-bot]` covers both `support-bot` and `support-bot@<you>`.
39
+ - Several overlay datasets may extend the same case. Two of them may not set
40
+ the same evaluator for the same agent on one case: the second sync fails
41
+ with `E-OVERLAY-CLASH`.
42
+ - An overlay may only carry `extends`, `agents`, additive `tags`,
43
+ `evaluators.trajectory` (only `tool_trajectory_match` and
44
+ `required_tools_called`) and `evaluators.custom`. Touching `input`,
45
+ `expected`, or any other built-in evaluator config is a lint error — ground
46
+ truth is not overlay-editable. Stripping the overlay must leave a portable
47
+ case.
48
+ - Every custom evaluator name must be registered in the deployment's
49
+ config.yaml (`custom_evaluators:`), and the client must host the matching
50
+ Custom Evaluator API endpoint that knows how to score that config against
51
+ the run's answer + ATIF trajectory. The built-in tool checks need no
52
+ endpoint; see [`tool-checks.md`](tool-checks.md) for their config.
53
+ - Overlays live in the client's YAML dir and reach the server via
54
+ `evalkit sync` — removing one from the dir strips the enrichment on the next
55
+ directory sync.
56
+
57
+ ## Run-then-pin
58
+
59
+ 1. Run the case single-case (`evalkit run <dataset> --agent <agent>
60
+ --case-id <id>`; the run syncs first); collect the experiment.
61
+ 2. Read the observed trajectory from the collected bundle. Derive the
62
+ enrichment from what actually happened:
63
+ - required tools: the real data tools the run used;
64
+ - trajectory match: observed calls with their args (prefer `substring`
65
+ for free-text args);
66
+ - call caps: observed counts plus slack (a cap of observed+1 fails the case
67
+ on the first regression into retry-grinding without flaking on normal
68
+ variance).
69
+ 3. Cross-check the observed tool choices against the harness's canonical tool
70
+ surface (its tool definitions / MCP server source). If a better tool or
71
+ trajectory exists than the one observed, pin the better one and let the
72
+ case go red: the case is the contract, and the red is a finding for the
73
+ EDD loop.
74
+ 4. Curate — pin intent, not accident:
75
+ - Date literals in args are correct when the case input is date-anchored
76
+ (they assert the agent honoured the as-of). Do not pin values the agent
77
+ derived from run time.
78
+ - Do not pin incidental arg values (page sizes, orderings) that a
79
+ different-but-correct run would legitimately vary.
80
+ 5. `evalkit lint <file> --dataset <slug>` the overlay file (unregistered
81
+ evaluator names and bad targets are errors; the target check needs
82
+ `--dataset`), then re-run the case to confirm the enriched assertions
83
+ hold.
@@ -0,0 +1,71 @@
1
+ # Built-in tool checks
2
+
3
+ Two built-in evaluators check the tool calls in the run's ATIF trajectory,
4
+ subagents included: `required_tools_called` and `tool_trajectory_match`. Both
5
+ need a harness that declares `trajectory` and `tool_calls`; otherwise they
6
+ skip. Both score into the trajectory bucket.
7
+
8
+ Write each tool name exactly as the harness records it in the trajectory,
9
+ including any prefix the harness adds.
10
+
11
+ ## Where they go
12
+
13
+ Tool checks name the harness's tools, so a case that carries them only works
14
+ against that harness. Put them in one of two places:
15
+
16
+ - **In the case itself**, under `evaluators.trajectory`, when the case lives
17
+ in the client's own harness-specific dataset (cases written only for that
18
+ client's agent). The rest of the case stays blackbox: `input.question`
19
+ and every rubric remain free of tool names, and lint still checks that.
20
+
21
+ ```yaml
22
+ - id: <case-id>
23
+ input: {question: "..."}
24
+ evaluators:
25
+ output:
26
+ answer_rubrics: {rubrics: [...]}
27
+ trajectory:
28
+ required_tools_called: {tools: [<real tool names>]}
29
+ tool_trajectory_match: {expected: [...]}
30
+ ```
31
+
32
+ - **In an overlay**, under `evaluators.trajectory`, when the case belongs to
33
+ a portable suite someone else maintains. The overlay adds the checks
34
+ without touching the case; see [`overlays.md`](overlays.md).
35
+
36
+ ## Config
37
+
38
+ `required_tools_called` — every listed tool must be called at least once.
39
+ Extra calls are fine. Score = tools called ÷ tools listed.
40
+
41
+ ```yaml
42
+ required_tools_called:
43
+ tools: [get_instrument_details, get_bond_trades]
44
+ ```
45
+
46
+ `tool_trajectory_match` — expected calls, matched by name and args. Each
47
+ actual call can satisfy at most one expected entry. Score = entries matched ÷
48
+ entries.
49
+
50
+ ```yaml
51
+ tool_trajectory_match:
52
+ ordered: false # true: entries must also appear in this order
53
+ expected:
54
+ - name: get_bond_trades
55
+ args: {isins: "INE831R07540"}
56
+ args_mode: substring # subset (default) | exact | ignore | substring
57
+ - name: get_bond_vwap
58
+ args: {series: "SDL", isin: "INE"}
59
+ match_overrides: {isin: substring} # per-arg: equals | substring
60
+ ```
61
+
62
+ | `args_mode` | Matches when |
63
+ |---|---|
64
+ | `subset` | every expected key is present and equal; extra actual keys allowed |
65
+ | `exact` | the actual args equal the expected args |
66
+ | `ignore` | the name matches; args are not checked |
67
+ | `substring` | like `subset`, but each expected value need only appear, case-insensitively, inside the actual value (lists and dicts compared as JSON text) |
68
+
69
+ `match_overrides` sets the mode for single keys of `args`; it is not allowed
70
+ with `exact` or `ignore`. Each unmatched entry reports why: `name miss`,
71
+ `args mismatch`, `out of order` or `no available matching call`.