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,458 @@
1
+ ---
2
+ name: eval-driven-development
3
+ description: Drives eval-driven development (EDD) against an evalkit deployment in two loops. Improve the agent — run a dataset, pull the runs, diagnose each failure, synthesize file-cited fixes, apply and re-run until green. Mine cases — pull a batch of an agent's app runs (production, staging or manual traffic), analyze each, cluster the failure patterns and author new eval cases for review. Use whenever working with agent or LLM evals — running a dataset, turning a failing experiment into fixes, capturing an app-run issue as a regression guard, building a capability cases-first, or generating cases from real traffic.
4
+ ---
5
+
6
+ # Eval-Driven Development
7
+
8
+ Two loops share one toolbox. **Loop 1 — Improve the agent** runs cases and
9
+ turns failures into file-cited fixes until nothing scores below threshold.
10
+ **Loop 2 — Mine cases** reads a batch of the agent's app runs and turns the
11
+ failure patterns it finds into new cases for review. Pick one loop first (see
12
+ "Pick a loop") and stay on it; the two meet only at the handoffs in "Where
13
+ the loops meet".
14
+
15
+ All eval operations go through the `evalkit` CLI. Discover exact command
16
+ shapes with `evalkit --help` (and `--help` on any subcommand) instead of
17
+ guessing. Loop 1 leans on `sync`, `run`, `runs pull --experiment` and
18
+ `summary`; Loop 2 on `runs list`, `runs pull`, `lint`, `sync` and
19
+ `review request`.
20
+
21
+ ## Terms
22
+
23
+ | Term | Meaning |
24
+ |---|---|
25
+ | Loop 1 — Improve the agent | Run cases, diagnose failures, fix the agent's code, prompts, tools or data. Output: a scorecard and agent changes. |
26
+ | Loop 2 — Mine cases | Pull app runs, analyze each, cluster failure patterns, author cases. Output: cases sent to review. |
27
+ | App run | A run of the agent outside any experiment: production, staging or by hand. |
28
+ | Experiment | One run of one dataset (or a case subset) against one agent. Referenced by id or name. |
29
+ | Run | One case executed once against the agent, in a fresh session. |
30
+ | Case | One eval question: input, expected behaviour, evaluator config. A YAML document. |
31
+ | Surface | The place a fix lands: a skill, a tool description, a prompt, or a data source. |
32
+ | Working set | The failing case ids plus sibling cases that exercise the same surfaces; what Step 6 re-runs. |
33
+ | Run directory | One run pulled by `evalkit runs pull` — `runs/<run_id>/` with `run.json`, `trajectory.json`, `case.json`, `evaluations.json`; `files.json` and `files/` only after `evalkit runs files`. |
34
+ | Finding | The one JSON diagnosis Step 4 produces per failing case. |
35
+ | Proposal group | One set of related fixes in `proposals.md`; Step 6 applies one group per iteration. |
36
+ | Overlay | A client extension of a case by id, attaching custom-evaluator config or the built-in tool checks for the agents it names. |
37
+ | Blackbox / whitebox | Blackbox: what any observer could see — the portable case. Whitebox: harness-specific checks — the overlay. |
38
+ | Coverage gap | A Loop 1 finding that says no case covers a scenario, or that the case itself is wrong. |
39
+ | Observation | The one JSON a Loop 2 analysis writes per app run. |
40
+ | Pattern | A group of observations that share a failure; the unit of the case plan. |
41
+ | Case plan | `case-plan.md`, Loop 2's ranked list of patterns with proposed cases. |
42
+ | EDD-infra note | A one-line nudge from diagnose/synthesize about a gap in the eval setup itself. |
43
+
44
+ ## Case levels
45
+
46
+ Every case is layered:
47
+
48
+ - **Blackbox case** — asserts only what any observer could see: the answer and
49
+ the trajectory in natural language (`answer_rubrics`, `trajectory_rubrics`,
50
+ `presentation_judge`, `max_response_time`). No tool/skill vocabulary —
51
+ portable across harnesses. Authoring doctrine lives in the
52
+ `authoring-eval-cases` skill.
53
+ - **Whitebox enrichment** — additive harness-specific assertions, attached as
54
+ an **overlay** on the case and scored by evalkit's built-in tool checks
55
+ (`tool_trajectory_match`, `required_tools_called`) or the client's own
56
+ Custom Evaluator API endpoints. A case in the client's own
57
+ harness-specific dataset may carry the built-in tool checks directly
58
+ instead (see the authoring skill's
59
+ [`references/tool-checks.md`](../authoring-eval-cases/references/tool-checks.md)).
60
+ Enrichment never edits blackbox evaluators; stripping the
61
+ overlay leaves a portable case. See the authoring skill's
62
+ [`references/overlays.md`](../authoring-eval-cases/references/overlays.md).
63
+
64
+ ## Pick a loop
65
+
66
+ | Developer gives | Wants back | Loop |
67
+ |---|---|---|
68
+ | A dataset to run, an experiment id or name, an app-run issue, a new capability | A scorecard, or agent changes | 1 |
69
+ | An agent and a time window ("look at last week's traffic", "what are users hitting?") | New cases | 2 |
70
+
71
+ If a request fits neither row, ask which output they want. Once a loop is
72
+ picked, follow only its steps. Loop 2's steps are named M1–M5 so they never
73
+ mix with Loop 1's Steps 1–6.
74
+
75
+ ## Runs are history
76
+
77
+ This applies to both loops. Every pulled run shows the agent as it was when
78
+ the run happened (`run.json` `started_at`, `index.json` `created_at`), not as
79
+ the code is now. Prompts,
80
+ skills, tools and data may have changed since, so a failure in a run may
81
+ already be fixed. Before diagnosing or proposing a fix, check the git history
82
+ of the agent repo for changes made after the run:
83
+
84
+ ```bash
85
+ git log --since=<run started_at> --oneline -- <paths of the surfaces involved>
86
+ git log --since=<run started_at> --oneline -S '<tool or prompt text from the trajectory>'
87
+ ```
88
+
89
+ `--since` compares commit dates, which a rebase or squash merge resets, so
90
+ treat it as a first pass: also read the last few commits that touch the
91
+ surface (`git log -n 10 -- <path>`) whatever their date. Read any commit that
92
+ touches the failing surface. If it already addresses the failure:
93
+
94
+ - **Loop 1** — the finding says so (`already_addressed`) instead of proposing
95
+ the same fix again; re-run the case to confirm the fix rather than editing
96
+ code. Diagnose against the code at `HEAD`, and cite what changed since the
97
+ run.
98
+ - **Loop 2** — the observation says so (`fixed_since`). Still author cases for
99
+ the pattern: they guard the fix against regressions. The case plan marks
100
+ them "expected green" with the commit, so nobody reads them as open
101
+ failures.
102
+
103
+ ## Loop 1 — Improve the agent
104
+
105
+ **Output is a scorecard and agent changes. New cases come only from Step 1 or
106
+ from the coverage-gap handoff; never edit cases to make a run pass.**
107
+
108
+ Four entry points, one shared loop. Infer the entry point from what the
109
+ developer gave you: a dataset to run → D; an experiment id or name → A; a
110
+ described app-run issue → B; a feature/behaviour intent → C.
111
+
112
+ One flag: `--apply` in the invocation runs the autonomous apply → re-run loop
113
+ (Step 6). Without it, stop after the proposal for the human to act.
114
+
115
+ ```mermaid
116
+ stateDiagram-v2
117
+ author: Step 1 — author case(s)
118
+ sync_run: Step 2 — evalkit lint + sync + run
119
+ pull: Step 3 — pull runs, pick failures
120
+ diagnose: Step 4 — diagnose each failure
121
+ synthesize: Step 5 — synthesize grouped proposal
122
+ apply: Step 6 — apply one group
123
+ state check <<choice>>
124
+
125
+ [*] --> pull: A · experiment id/name given
126
+ [*] --> sync_run: D · run a dataset
127
+ [*] --> author: B · app-run issue / C · new or changed capability
128
+
129
+ author --> sync_run
130
+ sync_run --> [*]: D · summary, stop
131
+ sync_run --> pull
132
+ pull --> check
133
+ check --> [*]: green, or cap reached → human review
134
+ check --> diagnose: failures, no proposal yet
135
+ check --> apply: still red, proposal ready, iterations left
136
+ diagnose --> synthesize
137
+ synthesize --> [*]: without --apply → human review
138
+ synthesize --> apply: with --apply
139
+ apply --> sync_run: re-run full working set
140
+ ```
141
+
142
+ - **A — fix a failing experiment (regression).** An experiment already ran;
143
+ the developer names it (`runs pull --experiment` takes its numeric id). →
144
+ start at Step 3.
145
+ - **B — capture an app-run issue as a regression guard.** An app run (one
146
+ outside any experiment: production, staging or by hand) misbehaved. →
147
+ Step 1: author a case (from the run *and* the developer's input) asserting the correct behaviour, then run and loop. The case stays in
148
+ the suite afterwards as a permanent guard. If the developer points at a
149
+ run/session id, pull it with `evalkit runs pull <agent> --run-id <id>` and
150
+ read its `trajectory.json` before authoring.
151
+ - **C — build or change a capability, cases-first.** New or changed behaviour,
152
+ code not written yet. → Step 1: author cases for the desired behaviour;
153
+ expect the first run to be red.
154
+ - **D — run a dataset.** The developer wants to know how the agent does on a
155
+ dataset (or part of one). → Step 2: `evalkit run`, then `evalkit summary
156
+ <experiment-id>`, and stop there. Continue at Step 3 only if they ask for the
157
+ failures to be fixed.
158
+
159
+ ### Step 1 — author / select cases (B and C)
160
+
161
+ Use the `authoring-eval-cases` skill. Ground every case in the material at
162
+ hand — the request in this conversation, any app run or links shared, files
163
+ already open — and ask the developer to fill any gap (the exact input, the
164
+ correct output) rather than guessing. The case asserts the **ideal
165
+ behaviour** — a time-anchored input and specific expected values — never the
166
+ current broken behaviour: don't write rubrics that merely guard against the
167
+ failure you just saw, or the case overfits to today's bug instead of stating
168
+ what correct output looks like for this input and every sibling like it.
169
+
170
+ ### Step 2 — lint, sync, run (B, C and D)
171
+
172
+ After authoring or editing any case YAML — in any entry point — run
173
+ `evalkit lint <file> --dataset <slug>` first; errors block sync. Then
174
+ `evalkit run <dataset> --agent <agent>`: with an `evalkit.yaml` in the repo
175
+ this syncs the dataset directory to your workspace and runs your local agent
176
+ from this machine. For a tight loop, run only the relevant cases
177
+ (`evalkit run <dataset>/<file>.yaml`, `evalkit run <dataset>/<subfolder>`, or
178
+ `--case-id`, repeatable) rather than the whole dataset.
179
+
180
+ `evalkit run` executes every selected case, in personal and shared datasets
181
+ alike; review state never filters a run.
182
+ When you are confident the case is correct and it has reached a shared
183
+ dataset, ask for review:
184
+ `evalkit review request <dataset>@dev --case-id <id> --reviewer <user>`. If `dev` is
185
+ linked to a promotion target such as `prod`, the reviewer's approval also puts
186
+ the case into `<dataset>@prod`, approved; nothing else is needed to release
187
+ it. Whether the
188
+ agent passes the case has no bearing on review; a red case that asserts the
189
+ right behaviour is exactly what a reviewer should approve.
190
+
191
+ `run` executes two phases: agent runs, then evaluators. If a run crashes or is
192
+ killed before evaluation, don't re-run the cases — `evalkit evaluate
193
+ <experiment-id>` scores the runs that already persisted, and `evalkit run
194
+ --resume <experiment-id>` finishes a partially-run experiment.
195
+
196
+ ### Step 3 — pull runs and pick the failures
197
+
198
+ `evalkit runs pull --experiment <experiment-id>` downloads every run of the
199
+ experiment to `evalkit-runs/experiment-<id>/` (keep that directory out of
200
+ git): `index.json` and one `runs/<run_id>/` per run with `run.json` (status,
201
+ answer, metrics), `trajectory.json` (ATIF), `case.json` (the case version the
202
+ run answered) and `evaluations.json` (every evaluator's score and explanation).
203
+
204
+ The pull does not fetch files: not the run's workspace files (deliverables)
205
+ and not the full outputs of tool results the harness shortened (the
206
+ trajectory keeps the shortened one). Fetch them only for the failures you
207
+ diagnose, and only when the trajectory is not enough:
208
+ `evalkit runs files <dir> <run_id>` prints the run's file tree (also written
209
+ to `runs/<run_id>/files.json`); then
210
+ `evalkit runs files <dir> <run_id> --path <file or folder>` fetches just those
211
+ into `runs/<run_id>/files/<path>`. A tool result's `extra.full_output_path` is
212
+ such a path, even when the tree does not list it. The first file that fails
213
+ stops the command and names it; rerun with the remaining paths if you still
214
+ need them. Never fetch a whole heavy workspace when one file answers the
215
+ question.
216
+
217
+ Pick the failures yourself from `index.json` `runs`: a run fails when its
218
+ `status` is not `completed` or any value in `scores` is below 0.8 (use another
219
+ threshold if the developer asked, and only their evaluator if they named one).
220
+ A row with `pull_error` set could not be fetched in full (its run directory
221
+ has no `trajectory.json`); pull it again into the same directory with
222
+ `evalkit runs pull <index.json agent> --run-id <run_id> --out <same dir>`, and
223
+ if it still fails, list it for the developer instead of diagnosing it. If
224
+ `index.json` has a `note`, tell the developer (for example, the harness scan
225
+ stopped early).
226
+ If none fail, report "no failures below threshold" and STOP (for B/C, an empty
227
+ failure set on the first run means the capability already works — confirm and
228
+ stop). Diagnose failures only; the passing runs are there for profiling.
229
+
230
+ ### Step 4 — diagnose (fan-out, capped at 5 concurrent)
231
+
232
+ For each failing case, run the instructions in
233
+ [`references/diagnose.md`](references/diagnose.md) against its failing run
234
+ directories. On agents with subagent support, dispatch each diagnosis as a
235
+ subagent, batched 5 at a time (one message with 5 parallel dispatches, wait,
236
+ then the next batch); otherwise run them inline, sequentially. Each diagnosis
237
+ produces a single JSON finding — write each one to
238
+ `<review-dir>/findings/<case_id>.json` (create `findings/` first).
239
+
240
+ Trajectory efficiency is in scope for every diagnosis, not just wrong output:
241
+ errored, retried, or redundant tool calls and wrong-first-call discovery
242
+ overhead are diagnosable defects in their own right. Don't let a
243
+ plausibly-correct final answer mask a wasteful trajectory.
244
+
245
+ ### Step 5 — synthesize (once)
246
+
247
+ Run the instructions in [`references/synthesize.md`](references/synthesize.md)
248
+ once (as a subagent where supported), passing: the `findings/` dir, the
249
+ `index.json` path, and the proposal output path `<review-dir>/proposals.md`.
250
+ It writes the proposal. Print the proposal path and a one-line summary
251
+ (`<N> failures diagnosed, proposal at <path>`).
252
+
253
+ If not `--apply`, STOP here for human review.
254
+
255
+ ### Interpreting Loop 1 outputs
256
+
257
+ Findings and the proposal carry flags addressed to you, not just to the
258
+ proposal's reader. Handle each explicitly instead of skimming past them:
259
+
260
+ - **`unverified` proposal groups** — the synthesizer could not confirm the
261
+ change against real code, or concluded the case itself may be wrong. Never
262
+ apply one autonomously in Step 6; carry it to the developer with the stated
263
+ reason.
264
+ - **Possibly-wrong case** — when the proposal says the expected answer is not
265
+ derivable from the data or domain (a `wrong_case` coverage gap), the fix is
266
+ a dataset fix. Escalate to the developer; do not bake the expected answer
267
+ into any prompt surface.
268
+ - **`verdict: borderline` findings** — near-threshold, not clearly broken.
269
+ Deprioritize below `failed` findings; mention them in the exit summary
270
+ rather than spending iterations on them.
271
+ - **`already_addressed` findings** — a commit after the run already changed
272
+ the failing surface. Don't apply anything for them; re-run those cases first
273
+ and only diagnose again if they still fail.
274
+ - **Case proposals (coverage gaps)** — `proposals.md` lists them apart from
275
+ the fix groups. Never apply them in Step 6. Offer them to the developer at
276
+ the end; accepted ones go through Loop 2's M5 (author, lint, sync, request
277
+ review). See "Where the loops meet".
278
+ - **`root_cause: unknown` or low `confidence`** — don't force these into a fix
279
+ group. List them for the developer with whatever evidence the finding has.
280
+ - **`EDD-infra note:` lines** — diagnose and synthesize may append one when
281
+ the eval setup itself has a gap. Collect every note and relay them in the
282
+ final summary (see Self-feedback); they are never a reason to edit evalkit
283
+ or the pulled runs yourself mid-loop.
284
+
285
+ ### Step 6 — apply & re-run (only with `--apply`)
286
+
287
+ The autonomous inner loop, capped at 3 iterations (a global cap on total
288
+ iterations across all groups; the developer can raise it in the request). Each iteration applies a single
289
+ proposal group, then re-runs the whole working set and pulls it again. One group
290
+ per iteration keeps each change attributable; re-running the full working set
291
+ catches a fix that regresses a sibling.
292
+
293
+ Copy this checklist and track progress:
294
+
295
+ ```
296
+ EDD loop:
297
+ - [ ] Build the working set (failing ids ∪ cases touching the same surfaces)
298
+ - [ ] Iteration 1: apply highest-leverage group → run full working set → re-pull
299
+ - [ ] Iteration 2 (if still red): apply next group / refine → run full set → re-pull
300
+ - [ ] Iteration 3 (if still red): apply next group / refine → run full set → re-pull
301
+ - [ ] Summarize (green, or what is still red + groups not reached at the cap) → hand to human
302
+ ```
303
+
304
+ **Build the working set (once, before the loop):** seed = the failing
305
+ `case_id`s you picked from `index.json`; widen with sibling cases that exercise the same
306
+ surfaces the proposal touches (search the case YAML for related scenarios).
307
+
308
+ **Each iteration:**
309
+
310
+ 1. Apply the chosen proposal group — edit the cited file at the surface the
311
+ proposal names. Create a brand-new surface only when the developer asked
312
+ for one or the proposal shows no existing surface can host the capability.
313
+ Any change to a prompt surface follows the prompt-change guidelines inside
314
+ [`references/synthesize.md`](references/synthesize.md): describe the
315
+ mechanism first, escalate to rule-style wording only when a re-run shows
316
+ the behaviour persisted, prefer deterministic guards, no eval awareness.
317
+ 2. `evalkit run <dataset> --agent <agent> --case-id <id> [--case-id …]`
318
+ over the working set (the run syncs your edits first).
319
+ 3. `evalkit runs pull --experiment <id>` for that experiment and pick the
320
+ failures from the new `index.json`.
321
+ 4. Stop when no failure scores below threshold (**green**) or when the
322
+ iteration cap is reached.
323
+
324
+ **On exit:** summarize what changed, what is green, and — if the cap was hit —
325
+ what is still red. List the case proposals, if any. Hand to the human; do not
326
+ keep looping.
327
+
328
+ ## Loop 2 — Mine cases from app runs
329
+
330
+ **Output is cases sent to review. Never edit the agent in this loop; to fix
331
+ the agent for the new cases, hand off to Loop 1 (see "Where the loops
332
+ meet").**
333
+
334
+ ```mermaid
335
+ stateDiagram-v2
336
+ m1: M1 — get app runs locally
337
+ m2: M2 — choose the window, pull every run
338
+ m3: M3 — analyze each run
339
+ m4: M4 — synthesize the case plan
340
+ m5: M5 — author, lint, sync, request review
341
+ [*] --> m1
342
+ m1 --> m2
343
+ m2 --> m3
344
+ m3 --> m4
345
+ m4 --> [*]: developer reviews case-plan.md
346
+ [*] --> m5: developer picks patterns
347
+ m5 --> [*]: cases in review (optionally → Loop 1 C)
348
+ ```
349
+
350
+ Work in one directory for the whole batch, `<dir>` (default
351
+ `evalkit-runs/<agent>/<YYYYMMDD-HHMMSS>/`, kept out of git): the pulled runs,
352
+ `observations/` and `case-plan.md` all live there.
353
+
354
+ ### M1 — get app runs locally
355
+
356
+ Check how the agent's runs reach evalkit (`evalkit agents show <agent>` says
357
+ OTel or harness), then take one route:
358
+
359
+ 1. **OTel agent that exports app traffic to evalkit** — the runs are already
360
+ on the server. Go to M2.
361
+ 2. **Traces live in an external tracing tool** — import them first with
362
+ `evalkit traces import` (Phoenix is the only supported source today), wait
363
+ for the import (`evalkit traces imports <agent> <id>`), then go to M2.
364
+ 3. **Harness agent** — `evalkit runs list` reads the harness's run list (the
365
+ server does it for a shared agent, your CLI for a personal one). Go to M2.
366
+
367
+ If `evalkit runs list <agent> --source app` returns nothing, stop: tell the
368
+ developer the agent sends only eval traffic to evalkit, and point at route 2
369
+ or at the connect-traces skill. Never continue with zero runs.
370
+
371
+ ### M2 — choose the window, pull every run
372
+
373
+ Analyze every app run in the window; don't sample.
374
+
375
+ 1. Ask for the time window (default: the last 7 days). Fix `until` to the
376
+ current time for the whole batch, so new runs don't shift the pages.
377
+ 2. Count: `evalkit runs list <agent> --source app --since <since> --until
378
+ <until> --json` (one row per line).
379
+ 3. If the count is 0, stop (see M1). If it is 100 or fewer, go on. Above 100,
380
+ tell the developer the count and the cost — one subagent per run, 5 at a
381
+ time — and offer to narrow the window. Go on with more than 100 only when
382
+ the developer states the number; "all" is not a number.
383
+ 4. Pull 25 runs per call into the same directory:
384
+
385
+ ```bash
386
+ evalkit runs pull <agent> --source app --since <since> --until <until> \
387
+ --limit 25 --offset <0, 25, 50, …> --out <dir>
388
+ ```
389
+
390
+ Every call adds to the same `index.json`; `runs/` stays flat. No files
391
+ come with the runs; M3 fetches them per run when it needs them.
392
+ 5. Rows with `pull_error` could not be fetched in full: list them for the
393
+ developer and skip them in M3. If `index.json` has a `note`, pass it on.
394
+
395
+ ### M3 — analyze each run (fan-out, capped at 5 concurrent)
396
+
397
+ For every row in `index.json` without a `pull_error`, run the instructions in
398
+ [`references/analyze-run.md`](references/analyze-run.md) against
399
+ `<dir>/<row.dir>`. On agents with subagent support, dispatch each analysis as
400
+ a subagent, 5 at a time; otherwise run them inline, one at a time. Each
401
+ writes `<dir>/observations/<run_id>.json` (create `observations/` first; use
402
+ the row's `dir` name for the file).
403
+
404
+ ### M4 — synthesize the case plan (once)
405
+
406
+ Run [`references/synthesize-cases.md`](references/synthesize-cases.md) once
407
+ (as a subagent where supported), passing `<dir>/observations/`,
408
+ `<dir>/index.json`, the target suite directory (the case YAML the new cases
409
+ will join; ask the developer if there is more than one), and the output path
410
+ `<dir>/case-plan.md`.
411
+
412
+ Print the plan path and one line (`<P> patterns from <N> runs, plan at
413
+ <path>`), then STOP until the developer picks which patterns to author.
414
+
415
+ ### M5 — author, lint, sync, request review
416
+
417
+ For each pattern the developer picked:
418
+
419
+ 1. Author its proposed cases with the `authoring-eval-cases` skill. Its
420
+ interview fills every `NEEDS DEVELOPER` ground truth; never guess one.
421
+ 2. `evalkit lint <file> --dataset <slug>`; errors block sync.
422
+ 3. `evalkit sync <dataset dir>` (with `--workspace <ws>` for a shared
423
+ workspace you write to).
424
+ 4. On a shared dataset, `evalkit review request <dataset>@<ws> --case-id <id>
425
+ --reviewer <user>`. The cases start Unreviewed.
426
+
427
+ Loop 2 ends here. It does not run the new cases; that is Loop 1's job.
428
+
429
+ ### Interpreting Loop 2 outputs
430
+
431
+ - **`fixed_since` patterns** — author them like any other, as regression
432
+ guards, and keep the "expected green" mark in the summary.
433
+ - **`Already covered by`** — a partly covered pattern still gets cases for the
434
+ part no case asserts; a fully covered one is dropped from the plan.
435
+ - **Unclear or low-confidence observations** — the plan lists them at the end.
436
+ Mention them to the developer; don't author cases from them.
437
+
438
+ ## Where the loops meet
439
+
440
+ Two handoffs, nothing else:
441
+
442
+ 1. **Loop 2 → Loop 1.** After M5 the developer may ask to fix the agent for
443
+ the new cases. Enter Loop 1 at **C** (new cases, red expected) with the new
444
+ case ids as the working set.
445
+ 2. **Loop 1 → authoring.** A diagnosis may find that a failure shows a scenario
446
+ no case covers, or that the case itself is wrong (`coverage_gap` on the
447
+ finding). `synthesize.md` lists these as "Case proposals" in
448
+ `proposals.md`, apart from the fix groups. Loop 1 keeps fixing the agent;
449
+ at the end, offer the case proposals to the developer, and author the
450
+ accepted ones through M5.
451
+
452
+ ## Self-feedback
453
+
454
+ If you hit a gap in the EDD setup itself while running either loop (data missing
455
+ from a run directory, a CLI flag the loop wanted, an evaluator that should exist),
456
+ tell the developer in one line at the end. A nudge, not a report.
457
+
458
+ 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,97 @@
1
+ # Analyze one app run
2
+
3
+ Instructions for analyzing **one** app run (a run of the agent outside any
4
+ experiment) and returning one structured JSON observation: what the user
5
+ wanted, whether the agent served it, and how it failed. On agents with
6
+ subagent support, dispatch these instructions as a read-only subagent, one
7
+ per run; otherwise follow them inline, one run at a time. Input: the absolute
8
+ path of one `runs/<run_id>/` directory produced by `evalkit runs pull
9
+ --source app`, plus the repo checkout(s) of the agent.
10
+
11
+ There is no expected answer and no score. The verdict comes from the
12
+ trajectory alone.
13
+
14
+ ## What you may touch
15
+
16
+ - **Read access to the entire repo.** Use read-only inspection (`cat`,
17
+ `grep`, `jq`, `ls`, `git log`/`git show` — never anything that writes).
18
+ - **Hard rule: never modify the code repo.** Your observation IS your final
19
+ output.
20
+
21
+ ## How to analyze
22
+
23
+ 1. Read `run.json` and `trajectory.json` end to end. Steps run in `step_id`
24
+ order; each step's `tool_calls` carry structured `arguments`, their results
25
+ are in `observation.results` (matched by `source_call_id`; `extra.is_error:
26
+ true` marks a failed call), and `timestamp` shows where time went.
27
+ Delegated work is in `subagent_trajectories`. `evalkit runs pull` does
28
+ not fetch the run's files. If a shortened tool result is not enough, fetch
29
+ its full output with `evalkit runs files <pull dir> <run_id> --path
30
+ <extra.full_output_path>`; to see the deliverables, list the tree with
31
+ `evalkit runs files <pull dir> <run_id>` and fetch only the paths you need.
32
+ Fetched files land in `runs/<run_id>/files/<path>`.
33
+ 2. Infer the user's intent: what they asked for, as of when, and what a good
34
+ answer would have contained.
35
+ 3. Look for failure signals, strongest first:
36
+ - the user correcting the agent, re-asking the same thing, or giving up
37
+ mid-conversation;
38
+ - tool errors, retries of the same call, timeouts;
39
+ - an answer that hedges, refuses without reason, or states figures no tool
40
+ result supports;
41
+ - a wrong tool, a missing step (data the answer needed but never fetched),
42
+ wrong arguments;
43
+ - wasteful steps: redundant calls, discovery overhead, dead-end pivots;
44
+ - presentation problems: the right content badly shaped for the user.
45
+ 4. Decide the verdict: `failed` (the user did not get what they needed),
46
+ `degraded` (they got it, with real waste or friction), `ok` (no failure),
47
+ `unclear` (the trajectory does not show enough to judge). Record `ok` runs
48
+ too; synthesis needs them.
49
+ 5. For each failure, trace the surface (skill, tool, prompt, data source) in
50
+ the repo and name the file when you can.
51
+ 6. **The run is history.** It shows the agent as of `run.json` /
52
+ `index.json` `created_at`. Check what changed since:
53
+ `git log --since=<created_at> -- <surface files>` and
54
+ `git log -S '<tool or prompt text from the trajectory>'`. Commit dates reset
55
+ on rebase and squash merge, so also read the last few commits on each
56
+ surface file (`git log -n 10 -- <file>`) whatever their date. If a later
57
+ commit already fixes the failure, fill `fixed_since`.
58
+ 7. Write a case seed: a new, time-anchored input that exercises the same
59
+ failure, and the ideal behaviour. Don't copy the user's words or data; the
60
+ seed generalises the run.
61
+
62
+ ## Output — return ONLY this JSON object
63
+
64
+ ```json
65
+ {
66
+ "run_id": "<from index.json>",
67
+ "created_at": "<from index.json>",
68
+ "intent": "<one line: what the user asked for>",
69
+ "task_type": "<a case type from the authoring-eval-cases skill>",
70
+ "verdict": "failed | degraded | ok | unclear",
71
+ "signals": ["<short label, e.g. 'user re-asked', 'tool error x3'>"],
72
+ "failures": [
73
+ {
74
+ "kind": "wrong_answer | wrong_tool | missing_step | inefficiency | presentation | refusal",
75
+ "evidence": "<one specific line, citing main:<step_id> or <trajectory_id>:<step_id>>",
76
+ "steps": [12, 14],
77
+ "surface": {"kind": "skill | tool | prompt | mcp | data | absent", "file": "<repo path or null>"}
78
+ }
79
+ ],
80
+ "ideal_behaviour": "<one or two lines: what a good run does>",
81
+ "case_seed": {"input": "<new input, not the user's>", "anchor_date": "<YYYY-MM-DD>", "ground_truth_known": false},
82
+ "fixed_since": null,
83
+ "confidence": "high | medium | low"
84
+ }
85
+ ```
86
+
87
+ Rules:
88
+
89
+ - `failures` is empty when `verdict` is `ok`.
90
+ - Every `evidence` line cites a concrete step, tool result or artifact.
91
+ - `ground_truth_known` is `true` only when the correct answer can be checked
92
+ from the run's own tool results or the agent's data sources.
93
+ - `fixed_since` is `null`, or `{"commit": "<sha>", "detail": "<what it
94
+ changed>"}` when a commit made after the run already fixes every failure
95
+ listed.
96
+ - Never put user names, account ids or other personal data from the run into
97
+ the observation.