coder-eval 0.9.1__tar.gz → 0.9.3__tar.gz

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 (601) hide show
  1. {coder_eval-0.9.1 → coder_eval-0.9.3}/.env.example +11 -0
  2. {coder_eval-0.9.1 → coder_eval-0.9.3}/CHANGELOG.md +208 -0
  3. {coder_eval-0.9.1 → coder_eval-0.9.3}/CLAUDE.md +5 -4
  4. {coder_eval-0.9.1 → coder_eval-0.9.3}/PKG-INFO +1 -1
  5. {coder_eval-0.9.1 → coder_eval-0.9.3}/action.yml +1 -1
  6. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/EXTENDING.md +10 -2
  7. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/REPORT_SCHEMA.md +63 -6
  8. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/TASK_DEFINITION_GUIDE.md +61 -5
  9. coder_eval-0.9.3/evalboard/app/_components/__tests__/harness-badge.test.tsx +45 -0
  10. coder_eval-0.9.3/evalboard/app/_components/__tests__/harness-selector.test.tsx +81 -0
  11. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/_components/harness-badge.tsx +21 -3
  12. coder_eval-0.9.3/evalboard/app/_components/harness-selector.tsx +101 -0
  13. coder_eval-0.9.3/evalboard/app/_overview/__tests__/harness-legend.test.tsx +130 -0
  14. coder_eval-0.9.3/evalboard/app/_overview/__tests__/harness-series.test.ts +148 -0
  15. coder_eval-0.9.3/evalboard/app/_overview/daily-chart.tsx +106 -0
  16. coder_eval-0.9.3/evalboard/app/_overview/harness-legend.tsx +111 -0
  17. coder_eval-0.9.3/evalboard/app/_overview/harness-series.ts +75 -0
  18. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/_overview/tag-rail.tsx +6 -17
  19. coder_eval-0.9.3/evalboard/app/_overview/turn-budget-chart.tsx +110 -0
  20. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/_overview/window-summary.tsx +15 -8
  21. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/page.tsx +166 -150
  22. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/path-to-ga/page.tsx +43 -30
  23. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/trends/trends-view.tsx +6 -7
  24. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/watchlist/watchlist-view.tsx +4 -3
  25. coder_eval-0.9.3/litellm/cost_logger.py +226 -0
  26. {coder_eval-0.9.1 → coder_eval-0.9.3}/litellm/litellm-config.yaml +35 -10
  27. {coder_eval-0.9.1 → coder_eval-0.9.3}/litellm/start-litellm.sh +11 -0
  28. {coder_eval-0.9.1 → coder_eval-0.9.3}/pyproject.toml +1 -1
  29. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/__init__.py +1 -1
  30. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/agent.py +18 -0
  31. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/agents/antigravity_agent.py +1 -2
  32. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/agents/claude_code_agent.py +49 -0
  33. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/agents/codex_agent.py +1 -2
  34. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/config.py +6 -0
  35. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/base.py +21 -34
  36. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/command_executed.py +1 -37
  37. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/llm_judge.py +2 -2
  38. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/skill_triggered.py +5 -35
  39. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_usage.py +18 -2
  40. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/isolation/docker_runner.py +16 -2
  41. coder_eval-0.9.3/src/coder_eval/litellm_cost.py +231 -0
  42. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/__init__.py +20 -0
  43. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/criteria.py +132 -3
  44. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/experiment.py +13 -2
  45. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/limits.py +43 -7
  46. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/results.py +227 -7
  47. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/sandbox.py +6 -0
  48. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/telemetry.py +18 -0
  49. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/orchestration/batch.py +45 -1
  50. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/orchestration/early_stop.py +204 -52
  51. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/orchestrator.py +177 -14
  52. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/pricing.py +75 -53
  53. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/reports.py +52 -11
  54. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/reports_experiment.py +74 -10
  55. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/reports_html.py +22 -16
  56. coder_eval-0.9.3/tasks/early_stop_decision_budget_exceeded.yaml +40 -0
  57. coder_eval-0.9.3/tasks/early_stop_weighted_high_weight_kills_run.yaml +55 -0
  58. coder_eval-0.9.3/tasks/early_stop_weighted_low_weight_absorbed.yaml +54 -0
  59. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/_scrub.py +10 -1
  60. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/experiment_2variant.md +1 -1
  61. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/experiment_3variant.md +1 -1
  62. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/experiment_replicates.md +1 -1
  63. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/run_full.md +1 -1
  64. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/run_minimal.md +1 -1
  65. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/runner.py +0 -2
  66. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_agent_timeout.py +57 -0
  67. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_antigravity_agent.py +4 -0
  68. coder_eval-0.9.3/tests/test_cost_accounting_paths.py +362 -0
  69. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_custom_lint.py +99 -56
  70. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_docker_litellm_env.py +25 -0
  71. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_early_stop.py +618 -58
  72. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_event_collector.py +7 -4
  73. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_experiment_reports.py +2 -2
  74. coder_eval-0.9.3/tests/test_litellm_config.py +57 -0
  75. coder_eval-0.9.3/tests/test_litellm_cost.py +336 -0
  76. coder_eval-0.9.3/tests/test_litellm_cost_logger.py +259 -0
  77. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_litellm_route.py +56 -0
  78. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_reports.py +5 -2
  79. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_route_seam_exhaustiveness.py +1 -1
  80. coder_eval-0.9.3/tests/test_run_metrics.py +253 -0
  81. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_timeout_orchestrator.py +82 -0
  82. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_token_usage.py +87 -3
  83. {coder_eval-0.9.1 → coder_eval-0.9.3}/uv.lock +110 -110
  84. coder_eval-0.9.1/evalboard/app/_components/harness-selector.tsx +0 -49
  85. coder_eval-0.9.1/evalboard/app/_components/window-selector.tsx +0 -33
  86. coder_eval-0.9.1/evalboard/app/_overview/daily-chart.tsx +0 -112
  87. coder_eval-0.9.1/evalboard/app/_overview/turn-budget-chart.tsx +0 -117
  88. coder_eval-0.9.1/tests/lint/rules/ce025_live_verdict_consistency.py +0 -111
  89. {coder_eval-0.9.1 → coder_eval-0.9.3}/.claude/commands/coder-eval-code-review-full.md +0 -0
  90. {coder_eval-0.9.1 → coder_eval-0.9.3}/.claude/commands/coder-eval-code-review-wf.md +0 -0
  91. {coder_eval-0.9.1 → coder_eval-0.9.3}/.claude/commands/coder-eval-code-review.md +0 -0
  92. {coder_eval-0.9.1 → coder_eval-0.9.3}/.claude/commands/coder-eval-create-plan.md +0 -0
  93. {coder_eval-0.9.1 → coder_eval-0.9.3}/.claude/commands/coder-eval-implement-plan.md +0 -0
  94. {coder_eval-0.9.1 → coder_eval-0.9.3}/.claude/commands/coder-eval-review.md +0 -0
  95. {coder_eval-0.9.1 → coder_eval-0.9.3}/.claude/commands/coder-eval-run-analysis.md +0 -0
  96. {coder_eval-0.9.1 → coder_eval-0.9.3}/.claude/commands/coder-eval-task-create.md +0 -0
  97. {coder_eval-0.9.1 → coder_eval-0.9.3}/.claude/harness-candidates.md +0 -0
  98. {coder_eval-0.9.1 → coder_eval-0.9.3}/.claude/shared/axes.md +0 -0
  99. {coder_eval-0.9.1 → coder_eval-0.9.3}/.claude/shared/multi-model-review.md +0 -0
  100. {coder_eval-0.9.1 → coder_eval-0.9.3}/.claude/shared/review-rubric.md +0 -0
  101. {coder_eval-0.9.1 → coder_eval-0.9.3}/.claude/shared/run-layout.md +0 -0
  102. {coder_eval-0.9.1 → coder_eval-0.9.3}/.claude/workflows/cr-axis.js +0 -0
  103. {coder_eval-0.9.1 → coder_eval-0.9.3}/.claude/workflows/cr-parent.js +0 -0
  104. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/CODEOWNERS +0 -0
  105. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/ISSUE_TEMPLATE/adopter.yml +0 -0
  106. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  107. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  108. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/code_review.md +0 -0
  109. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/dependabot.yml +0 -0
  110. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/pages-stub/index.html +0 -0
  111. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/scripts/release_notes.py +0 -0
  112. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/workflows/claude-pr-review.yml +0 -0
  113. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/workflows/codeql.yml +0 -0
  114. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/workflows/conventional-commits.yml +0 -0
  115. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/workflows/docker-publish.yml +0 -0
  116. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/workflows/docs.yml +0 -0
  117. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/workflows/pr-checks.yml +0 -0
  118. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/workflows/publish-testpypi.yml +0 -0
  119. {coder_eval-0.9.1 → coder_eval-0.9.3}/.github/workflows/release.yml +0 -0
  120. {coder_eval-0.9.1 → coder_eval-0.9.3}/.gitignore +0 -0
  121. {coder_eval-0.9.1 → coder_eval-0.9.3}/.pre-commit-config.yaml +0 -0
  122. {coder_eval-0.9.1 → coder_eval-0.9.3}/.python-version +0 -0
  123. {coder_eval-0.9.1 → coder_eval-0.9.3}/ADOPTERS.md +0 -0
  124. {coder_eval-0.9.1 → coder_eval-0.9.3}/CODE_OF_CONDUCT.md +0 -0
  125. {coder_eval-0.9.1 → coder_eval-0.9.3}/CONTRIBUTING.md +0 -0
  126. {coder_eval-0.9.1 → coder_eval-0.9.3}/LICENSE +0 -0
  127. {coder_eval-0.9.1 → coder_eval-0.9.3}/Makefile +0 -0
  128. {coder_eval-0.9.1 → coder_eval-0.9.3}/NOTICE +0 -0
  129. {coder_eval-0.9.1 → coder_eval-0.9.3}/README.md +0 -0
  130. {coder_eval-0.9.1 → coder_eval-0.9.3}/SECURITY.md +0 -0
  131. {coder_eval-0.9.1 → coder_eval-0.9.3}/docker/Dockerfile +0 -0
  132. {coder_eval-0.9.1 → coder_eval-0.9.3}/docker/Dockerfile.runtime +0 -0
  133. {coder_eval-0.9.1 → coder_eval-0.9.3}/docker/coder_eval_entrypoint.sh +0 -0
  134. {coder_eval-0.9.1 → coder_eval-0.9.3}/docker/coder_eval_runtime_entrypoint.sh +0 -0
  135. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/AB_EXPERIMENTS.md +0 -0
  136. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/CI_GATE.md +0 -0
  137. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/DATASETS.md +0 -0
  138. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/DIALOG_MODE.md +0 -0
  139. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/DOCKER_ISOLATION.md +0 -0
  140. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/USER_GUIDE.md +0 -0
  141. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/agents/ANTIGRAVITY.md +0 -0
  142. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/agents/CLAUDE_CODE.md +0 -0
  143. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/agents/CODEX.md +0 -0
  144. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/assets/hero.gif +0 -0
  145. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/comparison.md +0 -0
  146. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/index.md +0 -0
  147. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/llms.txt +0 -0
  148. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/tutorials/01-first-evaluation.md +0 -0
  149. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/tutorials/02-ci-pipeline.md +0 -0
  150. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/tutorials/03-evalboard-local.md +0 -0
  151. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/tutorials/04-writing-a-task.md +0 -0
  152. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/tutorials/05-comparing-models.md +0 -0
  153. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/tutorials/06-use-docker-isolation.md +0 -0
  154. {coder_eval-0.9.1 → coder_eval-0.9.3}/docs/tutorials/README.md +0 -0
  155. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/.gitignore +0 -0
  156. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/README.md +0 -0
  157. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/_components/__tests__/search-box.test.tsx +0 -0
  158. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/_components/col-help.tsx +0 -0
  159. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/_components/collapsible-rail.tsx +0 -0
  160. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/_components/scroll-table.tsx +0 -0
  161. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/_components/search-box.tsx +0 -0
  162. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/_components/unit-toggle.tsx +0 -0
  163. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/_components/version-list.tsx +0 -0
  164. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/api/download/route.ts +0 -0
  165. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/api/file/route.ts +0 -0
  166. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/api/refresh/__tests__/route.test.ts +0 -0
  167. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/api/refresh/route.ts +0 -0
  168. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/error.tsx +0 -0
  169. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/globals.css +0 -0
  170. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/icon.png +0 -0
  171. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/layout.tsx +0 -0
  172. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/trends/__tests__/trends-view.test.tsx +0 -0
  173. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/trends/actions.ts +0 -0
  174. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/trends/page.tsx +0 -0
  175. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/watchlist/__tests__/watchlist-view.test.tsx +0 -0
  176. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/app/watchlist/page.tsx +0 -0
  177. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/next-env.d.ts +0 -0
  178. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/next.config.mjs +0 -0
  179. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/package.json +0 -0
  180. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/pnpm-lock.yaml +0 -0
  181. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/postcss.config.mjs +0 -0
  182. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/public/harness/antigravity.png +0 -0
  183. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/public/harness/claude-code.png +0 -0
  184. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/public/harness/codex.png +0 -0
  185. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/public/uipath.png +0 -0
  186. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/tailwind.config.ts +0 -0
  187. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/tsconfig.json +0 -0
  188. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/vitest.config.ts +0 -0
  189. {coder_eval-0.9.1 → coder_eval-0.9.3}/evalboard/vitest.setup.ts +0 -0
  190. {coder_eval-0.9.1 → coder_eval-0.9.3}/experiments/default.yaml +0 -0
  191. {coder_eval-0.9.1 → coder_eval-0.9.3}/experiments/early-stop-ab.yaml +0 -0
  192. {coder_eval-0.9.1 → coder_eval-0.9.3}/experiments/model-comparison.yaml +0 -0
  193. {coder_eval-0.9.1 → coder_eval-0.9.3}/experiments/permissions-smoke.yaml +0 -0
  194. {coder_eval-0.9.1 → coder_eval-0.9.3}/experiments/plugin-comparison.yaml +0 -0
  195. {coder_eval-0.9.1 → coder_eval-0.9.3}/experiments/prompt-mutations-example.yaml +0 -0
  196. {coder_eval-0.9.1 → coder_eval-0.9.3}/experiments/smoke_variants.yaml +0 -0
  197. {coder_eval-0.9.1 → coder_eval-0.9.3}/litellm/README.md +0 -0
  198. {coder_eval-0.9.1 → coder_eval-0.9.3}/mkdocs.yml +0 -0
  199. {coder_eval-0.9.1 → coder_eval-0.9.3}/osv-scanner.toml +0 -0
  200. {coder_eval-0.9.1 → coder_eval-0.9.3}/scripts/check_commit_msg.sh +0 -0
  201. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/.gitattributes +0 -0
  202. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/agents/__init__.py +0 -0
  203. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/agents/_logging.py +0 -0
  204. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/agents/noop_agent.py +0 -0
  205. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/agents/registry.py +0 -0
  206. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/agents/watchdog.py +0 -0
  207. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/analysis.py +0 -0
  208. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/cli/__init__.py +0 -0
  209. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/cli/aggregate_command.py +0 -0
  210. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/cli/console.py +0 -0
  211. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/cli/evaluate_command.py +0 -0
  212. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/cli/plan_command.py +0 -0
  213. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/cli/report_command.py +0 -0
  214. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/cli/run_command.py +0 -0
  215. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/cli/run_helpers.py +0 -0
  216. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/cli/run_task_internal_command.py +0 -0
  217. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/cli/utils.py +0 -0
  218. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/__init__.py +0 -0
  219. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/_classification_aggregate.py +0 -0
  220. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/agent_judge.py +0 -0
  221. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/classification_match.py +0 -0
  222. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/commands_efficiency.py +0 -0
  223. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/file_check.py +0 -0
  224. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/file_contains.py +0 -0
  225. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/file_exists.py +0 -0
  226. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/file_matches_regex.py +0 -0
  227. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/json_check.py +0 -0
  228. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/reference_comparison.py +0 -0
  229. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/run_command.py +0 -0
  230. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/criteria/uipath_eval.py +0 -0
  231. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/errors/__init__.py +0 -0
  232. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/errors/agent.py +0 -0
  233. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/errors/budget.py +0 -0
  234. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/errors/categories.py +0 -0
  235. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/errors/categorization.py +0 -0
  236. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/errors/checker_misuse.py +0 -0
  237. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/errors/executor.py +0 -0
  238. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/errors/judge.py +0 -0
  239. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/errors/retry.py +0 -0
  240. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/errors/timeout.py +0 -0
  241. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/evaluation/__init__.py +0 -0
  242. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/evaluation/checker.py +0 -0
  243. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_anthropic.py +0 -0
  244. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_bedrock.py +0 -0
  245. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_context.py +0 -0
  246. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_models.py +0 -0
  247. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_persistence.py +0 -0
  248. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/evaluation/sub_agent.py +0 -0
  249. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/evaluation/summaries.py +0 -0
  250. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/evaluation/verdict_tool.py +0 -0
  251. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/formatting.py +0 -0
  252. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/isolation/__init__.py +0 -0
  253. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/logging_config.py +0 -0
  254. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/agent_config.py +0 -0
  255. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/container_paths.py +0 -0
  256. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/enums.py +0 -0
  257. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/judge.py +0 -0
  258. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/judge_defaults.py +0 -0
  259. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/merge_strategy.py +0 -0
  260. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/mutations.py +0 -0
  261. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/routing.py +0 -0
  262. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/tasks.py +0 -0
  263. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/models/templates.py +0 -0
  264. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/orchestration/__init__.py +0 -0
  265. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/orchestration/config.py +0 -0
  266. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/orchestration/config_merge.py +0 -0
  267. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/orchestration/evaluation.py +0 -0
  268. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/orchestration/experiment.py +0 -0
  269. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/orchestration/overrides.py +0 -0
  270. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/orchestration/task_loader.py +0 -0
  271. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/path_utils.py +0 -0
  272. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/plugins.py +0 -0
  273. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/py.typed +0 -0
  274. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/reports_junit.py +0 -0
  275. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/reports_stats.py +0 -0
  276. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/resources/__init__.py +0 -0
  277. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/resources/default_ignore_patterns.yaml +0 -0
  278. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/resources/tags.yaml +0 -0
  279. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/sandbox.py +0 -0
  280. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/scoring/__init__.py +0 -0
  281. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/scoring/ast_similarity.py +0 -0
  282. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/scoring/complexity.py +0 -0
  283. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/scoring/quality.py +0 -0
  284. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/scoring/signature_similarity.py +0 -0
  285. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/scoring/similarity.py +0 -0
  286. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/scoring/token_similarity.py +0 -0
  287. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/simulation/__init__.py +0 -0
  288. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/simulation/termination.py +0 -0
  289. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/simulation/user_simulator.py +0 -0
  290. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/streaming/__init__.py +0 -0
  291. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/streaming/callbacks.py +0 -0
  292. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/streaming/collector.py +0 -0
  293. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/streaming/events.py +0 -0
  294. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/streaming/renderers.py +0 -0
  295. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/streaming/wire.py +0 -0
  296. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/telemetry.py +0 -0
  297. {coder_eval-0.9.1 → coder_eval-0.9.3}/src/coder_eval/utils.py +0 -0
  298. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/README.md +0 -0
  299. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agentless_smoke_test.yaml +0 -0
  300. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agents/antigravity_hello_world.yaml +0 -0
  301. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agents/antigravity_hello_world_docker.yaml +0 -0
  302. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agents/claude_hello_world.yaml +0 -0
  303. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agents/claude_hello_world_docker.yaml +0 -0
  304. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agents/claude_parallel_single_gen.yaml +0 -0
  305. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agents/claude_subagent_test.yaml +0 -0
  306. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agents/codex_disallowed_tools_test.yaml +0 -0
  307. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agents/codex_hello_world.yaml +0 -0
  308. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agents/codex_parallel_commands.yaml +0 -0
  309. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agents/codex_parallel_single_gen.yaml +0 -0
  310. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agents/codex_skills_test.yaml +0 -0
  311. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agents/codex_string_utils.yaml +0 -0
  312. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agents/codex_subagent_test.yaml +0 -0
  313. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agents/subagent_bash_long_input.yaml +0 -0
  314. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/agents/subagent_merge_sort.yaml +0 -0
  315. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/byod_smoke_test.yaml +0 -0
  316. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/dataset_example.yaml +0 -0
  317. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/datasets/sentiment.jsonl +0 -0
  318. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/dockerfile_build_example/dockerfile_build_example.yaml +0 -0
  319. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/dockerfile_build_example/environment/Dockerfile +0 -0
  320. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/dockerfile_build_example/environment/Dockerfile.workdir +0 -0
  321. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/dockerfile_build_example/environment/input.txt +0 -0
  322. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/dockerfile_build_example/working_dir_auto_example.yaml +0 -0
  323. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/dockerfile_build_example/working_dir_concrete_example.yaml +0 -0
  324. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/fibonacci_with_template.yaml +0 -0
  325. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/hello_date.yaml +0 -0
  326. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/inline_starter_example.yaml +0 -0
  327. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/internal/session_resumption.yaml +0 -0
  328. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/mock_path_dirs_smoke.yaml +0 -0
  329. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/mock_path_dirs_template_dir/mock-cli-bins/README.md +0 -0
  330. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/mock_path_dirs_template_dir/mock-cli-bins/mocks/echo_args +0 -0
  331. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/mock_path_dirs_template_dir/mock-cli-bins/mocks/fixtures/config.json +0 -0
  332. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/mock_path_dirs_template_dir/mock-cli-bins/mocks/say_hello +0 -0
  333. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/mock_path_dirs_template_dir/task.yaml +0 -0
  334. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/python_cli_simulated_judged/echo_simulated_judged.yaml +0 -0
  335. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/3d-scan-calc.yaml +0 -0
  336. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/environment/Dockerfile +0 -0
  337. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/environment/material_density_table.md +0 -0
  338. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/environment/scan_data.stl +0 -0
  339. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/verifier/test.sh +0 -0
  340. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/verifier/test_outputs.py +0 -0
  341. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/README.md +0 -0
  342. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/court-form-filling/court-form-filling.yaml +0 -0
  343. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/court-form-filling/environment/Dockerfile +0 -0
  344. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/court-form-filling/environment/sc100-blank.pdf +0 -0
  345. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/court-form-filling/verifier/test.sh +0 -0
  346. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/court-form-filling/verifier/test_outputs.py +0 -0
  347. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/dialogue-parser/dialogue-parser.yaml +0 -0
  348. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/dialogue-parser/environment/Dockerfile +0 -0
  349. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/dialogue-parser/environment/script.txt +0 -0
  350. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/dialogue-parser/verifier/test.sh +0 -0
  351. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/samples/skillsbench/dialogue-parser/verifier/test_outputs.py +0 -0
  352. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/sentiment_classification.yaml +0 -0
  353. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/smoke_agent_judge.yaml +0 -0
  354. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/smoke_budget_exceeded.yaml +0 -0
  355. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/smoke_cost_budget_exceeded.yaml +0 -0
  356. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/smoke_llm_judge.yaml +0 -0
  357. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/smoke_negative_path.yaml +0 -0
  358. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/smoke_task_timeout.yaml +0 -0
  359. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/smoke_variants.yaml +0 -0
  360. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/test_sandbox.yaml +0 -0
  361. {coder_eval-0.9.1 → coder_eval-0.9.3}/tasks/token_check.yaml +0 -0
  362. {coder_eval-0.9.1 → coder_eval-0.9.3}/templates/byod_smoke_test/Dockerfile +0 -0
  363. {coder_eval-0.9.1 → coder_eval-0.9.3}/templates/fibonacci-starter/README.md +0 -0
  364. {coder_eval-0.9.1 → coder_eval-0.9.3}/templates/fibonacci-starter/src/main.py +0 -0
  365. {coder_eval-0.9.1 → coder_eval-0.9.3}/templates/fibonacci-starter/tests/test_main.py +0 -0
  366. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/__init__.py +0 -0
  367. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/__init__.py +0 -0
  368. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/__init__.py +0 -0
  369. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/claude_fixtures.py +0 -0
  370. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/codex_fixtures.py +0 -0
  371. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_a_single_text_turn.json +0 -0
  372. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_b_tool_use_result.json +0 -0
  373. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_c_multi_emission_delta.json +0 -0
  374. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_d_subagent_terminal.json +0 -0
  375. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_e_model_usage_and_backfill.json +0 -0
  376. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_f_orphaned_tool.json +0 -0
  377. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_g_crash_format_placeholder.json +0 -0
  378. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_h1_timeout_process_error.json +0 -0
  379. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_h2_process_error_crash.json +0 -0
  380. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_i_in_loop_deadline_break.json +0 -0
  381. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_a_agent_message_only.json +0 -0
  382. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_b_command_execution.json +0 -0
  383. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_c_reasoning_placeholder.json +0 -0
  384. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_d_cross_flush_is_error.json +0 -0
  385. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_e_orphan_tool.json +0 -0
  386. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_f_collab_fallback.json +0 -0
  387. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_g_items_rebuild.json +0 -0
  388. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_h_no_turn_completed_crash.json +0 -0
  389. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/__init__.py +0 -0
  390. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/_snapshot.py +0 -0
  391. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/_path_helpers.py +0 -0
  392. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/conftest.py +0 -0
  393. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/fixtures/__init__.py +0 -0
  394. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/fixtures/byoa_demo_plugin/byoa_demo.py +0 -0
  395. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/fixtures/byoa_demo_plugin/pyproject.toml +0 -0
  396. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/fixtures/mock_agent.py +0 -0
  397. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/fixtures/tasks/test_task_informational_criterion.yaml +0 -0
  398. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/fixtures/tasks/test_task_multiple_criteria.yaml +0 -0
  399. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/fixtures/tasks/test_task_pass.yaml +0 -0
  400. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/fixtures/text_stub_agent.py +0 -0
  401. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/__init__.py +0 -0
  402. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/dead_config_fields.py +0 -0
  403. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/doc_env_parity.py +0 -0
  404. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/doc_examples.py +0 -0
  405. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/doc_indexes.py +0 -0
  406. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/doc_schema_parity.py +0 -0
  407. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/__init__.py +0 -0
  408. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/base.py +0 -0
  409. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/ce014_merge_strategy_declared.py +0 -0
  410. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/ce015_create_subprocess_limit.py +0 -0
  411. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/ce016_no_computed_tokenusage_kwargs.py +0 -0
  412. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/ce017_models_lazy_agent_imports.py +0 -0
  413. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/ce018_no_final_status_name_denylist.py +0 -0
  414. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/ce019_telemetry_non_fatal.py +0 -0
  415. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/ce020_no_sdk_typed_base_agent_fields.py +0 -0
  416. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/ce021_guarded_evaluationresult_parse.py +0 -0
  417. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/ce022_dialog_loop_statement_cap.py +0 -0
  418. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/ce023_no_proxy_shim_import.py +0 -0
  419. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/ce024_discriminated_unions.py +0 -0
  420. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/no_agent_timing_access.py +0 -0
  421. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/no_blocking_io_in_async.py +0 -0
  422. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/no_cli_imports_in_core.py +0 -0
  423. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/no_silent_except.py +0 -0
  424. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/no_submodule_model_imports.py +0 -0
  425. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/no_top_level_run_limits_access.py +0 -0
  426. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/no_transcript_regex_in_eval.py +0 -0
  427. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/no_type_name_string_dispatch.py +0 -0
  428. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/open_explicit_encoding.py +0 -0
  429. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/read_text_explicit_encoding.py +0 -0
  430. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/register_criterion_required.py +0 -0
  431. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/subprocess_run_explicit_encoding.py +0 -0
  432. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/rules/yaml_models_forbid_extras.py +0 -0
  433. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/lint/violation.py +0 -0
  434. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_action_version_pin.py +0 -0
  435. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_agent.py +0 -0
  436. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_agent_config_no_timing_fields.py +0 -0
  437. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_agent_config_optional_type.py +0 -0
  438. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_agent_config_registry_dispatch.py +0 -0
  439. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_agent_config_sdk_decoupling.py +0 -0
  440. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_agent_golden_master.py +0 -0
  441. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_agent_judge_criterion.py +0 -0
  442. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_agent_telemetry.py +0 -0
  443. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_agent_telemetry_advanced.py +0 -0
  444. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_agentless.py +0 -0
  445. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_aggregate.py +0 -0
  446. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_byoa_plugin.py +0 -0
  447. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_byoa_plugin_live.py +0 -0
  448. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_byod_feature.py +0 -0
  449. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_check_all_async.py +0 -0
  450. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_checker_logging.py +0 -0
  451. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_classification_match.py +0 -0
  452. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_claude_settings_enforcement_live.py +0 -0
  453. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_cleanup_preservation_guard.py +0 -0
  454. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_cli_backend_flag.py +0 -0
  455. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_cli_empty_glob.py +0 -0
  456. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_cli_sdk_options.py +0 -0
  457. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_cli_set_overrides.py +0 -0
  458. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_cli_telemetry.py +0 -0
  459. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_cli_type_flag.py +0 -0
  460. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_code_review_bugs.py +0 -0
  461. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_codex_agent.py +0 -0
  462. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_codex_agent_live.py +0 -0
  463. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_codex_agent_unit.py +0 -0
  464. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_codex_token_mapping.py +0 -0
  465. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_command_executed.py +0 -0
  466. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_command_statistics.py +0 -0
  467. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_command_telemetry_result_data.py +0 -0
  468. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_commands_efficiency.py +0 -0
  469. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_config_lineage.py +0 -0
  470. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_config_merge_engine.py +0 -0
  471. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_config_precedence.py +0 -0
  472. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_continuous_scoring.py +0 -0
  473. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_criterion_result_round_trip.py +0 -0
  474. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_dataset_expansion.py +0 -0
  475. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_debug_logging.py +0 -0
  476. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_docker_build_failure.py +0 -0
  477. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_docker_runner_container_death.py +0 -0
  478. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_docker_runner_mounts.py +0 -0
  479. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_docker_runner_stream_limit.py +0 -0
  480. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_docker_wildcard_env.py +0 -0
  481. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_docker_workdir_live.py +0 -0
  482. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_driver_resolver.py +0 -0
  483. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_error_handling.py +0 -0
  484. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_evaluate_command.py +0 -0
  485. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_evaluator.py +0 -0
  486. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_experiment_cli.py +0 -0
  487. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_experiment_loader.py +0 -0
  488. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_experiment_models.py +0 -0
  489. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_experiment_resolver.py +0 -0
  490. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_experiment_runner.py +0 -0
  491. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_file_check.py +0 -0
  492. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_file_contains_scoring.py +0 -0
  493. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_formatting.py +0 -0
  494. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_git_clone_failure.py +0 -0
  495. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_heartbeat_watchdog.py +0 -0
  496. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_ignore_patterns_negation.py +0 -0
  497. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_image_from_dockerfiles.py +0 -0
  498. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_integration.py +0 -0
  499. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_json_check.py +0 -0
  500. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_judge_anthropic.py +0 -0
  501. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_judge_bedrock.py +0 -0
  502. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_judge_burn_in_live.py +0 -0
  503. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_judge_context_builder.py +0 -0
  504. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_judge_models.py +0 -0
  505. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_judge_persistence.py +0 -0
  506. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_lint_no_top_level_run_limits.py +0 -0
  507. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_lint_runner.py +0 -0
  508. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_llm_judge_criterion.py +0 -0
  509. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_log_tail_buffer.py +0 -0
  510. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_logging.py +0 -0
  511. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_logging_isolation.py +0 -0
  512. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_merge_characterization.py +0 -0
  513. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_merge_strategy_annotations.py +0 -0
  514. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_merge_unification.py +0 -0
  515. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_models.py +0 -0
  516. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_mutations.py +0 -0
  517. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_new_criteria.py +0 -0
  518. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_node_env_config.py +0 -0
  519. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_optional_dependencies.py +0 -0
  520. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_orchestrator.py +0 -0
  521. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_orchestrator_error_log_tail.py +0 -0
  522. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_orchestrator_telemetry.py +0 -0
  523. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_overrides_engine.py +0 -0
  524. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_parallel.py +0 -0
  525. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_path_utils.py +0 -0
  526. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_plan_command.py +0 -0
  527. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_plugin_processing.py +0 -0
  528. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_plugins.py +0 -0
  529. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_post_run.py +0 -0
  530. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_pr_review_workflow.py +0 -0
  531. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_pre_run.py +0 -0
  532. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_preservation_mode.py +0 -0
  533. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_pricing_registry.py +0 -0
  534. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_reference_comparison_scoring.py +0 -0
  535. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_reference_evaluator.py +0 -0
  536. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_reference_missing_file.py +0 -0
  537. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_reference_models.py +0 -0
  538. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_reference_orchestrator.py +0 -0
  539. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_registry.py +0 -0
  540. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_release_notes.py +0 -0
  541. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_replicate_stats.py +0 -0
  542. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_report_command.py +0 -0
  543. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_reports_experiment.py +0 -0
  544. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_reports_html.py +0 -0
  545. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_reports_junit.py +0 -0
  546. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_reports_stats.py +0 -0
  547. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_reports_stats_nonfinite.py +0 -0
  548. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_resolve_task_files.py +0 -0
  549. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_resume.py +0 -0
  550. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_retry_logic_comprehensive.py +0 -0
  551. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_routing.py +0 -0
  552. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_run_command_junit.py +0 -0
  553. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_run_command_stdout.py +0 -0
  554. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_run_limits_models.py +0 -0
  555. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_run_limits_orchestrator.py +0 -0
  556. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_run_limits_resolver.py +0 -0
  557. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_runtime_tool_versions.py +0 -0
  558. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_sandbox.py +0 -0
  559. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_sandbox_layer_builder.py +0 -0
  560. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_sandbox_optional.py +0 -0
  561. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_sandbox_security.py +0 -0
  562. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_sandbox_symlink_preservation.py +0 -0
  563. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_sandbox_templates.py +0 -0
  564. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_scorers.py +0 -0
  565. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_scoring_quality.py +0 -0
  566. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_sdk_option_classification.py +0 -0
  567. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_simulation_config.py +0 -0
  568. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_simulation_integration.py +0 -0
  569. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_simulation_termination.py +0 -0
  570. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_simulation_trials.py +0 -0
  571. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_skill_triggered.py +0 -0
  572. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_streaming_agent_integration.py +0 -0
  573. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_streaming_batch.py +0 -0
  574. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_streaming_callbacks.py +0 -0
  575. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_streaming_cli.py +0 -0
  576. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_streaming_events.py +0 -0
  577. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_streaming_orchestrator.py +0 -0
  578. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_streaming_renderers.py +0 -0
  579. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_streaming_wire.py +0 -0
  580. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_sub_agent_runner.py +0 -0
  581. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_success_criterion_union.py +0 -0
  582. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_suite_rollup.py +0 -0
  583. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_summaries.py +0 -0
  584. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_tags.py +0 -0
  585. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_task_definition_unknown_fields.py +0 -0
  586. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_teardown_interrupt.py +0 -0
  587. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_telemetry.py +0 -0
  588. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_template_env_expansion.py +0 -0
  589. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_threshold_enforcement.py +0 -0
  590. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_timeout_batch.py +0 -0
  591. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_timeout_categorization.py +0 -0
  592. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_timeout_exceptions.py +0 -0
  593. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_timeout_models.py +0 -0
  594. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_uipath_eval.py +0 -0
  595. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_user_simulator.py +0 -0
  596. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_utils.py +0 -0
  597. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_utterance_extraction.py +0 -0
  598. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_variant_prompt_file.py +0 -0
  599. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_verdict_tool.py +0 -0
  600. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_watchdog.py +0 -0
  601. {coder_eval-0.9.1 → coder_eval-0.9.3}/tests/test_yaml_migration.py +0 -0
@@ -58,6 +58,17 @@ LOG_TO_FILE=false # Set to true to enable file logging
58
58
  # GEMINI_API_KEY="AIza..."
59
59
  # ANTIGRAVITY_MODEL="gemini-3.1-pro-preview"
60
60
 
61
+ # LiteLLM (Anthropic-compatible) open-weight backend (API_BACKEND=litellm). Point
62
+ # the agent at a self-hosted LiteLLM proxy (see litellm/start-litellm.sh, which
63
+ # prints these). LITELLM_COST_LOG must be the SAME path the proxy writes its
64
+ # per-call JSONL to — that is how the run joins ACTUAL OpenRouter cost + cache back
65
+ # onto each turn; if it is unset (or points elsewhere) the run silently falls back
66
+ # to static rate-card pricing with 0 cache reads.
67
+ # LITELLM_BASE_URL="http://localhost:4000"
68
+ # LITELLM_AUTH_TOKEN="sk-..."
69
+ # LITELLM_MODEL="zai.glm-5"
70
+ # LITELLM_COST_LOG="./tmp/litellm-costs.jsonl"
71
+
61
72
  # UiPath CLI plugin-discovery pin. When unset, the sandbox auto-derives
62
73
  # the canonical `node_modules/@uipath` from the resolved `uip` binary at setup
63
74
  # time. Operators on dedicated eval hosts can pin explicitly to override.
@@ -2,6 +2,214 @@
2
2
 
3
3
  <!-- version list -->
4
4
 
5
+ ## v0.9.3 (2026-08-04)
6
+
7
+ ### Bug Fixes
8
+
9
+ - **early-stop**: Address PR review — polarity-blind budget, pass_threshold displacement,
10
+ gate-semantic split ([#74](https://github.com/UiPath/coder_eval/pull/74),
11
+ [`800ac77`](https://github.com/UiPath/coder_eval/commit/800ac7730e53a0ce9e9128b42ea91f0030d01f89))
12
+
13
+ ### Chores
14
+
15
+ - **deps**: Bump aiohttp 3.14.1→3.14.3, cryptography 49.0.0→50.0.0
16
+ ([#74](https://github.com/UiPath/coder_eval/pull/74),
17
+ [`800ac77`](https://github.com/UiPath/coder_eval/commit/800ac7730e53a0ce9e9128b42ea91f0030d01f89))
18
+
19
+ ### Features
20
+
21
+ - **early-stop**: Weighted ceiling/floor bounds + decision-step budget
22
+ ([#74](https://github.com/UiPath/coder_eval/pull/74),
23
+ [`800ac77`](https://github.com/UiPath/coder_eval/commit/800ac7730e53a0ce9e9128b42ea91f0030d01f89))
24
+
25
+
26
+ ## v0.9.2 (2026-07-31)
27
+
28
+ ### Bug Fixes
29
+
30
+ - **cost**: A task timeout with no preserved turn is unrecorded spend, not free
31
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
32
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
33
+
34
+ - **cost**: Book spend on the error and timeout paths, flag what is unpriced
35
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
36
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
37
+
38
+ - **cost**: Flag every hard-killed task as a cost floor, not just the empty ones
39
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
40
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
41
+
42
+ - **evalboard**: Honest scoped counts, and one definition of a run's scope
43
+ ([#69](https://github.com/UiPath/coder_eval/pull/69),
44
+ [`0bdac0b`](https://github.com/UiPath/coder_eval/commit/0bdac0b2bab0d9f2937a2ddc5e54b26d110a56d1))
45
+
46
+ - **litellm**: Gate cost_log_tags on agent capability, not route (fixes non-Claude crash)
47
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
48
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
49
+
50
+ - **litellm**: Make the orphaned-spend warning actually fire
51
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
52
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
53
+
54
+ - **litellm**: Per-attempt cost-log scoping + single run-id accessor + no-match warning
55
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
56
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
57
+
58
+ - **litellm**: Pin each open-weight model to a vetted provider set (no silent fallback)
59
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
60
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
61
+
62
+ - **litellm**: Proxy-authoritative token buckets + all-priced gate + transactional join
63
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
64
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
65
+
66
+ - **litellm**: Sanitize cost headers, reject non-finite cost, drop debug scaffolding
67
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
68
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
69
+
70
+ - **orchestrator**: Recover the in-flight turn's spend on a hard kill
71
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
72
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
73
+
74
+ - **pricing**: Add the claude-opus-5 rate so killed turns stop booking zero
75
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
76
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
77
+
78
+ - **pricing**: Add the five unpriced codex tiers still on OpenAI's rate card
79
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
80
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
81
+
82
+ - **pricing**: Correct every wrong rate-card entry and close the alias gaps
83
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
84
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
85
+
86
+ - **pricing**: Refresh the rate card and correct gemini-3-flash-preview
87
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
88
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
89
+
90
+ - **reports**: Count errors as misses and stop losing cost on error paths
91
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
92
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
93
+
94
+ - **reports**: Count errors as misses in one canonical pass rate
95
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
96
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
97
+
98
+ ### Code Style
99
+
100
+ - **evalboard**: Drop the swatch dots and the scope caption from the header
101
+ ([#69](https://github.com/UiPath/coder_eval/pull/69),
102
+ [`0bdac0b`](https://github.com/UiPath/coder_eval/commit/0bdac0b2bab0d9f2937a2ddc5e54b26d110a56d1))
103
+
104
+ ### Documentation
105
+
106
+ - **cost**: Describe the per-turn backfill as the net it is
107
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
108
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
109
+
110
+ - **cost**: Describe the unpriced-crash mechanism accurately and keep comments framework-general
111
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
112
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
113
+
114
+ - **litellm**: Correct the cost contract after cutting per-message distribution
115
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
116
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
117
+
118
+ - **litellm**: Document LITELLM_COST_LOG wiring + correct the reconciliation-cost contract
119
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
120
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
121
+
122
+ ### Features
123
+
124
+ - **cost**: Publish one accurate total on every reporting surface
125
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
126
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
127
+
128
+ - **docker**: Bind-mount the LiteLLM cost log so --driver docker joins actual cost
129
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
130
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
131
+
132
+ - **evalboard**: Compare every harness on the overview, and scope the whole page to one
133
+ ([#69](https://github.com/UiPath/coder_eval/pull/69),
134
+ [`0bdac0b`](https://github.com/UiPath/coder_eval/commit/0bdac0b2bab0d9f2937a2ddc5e54b26d110a56d1))
135
+
136
+ - **evalboard**: Compare harnesses on the overview, and identify each run
137
+ ([#69](https://github.com/UiPath/coder_eval/pull/69),
138
+ [`0bdac0b`](https://github.com/UiPath/coder_eval/commit/0bdac0b2bab0d9f2937a2ddc5e54b26d110a56d1))
139
+
140
+ - **evalboard**: Lift the harness scope to the page header, in vendor colors
141
+ ([#69](https://github.com/UiPath/coder_eval/pull/69),
142
+ [`0bdac0b`](https://github.com/UiPath/coder_eval/commit/0bdac0b2bab0d9f2937a2ddc5e54b26d110a56d1))
143
+
144
+ - **evalboard**: Make each turn's provider-call table a collapsed dropdown
145
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
146
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
147
+
148
+ - **evalboard**: Mark a partly-priced run total as a floor, not the bill
149
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
150
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
151
+
152
+ - **evalboard**: One set of pass-rate cutoffs, and a run table that pages through all history
153
+ ([#69](https://github.com/UiPath/coder_eval/pull/69),
154
+ [`0bdac0b`](https://github.com/UiPath/coder_eval/commit/0bdac0b2bab0d9f2937a2ddc5e54b26d110a56d1))
155
+
156
+ - **evalboard**: Per-call cost/cache table from provider_call_costs (replaces inline)
157
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
158
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
159
+
160
+ - **evalboard**: Read the canonical pass rate and surface incomplete cost
161
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
162
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
163
+
164
+ - **evalboard**: Say which harness, model, and framework version a run used
165
+ ([#69](https://github.com/UiPath/coder_eval/pull/69),
166
+ [`0bdac0b`](https://github.com/UiPath/coder_eval/commit/0bdac0b2bab0d9f2937a2ddc5e54b26d110a56d1))
167
+
168
+ - **litellm**: Actual per-call cost + cache accounting for the open-weight backend
169
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
170
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
171
+
172
+ ### Refactoring
173
+
174
+ - **cost**: Correct the simulator-cost bound and drop the unread variant error share
175
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
176
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
177
+
178
+ - **cost**: Cut the commentary and drop unreachable rate-card keys
179
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
180
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
181
+
182
+ - **cost**: Define the unpriced-row test once, and only for new runs
183
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
184
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
185
+
186
+ - **cost**: Total_cost_usd means the whole bill everywhere
187
+ ([#63](https://github.com/UiPath/coder_eval/pull/63),
188
+ [`93c7fc0`](https://github.com/UiPath/coder_eval/commit/93c7fc086bbefe74e25625dd8b77106bef736c09))
189
+
190
+ - **evalboard**: Call the UiPath harness Delegate
191
+ ([#69](https://github.com/UiPath/coder_eval/pull/69),
192
+ [`0bdac0b`](https://github.com/UiPath/coder_eval/commit/0bdac0b2bab0d9f2937a2ddc5e54b26d110a56d1))
193
+
194
+ - **litellm**: Cut per-message distribution; turn-level join + per-call audit record
195
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
196
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
197
+
198
+ - **litellm**: Drop the provider field/column — unavailable on the streaming path
199
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
200
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
201
+
202
+ - **litellm**: Stream the cost log + de-duplicate the OpenRouter config comment
203
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
204
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
205
+
206
+ ### Testing
207
+
208
+ - **litellm**: Cover config shape, join ordering, and defensive cost branches
209
+ ([#66](https://github.com/UiPath/coder_eval/pull/66),
210
+ [`4131a2a`](https://github.com/UiPath/coder_eval/commit/4131a2a2983c347023927c66c04756595c3dbceb))
211
+
212
+
5
213
  ## v0.9.1 (2026-07-29)
6
214
 
7
215
  ### Features
@@ -25,6 +25,7 @@ coder_eval/
25
25
  ├── logging_config.py # Structured logging setup
26
26
  ├── path_utils.py # Run ID generation, path utilities
27
27
  ├── pricing.py # Model pricing / cost calculation (ModelPricing, calculate_cost, register_pricing)
28
+ ├── litellm_cost.py # Join proxy-captured ACTUAL per-call cost/cache onto turns (LiteLLM backend; apply_actual_cost)
28
29
  ├── utils.py # Version info helpers
29
30
 
30
31
  ├── agents/
@@ -41,7 +42,7 @@ coder_eval/
41
42
  │ ├── routing.py # ApiRoute (DirectRoute/BedrockRoute)
42
43
  │ ├── sandbox.py # SandboxConfig, ResourceLimits
43
44
  │ ├── tasks.py # TaskDefinition, AgentConfig, Dataset (dataset fan-out + sample)
44
- │ ├── telemetry.py # CommandTelemetry, CommandStatistics, TokenUsage, ReconciliationMessage, TranscriptMessage
45
+ │ ├── telemetry.py # CommandTelemetry, CommandStatistics, TokenUsage, ProviderCallCost, ReconciliationMessage, TranscriptMessage
45
46
  │ └── templates.py # RepoSource, TemplateDirSource, StarterFilesSource
46
47
 
47
48
  ├── criteria/ # Criterion checker plugins (one file per type)
@@ -138,10 +139,10 @@ action.yml # Published composite GitHub Action (coder-ev
138
139
  - **Dataset fan-out**: `TaskDefinition.dataset` (inline rows or JSONL path) expands a single task into N row-tasks with `${row.<field>}` substitution in `initial_prompt` and `success_criteria` string fields. Expansion runs in `task_loader.expand_dataset` **before** variant resolution, so variants cannot override the dataset. Row sampling: CLI `--sample N` (fixed-seed uniform-random N over the whole dataset) overrides `--sample-per-stratum N` / `dataset.sample_per_stratum` (stratified random N-per-stratum, keyed on `stratify_field`, default `expected_skill` — for classification suites like activation). Stratified sampling (whether the N-per-stratum count comes from the **CLI** `--sample-per-stratum` flag or **YAML** `dataset.sample_per_stratum`) is **nondeterministic** by default — it re-draws each run (so the nightly activation suite broadens coverage over time). Set `dataset.sample_seed` to pin a reproducible sample; an explicit seed always wins. (Only `--sample N` uses a fixed seed, since a smoke test wants the same N rows each run.)
139
140
  - **Per-criterion aggregation**: Each `BaseCriterion` subclass exposes `aggregate(criterion, per_row_results) -> CriterionAggregate | None`. Default emits `count / mean / median / std / min / max` so every criterion is suite-thresholdable for free. Classification-style criteria return `ClassificationCriterionResult` (subclass of `CriterionResult`) and layer accuracy / P/R/F1 / confusion via the shared `overlay_classification_metrics` utility. `BaseSuccessCriterion.suite_thresholds` gates the suite on those metrics; CLI exits non-zero on any gate failure.
140
141
  - **Sub-agent token accounting**: There is NO separate per-sub-agent field. Every sub-agent generation is captured as a `parent_tool_use_id`-tagged `AssistantMessage` in the turn transcript, so per-sub-agent usage is derived by grouping those messages on that id (the evalboard's `aggregateSubAgentUsage` does exactly this). Claude bubbles its sub-agent's intermediate generations into the parent stream natively, and the **terminal** generation (delivered as the Agent tool result, never streamed) is synthesized into one via `_synthesize_subagent_terminal_message` from `tool_use_result.usage`. Codex reconstructs all child generations from the child rollout (`_recover_subagent_tool_calls`). The turn total already includes sub-agent cost — Claude via the SDK's cumulative `model_usage`; Codex via `_fold_subagent_tokens`, which folds the child messages (their real per-generation tokens) into the parent total. `CommandTelemetry.result_summary` is stored **untruncated** (no 200-char cap) so sub-agent returns are preserved whole. Set `CODER_EVAL_RAW_SDK_LOG=1` to dump every raw SDK event to the task log for inspection.
141
- - **Reconciliation message (stream self-reconciles to the turn total)**: The per-message stream consistently under-reports the authoritative turn total — a fixed prompt slice (~512 input tokens on Claude) is billed on no SDK-emitted message, and sub-agent input/cache only partially bubbles up. So `EventCollector.build_turn_record` appends one synthetic `ReconciliationMessage` (`role="reconciliation"`, in the `TranscriptMessage` union) per turn, carrying the per-bucket residual = `token_usage` − Σ(assistant message buckets). The invariant: **summing the four token buckets across `TurnRecord.messages` (assistant + reconciliation) equals `token_usage` exactly**, for both Claude and Codex (Codex's stream is already complete after `_recover_subagent_tool_calls`, so its residual is usually 0 and no entry is emitted). This is what lets the evalboard SUM the message stream as the source of truth instead of reading a separate aggregate ("agent tokens"): `selectTokenTotals` returns the stream sum whenever a reconciliation entry is present, and the timeline renders it as its own row. It is agent-agnostic (booked at the single `EventCollector` seam), carries no cost (cost stays on `token_usage`), and is excluded from generation/turn counts and the cost simulator. The Python `token_usage`/`total_token_usage` aggregate is unchanged and still authoritative for budget/judges/reports.
142
+ - **Reconciliation message (stream self-reconciles to the turn total)**: The per-message stream consistently under-reports the authoritative turn total — a fixed prompt slice (~512 input tokens on Claude) is billed on no SDK-emitted message, and sub-agent input/cache only partially bubbles up. So `EventCollector.build_turn_record` appends one synthetic `ReconciliationMessage` (`role="reconciliation"`, in the `TranscriptMessage` union) per turn, carrying the per-bucket residual = `token_usage` − Σ(assistant message buckets). The invariant: **summing the four token buckets across `TurnRecord.messages` (assistant + reconciliation) equals `token_usage` exactly**, for both Claude and Codex (Codex's stream is already complete after `_recover_subagent_tool_calls`, so its residual is usually 0 and no entry is emitted). This is what lets the evalboard SUM the message stream as the source of truth instead of reading a separate aggregate ("agent tokens"): `selectTokenTotals` returns the stream sum whenever a reconciliation entry is present, and the timeline renders it as its own row. It is agent-agnostic (booked at the single `EventCollector` seam), carries no cost (cost stays on `token_usage`), and is excluded from generation/turn counts and the cost simulator. The LiteLLM open-weight actual-cost join (`litellm_cost.apply_actual_cost`) deliberately writes cost at the TURN level only (`token_usage.total_cost_usd` = the real OpenRouter bill) plus the per-call `TurnRecord.provider_call_costs` audit record; it does NOT touch the message token buckets, so `EventCollector` stays the single writer and this invariant holds on every backend. The Python `token_usage`/`total_token_usage` aggregate is unchanged and still authoritative for budget/judges/reports.
142
143
  - **sandbox isolation**: Tasks that don't need MCP servers should set `setting_sources: []` in their `agent:` block to isolate the sandbox from the host project's CLAUDE.md and settings. Without this, the host project's CLAUDE.md (often 20 KB+) is injected into every API call, inflating cache-creation tokens and cost significantly.
143
- - **Run-time caps (non-criterion enforcement)**: `TaskDefinition.run_limits` (`RunLimits` model) is the single namespace for all run-time caps — `max_turns` / `task_timeout` / `turn_timeout` (structural) and `max_input_tokens` / `max_output_tokens` / `max_total_tokens` / `max_usd` (cumulative budget). Token/USD breaches abort with `FinalStatus.TOKEN_BUDGET_EXCEEDED` or `COST_BUDGET_EXCEEDED` (both `category == "failed"`). Structural caps are set from the CLI via `-D run_limits.max_turns=…` / `-D run_limits.task_timeout=…` / `-D run_limits.turn_timeout=…` (field-merged into `run_limits`); budget caps via `-D run_limits.max_usd=…` etc. or YAML. Layered config uses field-merge — a variant block overrides individual keys without replacing the task's block.
144
- - **Early stop on criterion (opt-in)**: `run_limits.stop_early` (default off) ends a single-shot Claude run early once the run's **armed** criteria are decided, so a raised `max_turns` isn't wasted on the smoke flavor. A criterion is armed by `stop_when: pass|fail|decided|auto`; only criteria that can decide from a partial trajectory may arm (non-empty `live_stop_polarities` ClassVar + `live_verdict` override currently `skill_triggered`, `command_executed`; CE025 keeps the two consistent). `decided` arms **both** polarities; `auto` arms whichever polarities **this instance** can decide — the value for dataset-fanned criteria whose positive/distractor role flips per row. Stop rule: the pass-stop fires when every **pass-armed** criterion live-passes (fail-armed distractors are not required to pass; zero pass-armed never pass-stops); the fail-stop fires on the first fail-armed live-fail but is **deferred while any pass-armed criterion is undecided** a distractor misfire must not truncate a positive row's recall signal, so the latched misfire fires once the positives resolve (or the run continues to the cap). A fail-stop is therefore verdict-preserving; a pass-stop can miss a *later* distractor misfire, so authoritative P/R/F1 comes from a `stop_early: false` run. Driven by `orchestration/early_stop.py::EarlyStopWatcher` through the Claude agent's cooperative `should_stop` seam (tool-call granularity, no SIGKILL); live verdicts only *trigger* the stop — the standard `check_all_async` on the frozen trajectory is authoritative. An early-stopped run gates on the **armed subset** (`EvaluationResult.armed_criteria_passed`); a completed run gates on the full set. Every unsupported use is a hard error at resolution (plan *and* run), and a runtime verdict bug **fails open** to a full run. Surfaces: `EarlyStopInfo`, report notes/badges, `stopped_early` run.json rows, `EarlyStopped`/`EarlyStopReason` telemetry dims. Worked rationale: docs/TASK_DEFINITION_GUIDE.md § `stop_early`. Defaults off ⇒ behavior byte-for-behavior unchanged.
144
+ - **Run-time caps (non-criterion enforcement)**: `TaskDefinition.run_limits` (`RunLimits` model) is the single namespace for all *task-level* run-time caps — `max_turns` / `task_timeout` / `turn_timeout` (structural) and `max_input_tokens` / `max_output_tokens` / `max_total_tokens` / `max_usd` (cumulative budget). Token/USD breaches abort with `FinalStatus.TOKEN_BUDGET_EXCEEDED` or `COST_BUDGET_EXCEEDED` (both `category == "failed"`). Structural caps are set from the CLI via `-D run_limits.max_turns=…` / `-D run_limits.task_timeout=…` / `-D run_limits.turn_timeout=…` (field-merged into `run_limits`); budget caps via `-D run_limits.max_usd=…` etc. or YAML. Layered config uses field-merge — a variant block overrides individual keys without replacing the task's block. The one *per-criterion* cap, `max_steps_to_decide`, deliberately lives on `LiveSuccessCriterion` instead (see below) — the watcher must attribute a decision-step-budget breach to a specific criterion, which `RunLimits` (task-scoped, criterion-agnostic) cannot express.
145
+ - **Early stop on criterion (opt-in)**: `run_limits.stop_early` (default off) ends a single-shot Claude run early once the run's **armed** criteria are decided, so a raised `max_turns` isn't wasted on the smoke flavor. A criterion is armed by `stop_when: pass|fail|decided|auto`; only criteria that can decide from a partial trajectory may arm — "is this criterion type live-observable" is `models.LiveSuccessCriterion` subclassing (currently `skill_triggered`, `command_executed`), the single source of truth `validate_early_stop`/`EarlyStopWatcher` check directly via `isinstance`; each subclass implements the abstract, checker-independent `live_decidable_polarities()` (a pure function of its own fields) alongside the checker's `live_verdict` override, and lint rule CE025 (`tests/test_custom_lint.py::TestCE025LiveVerdictConsistency`, a registry-based whole-tree check, not a per-file AST rule) keeps the two paired. `decided` arms **both** polarities; `auto` arms whichever polarities **this instance** can decide — the value for dataset-fanned criteria whose positive/distractor role flips per row. Stop rule is weighted, not strict-boolean: `run_limits.stop_early_gate_threshold` (default `1.0`, reproducing pre-weighting behavior byte-for-byte) is the minimum weighted score ( weight·score / Σ weight` over the armed subset) required to pass; a fail-stop fires once the armed subset's **ceiling** (best case for everything still undecided) can no longer reach the threshold, a pass-stop once the pass-armed subset's **floor** (worst case) already meets it — both **deferred while any pass-armed criterion is undecided**, so a distractor misfire never truncates a positive row's recall signal before the positives resolve (or the run continues to the cap). A fail-stop is therefore verdict-preserving; a pass-stop can miss a *later* distractor misfire, so authoritative P/R/F1 comes from a `stop_early: false` run. A per-criterion `max_steps_to_decide` (on `LiveSuccessCriterion` only, requires `stop_when`) caps tool-call steps spent still undecided — cumulative across retry attempts of the same turn — before `EarlyStopReason.DECISION_BUDGET_EXCEEDED` force-fails the run outright, bypassing the weighted gate (nothing to weigh a criterion that never decided against). Driven by `orchestration/early_stop.py::EarlyStopWatcher` through the Claude agent's cooperative `should_stop` seam (tool-call granularity, no SIGKILL); live verdicts only *trigger* the stop — the standard `check_all_async` on the frozen trajectory is authoritative. An early-stopped run gates on the **armed subset** via the weighted `EvaluationResult.armed_criteria_passed`; a run that completes naturally (even with `stop_early: true`) gates on the full set via the strict-AND `all_criteria_passed` — weight magnitude only forgives under the former, so the weighted gate is contingent on the watcher itself firing, not solely on the configured threshold. Every unsupported use is a hard error at resolution (plan *and* run), and a runtime verdict bug **fails open** to a full run. Surfaces: `EarlyStopInfo` (incl. `gate_threshold` at stop time), report notes/badges, `stopped_early` run.json rows, `EarlyStopped`/`EarlyStopReason` telemetry dims. Worked rationale: docs/TASK_DEFINITION_GUIDE.md § `stop_early`. Defaults off ⇒ behavior byte-for-behavior unchanged.
145
146
 
146
147
  ## Success Criteria (14 types)
147
148
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: coder-eval
3
- Version: 0.9.1
3
+ Version: 0.9.3
4
4
  Summary: Evaluate, benchmark, and A/B-test AI coding agents (Claude Code, Codex, Gemini/Antigravity) with sandboxed, reproducible YAML task suites.
5
5
  Project-URL: Homepage, https://coder-eval.com
6
6
  Project-URL: Repository, https://github.com/UiPath/coder_eval
@@ -33,7 +33,7 @@ inputs:
33
33
  version:
34
34
  description: coder-eval version to install from PyPI, or "local" to install from the action checkout
35
35
  required: false
36
- default: "0.9.1" # <-- kept in sync with releases by release.yml
36
+ default: "0.9.3" # <-- kept in sync with releases by release.yml
37
37
  run-dir:
38
38
  description: Run directory (--run-dir)
39
39
  required: false
@@ -210,8 +210,16 @@ Notes:
210
210
  `count/mean/median/std/min/max`, so your criterion is suite-thresholdable for free.
211
211
  Classification-style criteria return a `ClassificationCriterionResult` and layer
212
212
  accuracy / precision / recall / F1 / confusion on top.
213
- - For **early stop**, implement `live_verdict(...)` and declare
214
- `live_stop_polarities` a lint rule keeps the two consistent.
213
+ - For **early stop**, make your criterion model subclass `LiveSuccessCriterion`
214
+ (`models/criteria.py`) instead of `BaseSuccessCriterion`, implement its
215
+ abstract `live_decidable_polarities()` (a pure function of the criterion's
216
+ own fields — no `turn_records`, no checker instance), and override the
217
+ checker's `live_verdict(...)`. `LiveSuccessCriterion` subclassing is the
218
+ single source of truth for "is this criterion type live-observable" —
219
+ `validate_early_stop`/`EarlyStopWatcher` check `isinstance(c,
220
+ LiveSuccessCriterion)` directly, no separate checker-side flag. A lint rule
221
+ (`tests/test_custom_lint.py::TestCE025LiveVerdictConsistency`) keeps the
222
+ model subclassing and the checker's `live_verdict` override paired.
215
223
 
216
224
  > A duplicate `criterion_type` **overwrites** the earlier checker with a warning (not
217
225
  > a hard error, unlike agents) — keep type strings unique.
@@ -51,6 +51,21 @@ run-level summary; full per-replicate detail lives in each `task.json`.
51
51
  | `framework_version` | `str` | Coder Eval version chip. |
52
52
  | `environment_info` | `dict` | Version/dependency info (may nest, e.g. `tool_plugins`). |
53
53
 
54
+ These are **computed**, not stored — derived from the counts and rows above on every
55
+ serialization, so they cannot drift from what they summarize. Read them rather than
56
+ re-deriving your own; independent re-derivations are how two consumers end up
57
+ publishing different numbers for the same run.
58
+
59
+ | Key | Type | Meaning |
60
+ | --- | --- | --- |
61
+ | `pass_rate` | `float \| None` | `tasks_succeeded / tasks_run` — errors are in the denominator, counted as misses. `None` on an empty run (0/0 is unknown, not 0%). |
62
+ | `error_share` | `float \| None` | `tasks_error / tasks_run`. Diagnostic only; never adjusts the rate. |
63
+ | `total_cost_usd` | `float \| None` | **The bill**: agent + judge + simulator, summed over the rows. `None` when nothing could be priced. |
64
+ | `agent_cost_usd` | `float \| None` | Subject-agent spend alone. The harness-vs-harness comparison figure — judge spend is a property of the suite's criteria and identical across harnesses, so leaving it in would make two harnesses look closer than they are. |
65
+ | `eval_overhead_cost_usd` | `float \| None` | Judge + simulator spend. The other half of `total_cost_usd`. |
66
+ | `tasks_cost_incomplete` | `int` | Rows whose recorded spend is missing money (unpriced model, or a hard kill that lost an in-flight turn). |
67
+ | `cost_complete` | `bool` | `tasks_cost_incomplete == 0`. When false, every cost figure above is a **floor**, not the bill. A run is never failed for this — see [Missing cost is never fatal](#missing-cost-is-never-fatal). |
68
+
54
69
  ### `task_results[]` — the flat per-task row
55
70
 
56
71
  Each entry is an **untyped dict** (a denormalization, not a Pydantic model) with keys
@@ -58,7 +73,10 @@ including: `task_id`, `replicate_index`, `variant_id`, `status`
58
73
  ([`FinalStatus`](#finalstatus)), `weighted_score`, `duration`, `iteration_count`,
59
74
  `tags`, `task_path`, `model_used`, `reference_similarity`, the token buckets
60
75
  (`input_tokens` = uncached input, `output_tokens`, `cache_creation_input_tokens`,
61
- `cache_read_input_tokens`, `total_tokens`), `total_cost_usd`, `expected_commands`,
76
+ `cache_read_input_tokens`, `total_tokens`), the cost fields
77
+ (`total_cost_usd` = agent + judge + simulator, plus the `agent_cost_usd` /
78
+ `judge_cost_usd` / `simulator_cost_usd` slices and the `cost_complete` flag),
79
+ `expected_commands`,
62
80
  `actual_commands`, `commands_efficiency`, `agent_config`, `sdk_options`,
63
81
  `installed_tools`, turn accounting (`total_turns`, `visible_turns`, `expected_turns`,
64
82
  `max_turns_exhausted`, `has_final_reply`), and early-stop fields (`stopped_early`,
@@ -66,6 +84,29 @@ including: `task_id`, `replicate_index`, `variant_id`, `status`
66
84
  turn digest (`{iteration, duration_seconds, command_count, assistant_turn_count,
67
85
  crashed, crash_reason}`) — the full transcript is in `task.json`.
68
86
 
87
+ ### Missing cost is never fatal
88
+
89
+ Pricing degrades; the evaluation does not. A model absent from the rate card, a turn
90
+ the backend never priced, a hard-killed task that lost its in-flight spend: each one
91
+ lowers a total and sets `cost_complete: false`. None of them raises, none of them
92
+ books a zero, and none of them changes a run's exit code.
93
+
94
+ The reasoning is that the two failure modes are not symmetric. A missing cost is
95
+ recoverable after the fact — the token counts are on the record, so a corrected rate
96
+ card reprices the run from its artifacts. A failed run is not: the tokens are already
97
+ spent and the only way back is to run it again. So the framework warns loudly and
98
+ keeps going.
99
+
100
+ The warning fires up front. `check_pricing_coverage` walks every model the run pins
101
+ (subject agents and judge criteria) before the first task dispatches, and logs the
102
+ ones the card cannot price — early enough to fix the card and restart while it is
103
+ still cheap. After that the run is on its own: totals become floors, and
104
+ `tasks_cost_incomplete` says how many rows are behind that floor.
105
+
106
+ Consumers should treat any cost field as a lower bound whenever `cost_complete` is
107
+ false, and must not read `None` as `0.0` — "nothing could be priced" and "it was
108
+ free" are different facts.
109
+
69
110
  ---
70
111
 
71
112
  ## `task.json` — `EvaluationResult`
@@ -127,23 +168,33 @@ fields so subclass keys round-trip.
127
168
  `iteration`, `user_input`, `agent_output`, `commands` (`list[CommandTelemetry]`),
128
169
  `timestamp`, `duration_seconds`, `token_usage`, `model_used`, `assistant_turn_count`,
129
170
  `messages` (`list[TranscriptMessage]`, discriminated on `role`:
130
- `user`/`assistant`/`reconciliation`), `num_turns`, `max_turns_exhausted`,
171
+ `user`/`assistant`/`reconciliation`), `provider_call_costs`
172
+ (`list[ProviderCallCost]` — one row per real upstream call with its ACTUAL cost +
173
+ cache buckets, captured proxy-side on the LiteLLM open-weight backend and rendered
174
+ by the evalboard as a per-call table; empty on every other
175
+ backend), `num_turns`, `max_turns_exhausted`,
131
176
  `result_summary` (`{is_error, subtype, stop_reason, result}`), `crashed`,
132
177
  `crash_reason`.
133
178
 
134
179
  > **Token invariant.** Summing the four token buckets across `messages`
135
180
  > (assistant + the synthetic `reconciliation` entry) equals `token_usage` exactly.
136
181
  > The `reconciliation` message carries the residual the per-message stream
137
- > under-reports; it has no cost and is excluded from turn/generation counts. See the
138
- > [Claude Code guide](agents/CLAUDE_CODE.md#telemetry).
182
+ > under-reports; it has no cost and is excluded from turn/generation counts. The
183
+ > LiteLLM actual-cost join writes cost at the TURN level only (`token_usage.total_cost_usd`
184
+ > = the real bill) plus the per-call `provider_call_costs` audit record — it does
185
+ > NOT touch the message token buckets, so this invariant holds on every backend.
186
+ > See the [Claude Code guide](agents/CLAUDE_CODE.md#telemetry).
139
187
 
140
188
  ### EarlyStopInfo
141
189
 
142
190
  Present (non-`null`) iff the run stopped early — there is no separate boolean.
143
- Fields: `reason` (`criterion_passed` / `criterion_failed`),
191
+ Fields: `reason` (`criterion_passed` / `criterion_failed` /
192
+ `decision_budget_exceeded` — the last forces `FinalStatus.FAILURE` outright,
193
+ bypassing the weighted gate),
144
194
  `deciding_criterion_type`, `deciding_criterion_description`, `armed_criteria`,
145
195
  `sdk_turn_index`, `tool_call_index` (1-based, includes the in-flight call),
146
- `elapsed_seconds`, `turns_remaining_at_stop`.
196
+ `elapsed_seconds`, `turns_remaining_at_stop`, `gate_threshold` (the
197
+ `run_limits.stop_early_gate_threshold` in effect for this stop; default `1.0`).
147
198
 
148
199
  ---
149
200
 
@@ -247,6 +298,12 @@ respectively), checked after each completed agent turn — see
247
298
  - `TokenUsage.total_tokens` is not serialized; sum the buckets (or use the computed
248
299
  `input_tokens` + `output_tokens` + cache buckets).
249
300
  - `EarlyStopInfo` presence is itself the "stopped early" signal.
301
+ - `total_cost_usd` is the whole bill (agent + judge + simulator) at both row and run
302
+ level; `agent_cost_usd` is the agent-only slice. `TokenUsage.total_cost_usd` is a
303
+ different thing: the cost of those tokens, so always agent-only. `run_limits.max_usd`
304
+ gates on that one, since judge and simulator spend is not known mid-run.
305
+ - A cost of `None` means unpriced, not free, and any total is a floor while
306
+ `cost_complete` is false — see [Missing cost is never fatal](#missing-cost-is-never-fatal).
250
307
 
251
308
  ## See also
252
309
 
@@ -260,6 +260,7 @@ run_limits:
260
260
  | `count_cached_input` | `false` | — | Count `cache_read_input_tokens` toward the input/total budgets. Off by default — cached reads are typically free. |
261
261
  | `count_cache_creation` | `false` | — | Count `cache_creation_input_tokens` toward the input/total budgets. Off by default. |
262
262
  | `stop_early` | `false` | — | Opt-in master switch for early-stop-on-criterion. See [`stop_early`](#stop_early-opt-in-early-stop). |
263
+ | `stop_early_gate_threshold` | `1.0` | `[0.0, 1.0]` (but `> 0.0` is enforced at resolution when `stop_early: true`) | Minimum weighted score over the armed subset required to gate as a pass. See [`stop_early`](#stop_early-opt-in-early-stop). |
263
264
 
264
265
  The authoritative source is `src/coder_eval/models/limits.py`. A lint rule (CE030) fails the build if
265
266
  a field defined there goes undocumented in this guide, so the table can't quietly fall behind the
@@ -376,11 +377,14 @@ Semantics:
376
377
  (e.g. `stop_when: pass` alongside a `max_count`, or `auto` on an instance that
377
378
  can decide neither) is likewise a hard error at resolution, not a silent full
378
379
  run.
379
- - **Verdict.** An early-stopped run is gated on the **armed subset only**; the
380
- non-armed criteria become **advisory** and are clearly marked (report badge +
381
- per-criterion note + `stopped_early` row). A run that completes naturally is
382
- gated on the **full** set, as always. This is what lets one file serve both a
383
- `smoke` flavor (`stop_early: true`) and an `e2e` flavor (`stop_early: false`)
380
+ - **Verdict.** Any task armed for early-stop (`stop_early: true`) is gated on
381
+ the **armed subset only** — the non-armed criteria become **advisory** and
382
+ are clearly marked (report badge + per-criterion note + `stopped_early`
383
+ row when the watcher actually fired) whether or not the watcher actually
384
+ cut the run short; one task config maps to one gate semantic. Only a task
385
+ that never armed `stop_early` at all is gated on the **full** set, as
386
+ always. This is what lets one file serve both a `smoke` flavor
387
+ (`stop_early: true`) and an `e2e` flavor (`stop_early: false`) —
384
388
  see [AB_EXPERIMENTS.md](AB_EXPERIMENTS.md). Verdict parity between the flavors
385
389
  is one-sided: a **fail-stop** is verdict-preserving (the deferral above
386
390
  guarantees every pass-armed signal was allowed to resolve first), but a
@@ -390,6 +394,57 @@ Semantics:
390
394
  authoritative precision/recall belongs on the `stop_early: false` run.
391
395
  - **Fail-safe.** A live-verdict bug **fails open** to a full run (logged loudly) —
392
396
  it can never silently disable a criterion or cause a false early stop.
397
+ - **Weighting.** `run_limits.stop_early_gate_threshold` (default `1.0`) is the
398
+ minimum weighted score (`Σ weight·score / Σ weight`, over the armed subset)
399
+ required to gate as a pass — both for the post-hoc verdict and for the live
400
+ stop rule itself. A fail-stop fires once the armed subset's **ceiling** (best
401
+ case: every still-undecided or already-passed criterion ends up scoring 1.0,
402
+ every live-failed one scores 0) can no longer reach the threshold — the gate
403
+ is mathematically guaranteed to fail regardless of how the trajectory
404
+ continues. A pass-stop fires once the pass-armed subset's **floor** (worst
405
+ case: every still-undecided one scores 0) already meets it. At the default
406
+ `1.0` both bounds collapse to the pre-weighting rules above exactly (any
407
+ single armed criterion's live-fail already drops the ceiling below 1.0, and
408
+ the floor only reaches 1.0 once every pass-armed criterion has actually
409
+ passed) — lowering it lets a low-weight armed criterion's failure be absorbed
410
+ without truncating the run, at the cost of the gate becoming a genuine
411
+ weighted average rather than a strict AND. **The armed weighted gate applies
412
+ whenever `stop_early: true` is set — one task config, one gate semantic —
413
+ regardless of whether the watcher actually fired a stop.** A task armed for
414
+ early-stop that instead completes naturally (the agent finishes, or
415
+ `max_turns` is hit, before the bound ever trips) is gated on the *same*
416
+ weighted armed-subset formula as an actual early stop, not the full-run
417
+ `all_criteria_passed`; only a task that never armed `stop_early` at all uses
418
+ the strict full-set gate. Each armed criterion's own `pass_threshold` still
419
+ decides whether it individually passed (converted to a binary 1.0/0.0
420
+ before weighting) — only the combination rule (weighted average vs strict
421
+ AND) changes, which is what makes the `gate_threshold=1.0` default an exact
422
+ equivalence with the pre-weighting `all(...)` rule.
423
+ - **Decision-step budget.** `max_steps_to_decide` (per armed criterion, only
424
+ on `skill_triggered` / `command_executed`, requires `stop_when`) caps how
425
+ many tool-call steps that criterion may spend still **undecided** before the
426
+ run gives up on it:
427
+
428
+ ```yaml
429
+ success_criteria:
430
+ - type: skill_triggered
431
+ description: "date-teller must activate within 5 steps"
432
+ skill_name: date-teller
433
+ expected_skill: date-teller
434
+ stop_when: pass
435
+ max_steps_to_decide: 5
436
+ ```
437
+
438
+ Once the cap is exceeded (checked AFTER the normal fail-/pass-stop checks
439
+ each round, so a criterion that decides on that very step is never
440
+ penalized), the watcher fires `reason: decision_budget_exceeded` and the run
441
+ is forced to `FinalStatus.FAILURE` outright — bypassing
442
+ `stop_early_gate_threshold`'s weighted gate entirely, since a criterion that
443
+ never reached a verdict has nothing meaningful to weigh against the others.
444
+ `None` (default) = no cap; the run relies solely on `run_limits.max_turns`.
445
+ The step count is **cumulative across every retry attempt** of the turn —
446
+ including an attempt that crashed or timed out before this criterion's own
447
+ investigation even began — so size the budget with that headroom in mind.
393
448
 
394
449
  Observability (every early-stopped run is flagged everywhere so analysis never
395
450
  compares a truncated run against a full one):
@@ -535,6 +590,7 @@ All criteria share these fields:
535
590
  | `weight` | 1.0 | Relative importance for weighted score. `0` = **informational**: excluded from both the score and the pass/fail gate |
536
591
  | `pass_threshold` | 0.9 | Minimum score (0.0–1.0) to pass |
537
592
  | `stop_when` | `null` | Arms this criterion for early stop (`pass`/`fail`/`decided`/`auto`); requires `run_limits.stop_early: true` and an observable criterion type (`skill_triggered`, `command_executed`). `auto` arms whichever polarity this instance can decide (for dataset-fanned criteria whose positive/distractor role flips per row). See [`stop_early`](#stop_early-opt-in-early-stop). |
593
+ | `max_steps_to_decide` | `null` | **Only on live-observable criteria** (`skill_triggered`, `command_executed`) — requires `stop_when` to be set. Caps the tool-call steps this armed criterion may spend still undecided before the run gives up and force-fails. See [`stop_early`](#stop_early-opt-in-early-stop). |
538
594
 
539
595
  **Scoring types:**
540
596
  - **Binary** (1.0 or 0.0): `file_exists`, `run_command`, `file_matches_regex`, `classification_match`, `skill_triggered`
@@ -0,0 +1,45 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { render, screen } from "@testing-library/react";
3
+ import { KNOWN_HARNESSES } from "@/lib/harness";
4
+ import { HarnessBadge, harnessShortLabel } from "../harness-badge";
5
+
6
+ describe("harnessShortLabel", () => {
7
+ test("every known harness has a human label", () => {
8
+ // A missing entry falls through to the raw id, which would put
9
+ // "delegate-sdk" in a legend next to "Codex" and "Antigravity".
10
+ for (const h of KNOWN_HARNESSES) {
11
+ expect(harnessShortLabel(h)).not.toBe(h);
12
+ }
13
+ });
14
+
15
+ test("the UiPath harness reads as Delegate", () => {
16
+ // The run data's id stays `delegate-sdk` (it's the registered
17
+ // `agent.type`); only the label people read is the short one.
18
+ expect(harnessShortLabel("delegate-sdk")).toBe("Delegate");
19
+ });
20
+
21
+ test("an unknown harness falls back to its id rather than a wrong name", () => {
22
+ expect(harnessShortLabel("some-new-agent")).toBe("some-new-agent");
23
+ });
24
+ });
25
+
26
+ describe("HarnessBadge", () => {
27
+ test("names the vendor in the alt text, not just the product", () => {
28
+ render(<HarnessBadge harness="delegate-sdk" />);
29
+ expect(screen.getByAltText("Delegate · UiPath")).toBeInTheDocument();
30
+ });
31
+
32
+ test("renders the id as text when there is no logo for it", () => {
33
+ // Better a raw id than another vendor's mark on someone else's run.
34
+ render(<HarnessBadge harness="some-new-agent" />);
35
+ expect(screen.getByText("some-new-agent")).toBeInTheDocument();
36
+ });
37
+
38
+ test("takes a size so the chart legend can sit inside 11px text", () => {
39
+ render(<HarnessBadge harness="codex" size={14} />);
40
+ expect(screen.getByAltText("Codex · OpenAI")).toHaveAttribute(
41
+ "width",
42
+ "14",
43
+ );
44
+ });
45
+ });