coder-eval 0.9.2__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 (597) hide show
  1. {coder_eval-0.9.2 → coder_eval-0.9.3}/CHANGELOG.md +21 -0
  2. {coder_eval-0.9.2 → coder_eval-0.9.3}/CLAUDE.md +2 -2
  3. {coder_eval-0.9.2 → coder_eval-0.9.3}/PKG-INFO +1 -1
  4. {coder_eval-0.9.2 → coder_eval-0.9.3}/action.yml +1 -1
  5. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/EXTENDING.md +10 -2
  6. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/REPORT_SCHEMA.md +5 -2
  7. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/TASK_DEFINITION_GUIDE.md +61 -5
  8. {coder_eval-0.9.2 → coder_eval-0.9.3}/pyproject.toml +1 -1
  9. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/__init__.py +1 -1
  10. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/base.py +21 -34
  11. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/command_executed.py +1 -37
  12. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/skill_triggered.py +5 -35
  13. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/__init__.py +4 -0
  14. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/criteria.py +132 -3
  15. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/limits.py +43 -7
  16. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/results.py +52 -5
  17. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/early_stop.py +204 -52
  18. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestrator.py +55 -12
  19. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/reports.py +8 -4
  20. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/reports_experiment.py +4 -0
  21. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/reports_html.py +9 -3
  22. coder_eval-0.9.3/tasks/early_stop_decision_budget_exceeded.yaml +40 -0
  23. coder_eval-0.9.3/tasks/early_stop_weighted_high_weight_kills_run.yaml +55 -0
  24. coder_eval-0.9.3/tasks/early_stop_weighted_low_weight_absorbed.yaml +54 -0
  25. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/runner.py +0 -2
  26. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_custom_lint.py +99 -56
  27. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_early_stop.py +618 -58
  28. {coder_eval-0.9.2 → coder_eval-0.9.3}/uv.lock +110 -110
  29. coder_eval-0.9.2/tests/lint/rules/ce025_live_verdict_consistency.py +0 -111
  30. {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-code-review-full.md +0 -0
  31. {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-code-review-wf.md +0 -0
  32. {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-code-review.md +0 -0
  33. {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-create-plan.md +0 -0
  34. {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-implement-plan.md +0 -0
  35. {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-review.md +0 -0
  36. {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-run-analysis.md +0 -0
  37. {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-task-create.md +0 -0
  38. {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/harness-candidates.md +0 -0
  39. {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/shared/axes.md +0 -0
  40. {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/shared/multi-model-review.md +0 -0
  41. {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/shared/review-rubric.md +0 -0
  42. {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/shared/run-layout.md +0 -0
  43. {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/workflows/cr-axis.js +0 -0
  44. {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/workflows/cr-parent.js +0 -0
  45. {coder_eval-0.9.2 → coder_eval-0.9.3}/.env.example +0 -0
  46. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/CODEOWNERS +0 -0
  47. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/ISSUE_TEMPLATE/adopter.yml +0 -0
  48. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  49. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  50. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/code_review.md +0 -0
  51. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/dependabot.yml +0 -0
  52. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/pages-stub/index.html +0 -0
  53. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/scripts/release_notes.py +0 -0
  54. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/claude-pr-review.yml +0 -0
  55. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/codeql.yml +0 -0
  56. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/conventional-commits.yml +0 -0
  57. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/docker-publish.yml +0 -0
  58. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/docs.yml +0 -0
  59. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/pr-checks.yml +0 -0
  60. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/publish-testpypi.yml +0 -0
  61. {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/release.yml +0 -0
  62. {coder_eval-0.9.2 → coder_eval-0.9.3}/.gitignore +0 -0
  63. {coder_eval-0.9.2 → coder_eval-0.9.3}/.pre-commit-config.yaml +0 -0
  64. {coder_eval-0.9.2 → coder_eval-0.9.3}/.python-version +0 -0
  65. {coder_eval-0.9.2 → coder_eval-0.9.3}/ADOPTERS.md +0 -0
  66. {coder_eval-0.9.2 → coder_eval-0.9.3}/CODE_OF_CONDUCT.md +0 -0
  67. {coder_eval-0.9.2 → coder_eval-0.9.3}/CONTRIBUTING.md +0 -0
  68. {coder_eval-0.9.2 → coder_eval-0.9.3}/LICENSE +0 -0
  69. {coder_eval-0.9.2 → coder_eval-0.9.3}/Makefile +0 -0
  70. {coder_eval-0.9.2 → coder_eval-0.9.3}/NOTICE +0 -0
  71. {coder_eval-0.9.2 → coder_eval-0.9.3}/README.md +0 -0
  72. {coder_eval-0.9.2 → coder_eval-0.9.3}/SECURITY.md +0 -0
  73. {coder_eval-0.9.2 → coder_eval-0.9.3}/docker/Dockerfile +0 -0
  74. {coder_eval-0.9.2 → coder_eval-0.9.3}/docker/Dockerfile.runtime +0 -0
  75. {coder_eval-0.9.2 → coder_eval-0.9.3}/docker/coder_eval_entrypoint.sh +0 -0
  76. {coder_eval-0.9.2 → coder_eval-0.9.3}/docker/coder_eval_runtime_entrypoint.sh +0 -0
  77. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/AB_EXPERIMENTS.md +0 -0
  78. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/CI_GATE.md +0 -0
  79. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/DATASETS.md +0 -0
  80. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/DIALOG_MODE.md +0 -0
  81. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/DOCKER_ISOLATION.md +0 -0
  82. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/USER_GUIDE.md +0 -0
  83. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/agents/ANTIGRAVITY.md +0 -0
  84. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/agents/CLAUDE_CODE.md +0 -0
  85. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/agents/CODEX.md +0 -0
  86. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/assets/hero.gif +0 -0
  87. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/comparison.md +0 -0
  88. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/index.md +0 -0
  89. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/llms.txt +0 -0
  90. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/tutorials/01-first-evaluation.md +0 -0
  91. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/tutorials/02-ci-pipeline.md +0 -0
  92. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/tutorials/03-evalboard-local.md +0 -0
  93. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/tutorials/04-writing-a-task.md +0 -0
  94. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/tutorials/05-comparing-models.md +0 -0
  95. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/tutorials/06-use-docker-isolation.md +0 -0
  96. {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/tutorials/README.md +0 -0
  97. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/.gitignore +0 -0
  98. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/README.md +0 -0
  99. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/__tests__/harness-badge.test.tsx +0 -0
  100. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/__tests__/harness-selector.test.tsx +0 -0
  101. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/__tests__/search-box.test.tsx +0 -0
  102. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/col-help.tsx +0 -0
  103. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/collapsible-rail.tsx +0 -0
  104. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/harness-badge.tsx +0 -0
  105. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/harness-selector.tsx +0 -0
  106. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/scroll-table.tsx +0 -0
  107. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/search-box.tsx +0 -0
  108. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/unit-toggle.tsx +0 -0
  109. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/version-list.tsx +0 -0
  110. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/__tests__/harness-legend.test.tsx +0 -0
  111. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/__tests__/harness-series.test.ts +0 -0
  112. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/daily-chart.tsx +0 -0
  113. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/harness-legend.tsx +0 -0
  114. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/harness-series.ts +0 -0
  115. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/tag-rail.tsx +0 -0
  116. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/turn-budget-chart.tsx +0 -0
  117. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/window-summary.tsx +0 -0
  118. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/api/download/route.ts +0 -0
  119. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/api/file/route.ts +0 -0
  120. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/api/refresh/__tests__/route.test.ts +0 -0
  121. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/api/refresh/route.ts +0 -0
  122. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/error.tsx +0 -0
  123. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/globals.css +0 -0
  124. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/icon.png +0 -0
  125. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/layout.tsx +0 -0
  126. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/page.tsx +0 -0
  127. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/path-to-ga/page.tsx +0 -0
  128. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/trends/__tests__/trends-view.test.tsx +0 -0
  129. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/trends/actions.ts +0 -0
  130. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/trends/page.tsx +0 -0
  131. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/trends/trends-view.tsx +0 -0
  132. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/watchlist/__tests__/watchlist-view.test.tsx +0 -0
  133. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/watchlist/page.tsx +0 -0
  134. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/watchlist/watchlist-view.tsx +0 -0
  135. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/next-env.d.ts +0 -0
  136. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/next.config.mjs +0 -0
  137. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/package.json +0 -0
  138. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/pnpm-lock.yaml +0 -0
  139. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/postcss.config.mjs +0 -0
  140. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/public/harness/antigravity.png +0 -0
  141. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/public/harness/claude-code.png +0 -0
  142. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/public/harness/codex.png +0 -0
  143. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/public/uipath.png +0 -0
  144. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/tailwind.config.ts +0 -0
  145. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/tsconfig.json +0 -0
  146. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/vitest.config.ts +0 -0
  147. {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/vitest.setup.ts +0 -0
  148. {coder_eval-0.9.2 → coder_eval-0.9.3}/experiments/default.yaml +0 -0
  149. {coder_eval-0.9.2 → coder_eval-0.9.3}/experiments/early-stop-ab.yaml +0 -0
  150. {coder_eval-0.9.2 → coder_eval-0.9.3}/experiments/model-comparison.yaml +0 -0
  151. {coder_eval-0.9.2 → coder_eval-0.9.3}/experiments/permissions-smoke.yaml +0 -0
  152. {coder_eval-0.9.2 → coder_eval-0.9.3}/experiments/plugin-comparison.yaml +0 -0
  153. {coder_eval-0.9.2 → coder_eval-0.9.3}/experiments/prompt-mutations-example.yaml +0 -0
  154. {coder_eval-0.9.2 → coder_eval-0.9.3}/experiments/smoke_variants.yaml +0 -0
  155. {coder_eval-0.9.2 → coder_eval-0.9.3}/litellm/README.md +0 -0
  156. {coder_eval-0.9.2 → coder_eval-0.9.3}/litellm/cost_logger.py +0 -0
  157. {coder_eval-0.9.2 → coder_eval-0.9.3}/litellm/litellm-config.yaml +0 -0
  158. {coder_eval-0.9.2 → coder_eval-0.9.3}/litellm/start-litellm.sh +0 -0
  159. {coder_eval-0.9.2 → coder_eval-0.9.3}/mkdocs.yml +0 -0
  160. {coder_eval-0.9.2 → coder_eval-0.9.3}/osv-scanner.toml +0 -0
  161. {coder_eval-0.9.2 → coder_eval-0.9.3}/scripts/check_commit_msg.sh +0 -0
  162. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/.gitattributes +0 -0
  163. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agent.py +0 -0
  164. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/__init__.py +0 -0
  165. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/_logging.py +0 -0
  166. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/antigravity_agent.py +0 -0
  167. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/claude_code_agent.py +0 -0
  168. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/codex_agent.py +0 -0
  169. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/noop_agent.py +0 -0
  170. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/registry.py +0 -0
  171. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/watchdog.py +0 -0
  172. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/analysis.py +0 -0
  173. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/__init__.py +0 -0
  174. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/aggregate_command.py +0 -0
  175. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/console.py +0 -0
  176. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/evaluate_command.py +0 -0
  177. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/plan_command.py +0 -0
  178. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/report_command.py +0 -0
  179. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/run_command.py +0 -0
  180. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/run_helpers.py +0 -0
  181. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/run_task_internal_command.py +0 -0
  182. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/utils.py +0 -0
  183. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/config.py +0 -0
  184. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/__init__.py +0 -0
  185. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/_classification_aggregate.py +0 -0
  186. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/agent_judge.py +0 -0
  187. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/classification_match.py +0 -0
  188. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/commands_efficiency.py +0 -0
  189. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/file_check.py +0 -0
  190. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/file_contains.py +0 -0
  191. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/file_exists.py +0 -0
  192. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/file_matches_regex.py +0 -0
  193. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/json_check.py +0 -0
  194. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/llm_judge.py +0 -0
  195. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/reference_comparison.py +0 -0
  196. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/run_command.py +0 -0
  197. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/uipath_eval.py +0 -0
  198. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/__init__.py +0 -0
  199. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/agent.py +0 -0
  200. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/budget.py +0 -0
  201. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/categories.py +0 -0
  202. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/categorization.py +0 -0
  203. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/checker_misuse.py +0 -0
  204. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/executor.py +0 -0
  205. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/judge.py +0 -0
  206. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/retry.py +0 -0
  207. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/timeout.py +0 -0
  208. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/__init__.py +0 -0
  209. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/checker.py +0 -0
  210. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_anthropic.py +0 -0
  211. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_bedrock.py +0 -0
  212. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_context.py +0 -0
  213. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_models.py +0 -0
  214. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_persistence.py +0 -0
  215. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_usage.py +0 -0
  216. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/sub_agent.py +0 -0
  217. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/summaries.py +0 -0
  218. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/verdict_tool.py +0 -0
  219. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/formatting.py +0 -0
  220. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/isolation/__init__.py +0 -0
  221. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/isolation/docker_runner.py +0 -0
  222. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/litellm_cost.py +0 -0
  223. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/logging_config.py +0 -0
  224. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/agent_config.py +0 -0
  225. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/container_paths.py +0 -0
  226. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/enums.py +0 -0
  227. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/experiment.py +0 -0
  228. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/judge.py +0 -0
  229. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/judge_defaults.py +0 -0
  230. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/merge_strategy.py +0 -0
  231. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/mutations.py +0 -0
  232. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/routing.py +0 -0
  233. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/sandbox.py +0 -0
  234. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/tasks.py +0 -0
  235. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/telemetry.py +0 -0
  236. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/templates.py +0 -0
  237. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/__init__.py +0 -0
  238. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/batch.py +0 -0
  239. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/config.py +0 -0
  240. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/config_merge.py +0 -0
  241. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/evaluation.py +0 -0
  242. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/experiment.py +0 -0
  243. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/overrides.py +0 -0
  244. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/task_loader.py +0 -0
  245. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/path_utils.py +0 -0
  246. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/plugins.py +0 -0
  247. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/pricing.py +0 -0
  248. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/py.typed +0 -0
  249. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/reports_junit.py +0 -0
  250. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/reports_stats.py +0 -0
  251. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/resources/__init__.py +0 -0
  252. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/resources/default_ignore_patterns.yaml +0 -0
  253. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/resources/tags.yaml +0 -0
  254. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/sandbox.py +0 -0
  255. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/scoring/__init__.py +0 -0
  256. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/scoring/ast_similarity.py +0 -0
  257. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/scoring/complexity.py +0 -0
  258. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/scoring/quality.py +0 -0
  259. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/scoring/signature_similarity.py +0 -0
  260. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/scoring/similarity.py +0 -0
  261. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/scoring/token_similarity.py +0 -0
  262. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/simulation/__init__.py +0 -0
  263. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/simulation/termination.py +0 -0
  264. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/simulation/user_simulator.py +0 -0
  265. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/streaming/__init__.py +0 -0
  266. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/streaming/callbacks.py +0 -0
  267. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/streaming/collector.py +0 -0
  268. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/streaming/events.py +0 -0
  269. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/streaming/renderers.py +0 -0
  270. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/streaming/wire.py +0 -0
  271. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/telemetry.py +0 -0
  272. {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/utils.py +0 -0
  273. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/README.md +0 -0
  274. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agentless_smoke_test.yaml +0 -0
  275. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/antigravity_hello_world.yaml +0 -0
  276. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/antigravity_hello_world_docker.yaml +0 -0
  277. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/claude_hello_world.yaml +0 -0
  278. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/claude_hello_world_docker.yaml +0 -0
  279. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/claude_parallel_single_gen.yaml +0 -0
  280. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/claude_subagent_test.yaml +0 -0
  281. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/codex_disallowed_tools_test.yaml +0 -0
  282. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/codex_hello_world.yaml +0 -0
  283. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/codex_parallel_commands.yaml +0 -0
  284. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/codex_parallel_single_gen.yaml +0 -0
  285. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/codex_skills_test.yaml +0 -0
  286. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/codex_string_utils.yaml +0 -0
  287. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/codex_subagent_test.yaml +0 -0
  288. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/subagent_bash_long_input.yaml +0 -0
  289. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/subagent_merge_sort.yaml +0 -0
  290. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/byod_smoke_test.yaml +0 -0
  291. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/dataset_example.yaml +0 -0
  292. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/datasets/sentiment.jsonl +0 -0
  293. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/dockerfile_build_example/dockerfile_build_example.yaml +0 -0
  294. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/dockerfile_build_example/environment/Dockerfile +0 -0
  295. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/dockerfile_build_example/environment/Dockerfile.workdir +0 -0
  296. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/dockerfile_build_example/environment/input.txt +0 -0
  297. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/dockerfile_build_example/working_dir_auto_example.yaml +0 -0
  298. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/dockerfile_build_example/working_dir_concrete_example.yaml +0 -0
  299. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/fibonacci_with_template.yaml +0 -0
  300. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/hello_date.yaml +0 -0
  301. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/inline_starter_example.yaml +0 -0
  302. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/internal/session_resumption.yaml +0 -0
  303. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/mock_path_dirs_smoke.yaml +0 -0
  304. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/mock_path_dirs_template_dir/mock-cli-bins/README.md +0 -0
  305. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/mock_path_dirs_template_dir/mock-cli-bins/mocks/echo_args +0 -0
  306. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/mock_path_dirs_template_dir/mock-cli-bins/mocks/fixtures/config.json +0 -0
  307. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/mock_path_dirs_template_dir/mock-cli-bins/mocks/say_hello +0 -0
  308. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/mock_path_dirs_template_dir/task.yaml +0 -0
  309. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/python_cli_simulated_judged/echo_simulated_judged.yaml +0 -0
  310. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/3d-scan-calc.yaml +0 -0
  311. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/environment/Dockerfile +0 -0
  312. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/environment/material_density_table.md +0 -0
  313. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/environment/scan_data.stl +0 -0
  314. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/verifier/test.sh +0 -0
  315. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/verifier/test_outputs.py +0 -0
  316. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/README.md +0 -0
  317. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/court-form-filling/court-form-filling.yaml +0 -0
  318. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/court-form-filling/environment/Dockerfile +0 -0
  319. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/court-form-filling/environment/sc100-blank.pdf +0 -0
  320. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/court-form-filling/verifier/test.sh +0 -0
  321. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/court-form-filling/verifier/test_outputs.py +0 -0
  322. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/dialogue-parser/dialogue-parser.yaml +0 -0
  323. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/dialogue-parser/environment/Dockerfile +0 -0
  324. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/dialogue-parser/environment/script.txt +0 -0
  325. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/dialogue-parser/verifier/test.sh +0 -0
  326. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/dialogue-parser/verifier/test_outputs.py +0 -0
  327. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/sentiment_classification.yaml +0 -0
  328. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/smoke_agent_judge.yaml +0 -0
  329. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/smoke_budget_exceeded.yaml +0 -0
  330. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/smoke_cost_budget_exceeded.yaml +0 -0
  331. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/smoke_llm_judge.yaml +0 -0
  332. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/smoke_negative_path.yaml +0 -0
  333. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/smoke_task_timeout.yaml +0 -0
  334. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/smoke_variants.yaml +0 -0
  335. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/test_sandbox.yaml +0 -0
  336. {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/token_check.yaml +0 -0
  337. {coder_eval-0.9.2 → coder_eval-0.9.3}/templates/byod_smoke_test/Dockerfile +0 -0
  338. {coder_eval-0.9.2 → coder_eval-0.9.3}/templates/fibonacci-starter/README.md +0 -0
  339. {coder_eval-0.9.2 → coder_eval-0.9.3}/templates/fibonacci-starter/src/main.py +0 -0
  340. {coder_eval-0.9.2 → coder_eval-0.9.3}/templates/fibonacci-starter/tests/test_main.py +0 -0
  341. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/__init__.py +0 -0
  342. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/__init__.py +0 -0
  343. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/__init__.py +0 -0
  344. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/_scrub.py +0 -0
  345. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/claude_fixtures.py +0 -0
  346. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/codex_fixtures.py +0 -0
  347. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_a_single_text_turn.json +0 -0
  348. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_b_tool_use_result.json +0 -0
  349. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_c_multi_emission_delta.json +0 -0
  350. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_d_subagent_terminal.json +0 -0
  351. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_e_model_usage_and_backfill.json +0 -0
  352. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_f_orphaned_tool.json +0 -0
  353. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_g_crash_format_placeholder.json +0 -0
  354. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_h1_timeout_process_error.json +0 -0
  355. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_h2_process_error_crash.json +0 -0
  356. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_i_in_loop_deadline_break.json +0 -0
  357. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_a_agent_message_only.json +0 -0
  358. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_b_command_execution.json +0 -0
  359. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_c_reasoning_placeholder.json +0 -0
  360. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_d_cross_flush_is_error.json +0 -0
  361. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_e_orphan_tool.json +0 -0
  362. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_f_collab_fallback.json +0 -0
  363. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_g_items_rebuild.json +0 -0
  364. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_h_no_turn_completed_crash.json +0 -0
  365. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/__init__.py +0 -0
  366. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/_snapshot.py +0 -0
  367. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/experiment_2variant.md +0 -0
  368. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/experiment_3variant.md +0 -0
  369. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/experiment_replicates.md +0 -0
  370. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/run_full.md +0 -0
  371. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/run_minimal.md +0 -0
  372. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_path_helpers.py +0 -0
  373. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/conftest.py +0 -0
  374. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/__init__.py +0 -0
  375. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/byoa_demo_plugin/byoa_demo.py +0 -0
  376. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/byoa_demo_plugin/pyproject.toml +0 -0
  377. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/mock_agent.py +0 -0
  378. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/tasks/test_task_informational_criterion.yaml +0 -0
  379. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/tasks/test_task_multiple_criteria.yaml +0 -0
  380. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/tasks/test_task_pass.yaml +0 -0
  381. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/text_stub_agent.py +0 -0
  382. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/__init__.py +0 -0
  383. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/dead_config_fields.py +0 -0
  384. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/doc_env_parity.py +0 -0
  385. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/doc_examples.py +0 -0
  386. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/doc_indexes.py +0 -0
  387. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/doc_schema_parity.py +0 -0
  388. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/__init__.py +0 -0
  389. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/base.py +0 -0
  390. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce014_merge_strategy_declared.py +0 -0
  391. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce015_create_subprocess_limit.py +0 -0
  392. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce016_no_computed_tokenusage_kwargs.py +0 -0
  393. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce017_models_lazy_agent_imports.py +0 -0
  394. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce018_no_final_status_name_denylist.py +0 -0
  395. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce019_telemetry_non_fatal.py +0 -0
  396. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce020_no_sdk_typed_base_agent_fields.py +0 -0
  397. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce021_guarded_evaluationresult_parse.py +0 -0
  398. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce022_dialog_loop_statement_cap.py +0 -0
  399. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce023_no_proxy_shim_import.py +0 -0
  400. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce024_discriminated_unions.py +0 -0
  401. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_agent_timing_access.py +0 -0
  402. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_blocking_io_in_async.py +0 -0
  403. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_cli_imports_in_core.py +0 -0
  404. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_silent_except.py +0 -0
  405. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_submodule_model_imports.py +0 -0
  406. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_top_level_run_limits_access.py +0 -0
  407. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_transcript_regex_in_eval.py +0 -0
  408. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_type_name_string_dispatch.py +0 -0
  409. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/open_explicit_encoding.py +0 -0
  410. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/read_text_explicit_encoding.py +0 -0
  411. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/register_criterion_required.py +0 -0
  412. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/subprocess_run_explicit_encoding.py +0 -0
  413. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/yaml_models_forbid_extras.py +0 -0
  414. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/violation.py +0 -0
  415. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_action_version_pin.py +0 -0
  416. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent.py +0 -0
  417. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_config_no_timing_fields.py +0 -0
  418. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_config_optional_type.py +0 -0
  419. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_config_registry_dispatch.py +0 -0
  420. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_config_sdk_decoupling.py +0 -0
  421. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_golden_master.py +0 -0
  422. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_judge_criterion.py +0 -0
  423. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_telemetry.py +0 -0
  424. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_telemetry_advanced.py +0 -0
  425. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_timeout.py +0 -0
  426. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agentless.py +0 -0
  427. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_aggregate.py +0 -0
  428. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_antigravity_agent.py +0 -0
  429. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_byoa_plugin.py +0 -0
  430. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_byoa_plugin_live.py +0 -0
  431. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_byod_feature.py +0 -0
  432. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_check_all_async.py +0 -0
  433. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_checker_logging.py +0 -0
  434. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_classification_match.py +0 -0
  435. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_claude_settings_enforcement_live.py +0 -0
  436. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cleanup_preservation_guard.py +0 -0
  437. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cli_backend_flag.py +0 -0
  438. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cli_empty_glob.py +0 -0
  439. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cli_sdk_options.py +0 -0
  440. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cli_set_overrides.py +0 -0
  441. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cli_telemetry.py +0 -0
  442. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cli_type_flag.py +0 -0
  443. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_code_review_bugs.py +0 -0
  444. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_codex_agent.py +0 -0
  445. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_codex_agent_live.py +0 -0
  446. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_codex_agent_unit.py +0 -0
  447. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_codex_token_mapping.py +0 -0
  448. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_command_executed.py +0 -0
  449. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_command_statistics.py +0 -0
  450. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_command_telemetry_result_data.py +0 -0
  451. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_commands_efficiency.py +0 -0
  452. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_config_lineage.py +0 -0
  453. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_config_merge_engine.py +0 -0
  454. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_config_precedence.py +0 -0
  455. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_continuous_scoring.py +0 -0
  456. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cost_accounting_paths.py +0 -0
  457. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_criterion_result_round_trip.py +0 -0
  458. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_dataset_expansion.py +0 -0
  459. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_debug_logging.py +0 -0
  460. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_docker_build_failure.py +0 -0
  461. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_docker_litellm_env.py +0 -0
  462. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_docker_runner_container_death.py +0 -0
  463. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_docker_runner_mounts.py +0 -0
  464. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_docker_runner_stream_limit.py +0 -0
  465. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_docker_wildcard_env.py +0 -0
  466. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_docker_workdir_live.py +0 -0
  467. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_driver_resolver.py +0 -0
  468. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_error_handling.py +0 -0
  469. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_evaluate_command.py +0 -0
  470. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_evaluator.py +0 -0
  471. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_event_collector.py +0 -0
  472. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_experiment_cli.py +0 -0
  473. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_experiment_loader.py +0 -0
  474. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_experiment_models.py +0 -0
  475. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_experiment_reports.py +0 -0
  476. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_experiment_resolver.py +0 -0
  477. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_experiment_runner.py +0 -0
  478. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_file_check.py +0 -0
  479. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_file_contains_scoring.py +0 -0
  480. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_formatting.py +0 -0
  481. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_git_clone_failure.py +0 -0
  482. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_heartbeat_watchdog.py +0 -0
  483. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_ignore_patterns_negation.py +0 -0
  484. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_image_from_dockerfiles.py +0 -0
  485. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_integration.py +0 -0
  486. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_json_check.py +0 -0
  487. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_judge_anthropic.py +0 -0
  488. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_judge_bedrock.py +0 -0
  489. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_judge_burn_in_live.py +0 -0
  490. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_judge_context_builder.py +0 -0
  491. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_judge_models.py +0 -0
  492. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_judge_persistence.py +0 -0
  493. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_lint_no_top_level_run_limits.py +0 -0
  494. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_lint_runner.py +0 -0
  495. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_litellm_config.py +0 -0
  496. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_litellm_cost.py +0 -0
  497. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_litellm_cost_logger.py +0 -0
  498. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_litellm_route.py +0 -0
  499. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_llm_judge_criterion.py +0 -0
  500. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_log_tail_buffer.py +0 -0
  501. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_logging.py +0 -0
  502. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_logging_isolation.py +0 -0
  503. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_merge_characterization.py +0 -0
  504. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_merge_strategy_annotations.py +0 -0
  505. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_merge_unification.py +0 -0
  506. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_models.py +0 -0
  507. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_mutations.py +0 -0
  508. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_new_criteria.py +0 -0
  509. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_node_env_config.py +0 -0
  510. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_optional_dependencies.py +0 -0
  511. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_orchestrator.py +0 -0
  512. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_orchestrator_error_log_tail.py +0 -0
  513. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_orchestrator_telemetry.py +0 -0
  514. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_overrides_engine.py +0 -0
  515. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_parallel.py +0 -0
  516. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_path_utils.py +0 -0
  517. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_plan_command.py +0 -0
  518. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_plugin_processing.py +0 -0
  519. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_plugins.py +0 -0
  520. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_post_run.py +0 -0
  521. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_pr_review_workflow.py +0 -0
  522. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_pre_run.py +0 -0
  523. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_preservation_mode.py +0 -0
  524. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_pricing_registry.py +0 -0
  525. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reference_comparison_scoring.py +0 -0
  526. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reference_evaluator.py +0 -0
  527. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reference_missing_file.py +0 -0
  528. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reference_models.py +0 -0
  529. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reference_orchestrator.py +0 -0
  530. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_registry.py +0 -0
  531. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_release_notes.py +0 -0
  532. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_replicate_stats.py +0 -0
  533. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_report_command.py +0 -0
  534. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reports.py +0 -0
  535. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reports_experiment.py +0 -0
  536. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reports_html.py +0 -0
  537. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reports_junit.py +0 -0
  538. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reports_stats.py +0 -0
  539. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reports_stats_nonfinite.py +0 -0
  540. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_resolve_task_files.py +0 -0
  541. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_resume.py +0 -0
  542. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_retry_logic_comprehensive.py +0 -0
  543. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_route_seam_exhaustiveness.py +0 -0
  544. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_routing.py +0 -0
  545. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_run_command_junit.py +0 -0
  546. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_run_command_stdout.py +0 -0
  547. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_run_limits_models.py +0 -0
  548. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_run_limits_orchestrator.py +0 -0
  549. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_run_limits_resolver.py +0 -0
  550. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_run_metrics.py +0 -0
  551. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_runtime_tool_versions.py +0 -0
  552. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sandbox.py +0 -0
  553. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sandbox_layer_builder.py +0 -0
  554. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sandbox_optional.py +0 -0
  555. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sandbox_security.py +0 -0
  556. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sandbox_symlink_preservation.py +0 -0
  557. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sandbox_templates.py +0 -0
  558. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_scorers.py +0 -0
  559. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_scoring_quality.py +0 -0
  560. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sdk_option_classification.py +0 -0
  561. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_simulation_config.py +0 -0
  562. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_simulation_integration.py +0 -0
  563. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_simulation_termination.py +0 -0
  564. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_simulation_trials.py +0 -0
  565. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_skill_triggered.py +0 -0
  566. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_agent_integration.py +0 -0
  567. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_batch.py +0 -0
  568. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_callbacks.py +0 -0
  569. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_cli.py +0 -0
  570. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_events.py +0 -0
  571. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_orchestrator.py +0 -0
  572. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_renderers.py +0 -0
  573. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_wire.py +0 -0
  574. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sub_agent_runner.py +0 -0
  575. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_success_criterion_union.py +0 -0
  576. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_suite_rollup.py +0 -0
  577. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_summaries.py +0 -0
  578. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_tags.py +0 -0
  579. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_task_definition_unknown_fields.py +0 -0
  580. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_teardown_interrupt.py +0 -0
  581. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_telemetry.py +0 -0
  582. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_template_env_expansion.py +0 -0
  583. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_threshold_enforcement.py +0 -0
  584. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_timeout_batch.py +0 -0
  585. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_timeout_categorization.py +0 -0
  586. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_timeout_exceptions.py +0 -0
  587. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_timeout_models.py +0 -0
  588. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_timeout_orchestrator.py +0 -0
  589. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_token_usage.py +0 -0
  590. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_uipath_eval.py +0 -0
  591. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_user_simulator.py +0 -0
  592. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_utils.py +0 -0
  593. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_utterance_extraction.py +0 -0
  594. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_variant_prompt_file.py +0 -0
  595. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_verdict_tool.py +0 -0
  596. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_watchdog.py +0 -0
  597. {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_yaml_migration.py +0 -0
@@ -2,6 +2,27 @@
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
+
5
26
  ## v0.9.2 (2026-07-31)
6
27
 
7
28
  ### Bug Fixes
@@ -141,8 +141,8 @@ action.yml # Published composite GitHub Action (coder-ev
141
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.
142
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.
143
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.
144
- - **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.
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 (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.
146
146
 
147
147
  ## Success Criteria (14 types)
148
148
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: coder-eval
3
- Version: 0.9.2
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.2" # <-- 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.
@@ -188,10 +188,13 @@ backend), `num_turns`, `max_turns_exhausted`,
188
188
  ### EarlyStopInfo
189
189
 
190
190
  Present (non-`null`) iff the run stopped early — there is no separate boolean.
191
- 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),
192
194
  `deciding_criterion_type`, `deciding_criterion_description`, `armed_criteria`,
193
195
  `sdk_turn_index`, `tool_call_index` (1-based, includes the in-flight call),
194
- `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`).
195
198
 
196
199
  ---
197
200
 
@@ -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`
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "coder-eval"
3
- version = "0.9.2"
3
+ version = "0.9.3"
4
4
  description = "Evaluate, benchmark, and A/B-test AI coding agents (Claude Code, Codex, Gemini/Antigravity) with sandboxed, reproducible YAML task suites."
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -1,3 +1,3 @@
1
1
  """coder_eval - A framework for evaluating AI coding agents."""
2
2
 
3
- __version__ = "0.9.2"
3
+ __version__ = "0.9.3"
@@ -26,6 +26,19 @@ logger = logging.getLogger(__name__)
26
26
 
27
27
  # A criterion's verdict from a PARTIAL, mid-run trajectory (early-stop observability).
28
28
  # "undecided" means the outcome is not yet knowable from the events seen so far.
29
+ #
30
+ # CONTRACT every live_verdict override must satisfy (see BaseCriterion.live_verdict):
31
+ # - Deterministic: a pure function of the ``turn_records`` prefix passed in — no
32
+ # wall-clock, randomness, or other hidden state.
33
+ # - Monotonic: once it returns "pass"/"fail" for some trajectory prefix, it MUST
34
+ # return that SAME verdict for every longer prefix (i.e. every later call in the
35
+ # same run). "undecided" is the only verdict allowed to change on a later call.
36
+ # EarlyStopWatcher's deferred fail-stop and pass/fail flip-attribution
37
+ # (early_stop.py::_prev_verdicts) are correct only because both existing
38
+ # implementations (skill_triggered, command_executed) honor this. A non-monotonic or
39
+ # non-deterministic override compiles and passes CE025 (which only checks
40
+ # LiveSuccessCriterion subclassing / live_verdict pairing, not this) but silently corrupts the stop
41
+ # logic — there is currently no automated enforcement beyond this docstring.
29
42
  LiveVerdict = Literal["pass", "fail", "undecided"]
30
43
 
31
44
 
@@ -200,13 +213,6 @@ class BaseCriterion[C: BaseSuccessCriterion](ABC):
200
213
  # Subclasses MUST define this as a class variable
201
214
  criterion_type: ClassVar[str]
202
215
 
203
- # Which polarities this criterion can decide from a PARTIAL, mid-run trajectory.
204
- # Empty (base default) = not observable mid-run, so it can never arm early-stop.
205
- # A subclass that reads only turn_records and can decide mid-run declares the
206
- # polarities it supports (e.g. frozenset({"pass", "fail"})) AND overrides
207
- # live_verdict; CE025 enforces that the two stay consistent.
208
- live_stop_polarities: ClassVar[frozenset[str]] = frozenset()
209
-
210
216
  def __new__(cls, *args: Any, **kwargs: Any) -> "BaseCriterion[C]":
211
217
  """Block direct instantiation of ``BaseCriterion`` itself.
212
218
 
@@ -426,36 +432,17 @@ class BaseCriterion[C: BaseSuccessCriterion](ABC):
426
432
  from ``check()``/``_check_impl`` run on the frozen trajectory after the
427
433
  stop, so a live/final divergence can never corrupt scoring.
428
434
 
429
- Base default: ``"undecided"`` (not observable mid-run). Subclasses that
430
- override this MUST also declare a non-empty ``live_stop_polarities`` (and
431
- vice versa) — enforced by lint rule CE025.
435
+ Base default: ``"undecided"`` (not observable mid-run). A checker
436
+ overrides this iff its criterion model is a ``LiveSuccessCriterion``
437
+ subclass (``models/criteria.py``) — that subclassing is the single
438
+ source of truth for "is this criterion type live-observable", checked
439
+ by ``validate_early_stop`` / ``EarlyStopWatcher`` and enforced by lint
440
+ rule CE025. An override MUST also satisfy the deterministic + monotonic
441
+ contract documented on the ``LiveVerdict`` type above (not enforced by
442
+ CE025 or any other automated check).
432
443
  """
433
444
  return "undecided"
434
445
 
435
- @classmethod
436
- def live_decidable_polarities(cls, criterion: C) -> frozenset[str]:
437
- """Which polarities THIS criterion *instance* can actually decide mid-run.
438
-
439
- ``live_stop_polarities`` is a class-level *capability* — the widest set
440
- of polarities the checker's ``live_verdict`` could ever emit. But for
441
- some criteria whether a given polarity can fire depends on the instance's
442
- configuration, not just its type. ``command_executed`` is the canonical
443
- case: it can live-``pass`` only with no upper bound, and live-``fail``
444
- only with one, so a specific criterion may support strictly fewer
445
- polarities than its class advertises (down to none — a "dead arm").
446
-
447
- ``validate_early_stop`` gates the requested ``stop_when`` polarity on THIS
448
- set, not the ClassVar, so an instance that can never decide its armed
449
- polarity is rejected at resolution rather than silently degrading to a
450
- full run (the "never a silent no-op" guarantee).
451
-
452
- Default: the class-level ``live_stop_polarities`` — correct for every
453
- criterion whose decidability is purely type-level (e.g. ``skill_triggered``).
454
- Overrides MUST return a subset of ``live_stop_polarities`` (a criterion
455
- cannot decide a polarity its ``live_verdict`` never emits).
456
- """
457
- return cls.live_stop_polarities
458
-
459
446
  def aggregate(
460
447
  self,
461
448
  criterion: C,
@@ -3,7 +3,7 @@
3
3
  import json
4
4
  import logging
5
5
  import re
6
- from typing import TYPE_CHECKING, ClassVar
6
+ from typing import TYPE_CHECKING
7
7
 
8
8
  from coder_eval.criteria.base import BaseCriterion, CheckContext, LiveVerdict, register_criterion
9
9
  from coder_eval.models import CommandExecutedCriterion, CriterionResult
@@ -30,42 +30,6 @@ class CommandExecutedChecker(BaseCriterion[CommandExecutedCriterion]):
30
30
 
31
31
  criterion_type = "command_executed"
32
32
 
33
- # Observable mid-run: command matches accumulate monotonically in the live
34
- # stream, so a min_count pass (no upper bound) and a max_count exceedance
35
- # (incl. the must-NOT-run 0/0 form) are both decidable before end-of-run.
36
- live_stop_polarities: ClassVar[frozenset[str]] = frozenset({"pass", "fail"})
37
-
38
- @classmethod
39
- def live_decidable_polarities(cls, criterion: CommandExecutedCriterion) -> frozenset[str]:
40
- """Narrow the class capability to what THIS instance can decide mid-run.
41
-
42
- The class advertises ``{"pass", "fail"}``, but ``live_verdict`` can only:
43
-
44
- - ``pass`` when there is no upper bound and a positive floor
45
- (``max_count is None and min_count > 0``) — with an upper bound a pass
46
- is not final until end-of-run, so it never fires live; and
47
- - ``fail`` when there IS an upper bound (``max_count is not None``), the
48
- moment the count exceeds it (this includes the ``min_count: 0,
49
- max_count: 0`` "must NOT run" form).
50
-
51
- So these instance shapes are dead arms the class-level check misses:
52
-
53
- - ``stop_when: pass`` with ``max_count`` set → pass can never fire;
54
- - ``stop_when: fail`` with ``max_count: None`` → fail can never fire;
55
- - ``min_count: 0, max_count: None`` → neither can ever fire.
56
-
57
- Reporting the true per-instance set here lets ``validate_early_stop``
58
- reject such arming at resolution instead of silently degrading to a full
59
- run. Stays a subset of ``live_stop_polarities`` by construction.
60
- """
61
- decidable: set[str] = set()
62
- if criterion.max_count is None:
63
- if criterion.min_count > 0:
64
- decidable.add("pass")
65
- else:
66
- decidable.add("fail")
67
- return frozenset(decidable)
68
-
69
33
  @staticmethod
70
34
  def _matching_commands(
71
35
  criterion: CommandExecutedCriterion,
@@ -10,7 +10,7 @@ from __future__ import annotations
10
10
 
11
11
  import logging
12
12
  import re
13
- from typing import TYPE_CHECKING, ClassVar
13
+ from typing import TYPE_CHECKING
14
14
 
15
15
  from coder_eval.criteria._classification_aggregate import overlay_classification_metrics
16
16
  from coder_eval.criteria.base import BaseCriterion, LiveVerdict, register_criterion
@@ -109,14 +109,6 @@ class SkillTriggeredChecker(BaseCriterion[SkillTriggeredCriterion]):
109
109
 
110
110
  criterion_type = "skill_triggered"
111
111
 
112
- # Observable mid-run: a Skill tool call (or a skill file read) is a positive
113
- # event in the live stream. The TYPE can decide either polarity — a positive
114
- # criterion live-passes when its expected skill is engaged, a
115
- # distractor/negative one live-fails when its (wrong) skill is engaged — but
116
- # any single INSTANCE decides only one of the two; see
117
- # ``live_decidable_polarities``.
118
- live_stop_polarities: ClassVar[frozenset[str]] = frozenset({"pass", "fail"})
119
-
120
112
  def _check_impl(
121
113
  self,
122
114
  criterion: SkillTriggeredCriterion,
@@ -179,37 +171,15 @@ class SkillTriggeredChecker(BaseCriterion[SkillTriggeredCriterion]):
179
171
  frozen trajectory by construction — whether or not the run stopped early.
180
172
  A positive criterion can therefore only ever live-``pass`` and a
181
173
  distractor/negative one only ever live-``fail``; their *absence* is never
182
- decidable mid-run (see ``live_decidable_polarities``). This is the change
183
- from first-engagement: a wrong skill engaged first no longer live-fails a
184
- positive row the run keeps going so the expected skill can still load.
174
+ decidable mid-run (see ``SkillTriggeredCriterion.live_decidable_polarities``
175
+ in models/criteria.py). This is the change from first-engagement: a wrong
176
+ skill engaged first no longer live-fails a positive row the run keeps
177
+ going so the expected skill can still load.
185
178
  """
186
179
  if criterion.skill_name not in _all_engaged_skill_names(turn_records):
187
180
  return "undecided"
188
181
  return "pass" if criterion.expected_skill == criterion.skill_name else "fail"
189
182
 
190
- @classmethod
191
- def live_decidable_polarities(cls, criterion: SkillTriggeredCriterion) -> frozenset[str]:
192
- """Per-instance narrowing under the any-engagement latch.
193
-
194
- Unlike the type-level capability (``live_stop_polarities`` = both), a
195
- single instance decides exactly one polarity:
196
-
197
- - a **positive** criterion (``skill_name == expected_skill``) can only
198
- live-``pass`` (the expected skill engaging is a decidable hit; its
199
- absence is not knowable mid-run);
200
- - a **distractor/negative** criterion (``skill_name != expected_skill``,
201
- including the ``expected_skill == ""`` negatives) can only
202
- live-``fail`` (a wrong skill engaging is a decidable miss; its absence
203
- is not).
204
-
205
- ``validate_early_stop`` gates the requested ``stop_when`` on this set, so
206
- arming a positive with ``fail`` / a distractor with ``pass`` — or either
207
- with ``decided`` (which needs both) — is rejected at resolution rather
208
- than silently degrading to a full run.
209
- """
210
- expected_yes = criterion.expected_skill == criterion.skill_name
211
- return frozenset({"pass"}) if expected_yes else frozenset({"fail"})
212
-
213
183
  def aggregate(
214
184
  self,
215
185
  criterion: SkillTriggeredCriterion,
@@ -40,6 +40,8 @@ from coder_eval.models.criteria import (
40
40
  FileMatchesRegexCriterion,
41
41
  JMESPathAssertion,
42
42
  JsonCheckCriterion,
43
+ LivePolarity,
44
+ LiveSuccessCriterion,
43
45
  LLMJudgeCriterion,
44
46
  ReferenceComparisonCriterion,
45
47
  RegexPattern,
@@ -232,6 +234,8 @@ __all__ = [ # noqa: RUF022 - Keep grouped by category for readability
232
234
  "LLMJudgeCriterion",
233
235
  "AgentJudgeCriterion",
234
236
  "SkillTriggeredCriterion",
237
+ "LiveSuccessCriterion",
238
+ "LivePolarity",
235
239
  "SuccessCriterion",
236
240
  # Routing
237
241
  "ROUTE_NAMES",
@@ -8,7 +8,7 @@
8
8
 
9
9
  from __future__ import annotations
10
10
 
11
- from abc import ABC
11
+ from abc import ABC, abstractmethod
12
12
  from typing import Annotated, Any, ClassVar, Literal, Self
13
13
 
14
14
  from pydantic import BaseModel, ConfigDict, Field, model_validator
@@ -187,6 +187,86 @@ class BaseSuccessCriterion(BaseModel, ABC):
187
187
  # Business logic (check operations) moved to SuccessChecker in evaluator.py
188
188
 
189
189
 
190
+ # The two polarities a live-observable criterion can decide mid-run — distinct
191
+ # from the 3-value LiveVerdict ("pass"/"fail"/"undecided") the checker's
192
+ # live_verdict returns: this is the narrower CAPABILITY type, "undecided" is
193
+ # never a valid decidable polarity. Typed here (not a bare frozenset[str]) so
194
+ # a live_decidable_polarities override returning a stray/typo'd string, or
195
+ # "undecided" itself, is a pyright error rather than a runtime-only lint gap.
196
+ LivePolarity = Literal["pass", "fail"]
197
+
198
+
199
+ class LiveSuccessCriterion(BaseSuccessCriterion):
200
+ """Base for criteria observable from a PARTIAL, mid-run trajectory (early-stop).
201
+
202
+ ``live_decidable_polarities`` is a pure function of THIS instance's own
203
+ fields — no ``turn_records``, no sandbox, no checker instance needed (e.g.
204
+ ``command_executed`` can decide this purely from whether ``max_count`` is
205
+ set). That makes it genuinely computable on the data model rather than the
206
+ checker, unlike the checker's ``live_verdict`` (``criteria/base.py``),
207
+ which reads the actual trajectory and stays checker-side logic. Moving
208
+ decidability here also gives early-stop-only config (e.g.
209
+ ``max_steps_to_decide``) a home that doesn't pollute ``BaseSuccessCriterion``
210
+ with a field meaningless for every non-observable criterion type.
211
+
212
+ Only ``SkillTriggeredCriterion`` / ``CommandExecutedCriterion`` subclass
213
+ this today; a criterion type is "live-observable" iff it is a
214
+ ``LiveSuccessCriterion`` subclass — the single source of truth
215
+ ``validate_early_stop`` / ``EarlyStopWatcher`` consult (no separate
216
+ checker-side flag to keep in sync).
217
+ """
218
+
219
+ max_steps_to_decide: int | None = Field(
220
+ default=None,
221
+ ge=1,
222
+ description=(
223
+ "Cap on tool-call steps this ARMED criterion (stop_when must be set) "
224
+ "may spend still 'undecided' before the run gives up on it. Once "
225
+ "exceeded, EarlyStopWatcher fires an early stop with reason "
226
+ "'decision_budget_exceeded' and the run is forced to FinalStatus."
227
+ "FAILURE outright — regardless of what any other armed criterion's "
228
+ "weighted score would otherwise gate to (this criterion never "
229
+ "reached a verdict at all, so there is nothing to weigh). None "
230
+ "(default) = no cap; the run relies solely on run_limits.max_turns. "
231
+ "Requires run_limits.stop_early and this criterion's own stop_when. "
232
+ "The step count is CUMULATIVE across every retry attempt of the "
233
+ "turn (the same EarlyStopWatcher instance, and its counters, "
234
+ "persist across retries) — including attempts that ultimately "
235
+ "crashed or timed out before this criterion's own investigation "
236
+ "even began. Size the budget with that headroom in mind."
237
+ ),
238
+ )
239
+
240
+ @model_validator(mode="after")
241
+ def _check_max_steps_requires_armed(self) -> Self:
242
+ """Reject a decision-step cap on a criterion that isn't armed for early-stop.
243
+
244
+ ``max_steps_to_decide`` only means anything relative to a criterion
245
+ that ``EarlyStopWatcher`` is actually tracking (``stop_when`` set);
246
+ setting it without ``stop_when`` is a dead field that silently does
247
+ nothing, so reject it at load time rather than let it rot unnoticed.
248
+ """
249
+ if self.max_steps_to_decide is not None and self.stop_when is None:
250
+ raise ValueError(
251
+ f"criterion {self.type!r}: max_steps_to_decide requires stop_when to be set "
252
+ + "(the decision-step budget is meaningless for a criterion that isn't armed "
253
+ + "for early-stop)."
254
+ )
255
+ return self
256
+
257
+ @abstractmethod
258
+ def live_decidable_polarities(self) -> frozenset[LivePolarity]:
259
+ """Which polarities THIS instance can decide mid-run, from its own fields alone.
260
+
261
+ Must return a subset of the polarities the corresponding checker's
262
+ ``live_verdict`` can ever emit for this criterion type. Used by
263
+ ``validate_early_stop`` to reject arming a polarity this instance can
264
+ never reach, and by ``EarlyStopWatcher`` to resolve which polarities a
265
+ ``stop_when`` value actually arms for this instance (see
266
+ ``orchestration.early_stop._requested_polarities``).
267
+ """
268
+
269
+
190
270
  class FileExistsCriterion(BaseSuccessCriterion):
191
271
  """Check if a file exists at the specified path.
192
272
 
@@ -472,7 +552,7 @@ class CommandsEfficiencyCriterion(BaseSuccessCriterion):
472
552
  expected_commands: int = Field(ge=1, description="Expected number of tool commands to complete the task")
473
553
 
474
554
 
475
- class CommandExecutedCriterion(BaseSuccessCriterion):
555
+ class CommandExecutedCriterion(LiveSuccessCriterion):
476
556
  """Check whether the agent executed specific commands/tools.
477
557
 
478
558
  Inspects CommandTelemetry records from TurnRecord.commands to verify
@@ -548,6 +628,32 @@ class CommandExecutedCriterion(BaseSuccessCriterion):
548
628
  raise ValueError(f"max_count ({self.max_count}) must be >= min_count ({self.min_count})")
549
629
  return self
550
630
 
631
+ def live_decidable_polarities(self) -> frozenset[LivePolarity]:
632
+ """Narrow to what THIS instance can decide mid-run.
633
+
634
+ The checker's ``live_verdict`` (``criteria/command_executed.py``) can
635
+ only:
636
+
637
+ - ``pass`` when there is no upper bound and a positive floor
638
+ (``max_count is None and min_count > 0``) — with an upper bound a
639
+ pass is not final until end-of-run, so it never fires live; and
640
+ - ``fail`` when there IS an upper bound (``max_count is not None``),
641
+ the moment the count exceeds it (this includes the
642
+ ``min_count: 0, max_count: 0`` "must-NOT-run" form).
643
+
644
+ So these instance shapes are dead arms the class-level check misses:
645
+ ``stop_when: pass`` with ``max_count`` set (pass can never fire);
646
+ ``stop_when: fail`` with ``max_count: None`` (fail can never fire);
647
+ ``min_count: 0, max_count: None`` (neither can ever fire).
648
+ """
649
+ decidable: set[LivePolarity] = set()
650
+ if self.max_count is None:
651
+ if self.min_count > 0:
652
+ decidable.add("pass")
653
+ else:
654
+ decidable.add("fail")
655
+ return frozenset(decidable)
656
+
551
657
 
552
658
  class UiPathEvalCriterion(BaseSuccessCriterion):
553
659
  """Check evaluation results against UiPath agent performance.
@@ -608,7 +714,7 @@ class ClassificationMatchCriterion(BaseSuccessCriterion):
608
714
  )
609
715
 
610
716
 
611
- class SkillTriggeredCriterion(BaseSuccessCriterion):
717
+ class SkillTriggeredCriterion(LiveSuccessCriterion):
612
718
  """Binary classifier: did the agent engage the target skill during the run?
613
719
 
614
720
  Agent-agnostic. Observed label is ``"yes"`` when ``turn_records`` show the
@@ -644,6 +750,29 @@ class SkillTriggeredCriterion(BaseSuccessCriterion):
644
750
  description="Only count Skill invocations whose 'skill' parameter matches this name.",
645
751
  )
646
752
 
753
+ def live_decidable_polarities(self) -> frozenset[LivePolarity]:
754
+ """Per-instance narrowing under the checker's any-engagement latch.
755
+
756
+ The checker's ``live_verdict`` (``criteria/skill_triggered.py``) can
757
+ decide either polarity at the TYPE level, but a single INSTANCE only
758
+ ever resolves one of them:
759
+
760
+ - a **positive** criterion (``skill_name == expected_skill``) can only
761
+ live-``pass`` (the expected skill engaging is a decidable hit; its
762
+ absence is not knowable mid-run);
763
+ - a **distractor/negative** criterion (``skill_name != expected_skill``,
764
+ including the ``expected_skill == ""`` negatives) can only
765
+ live-``fail`` (a wrong skill engaging is a decidable miss; its
766
+ absence is not).
767
+
768
+ ``validate_early_stop`` gates the requested ``stop_when`` on this set,
769
+ so arming a positive with ``fail`` / a distractor with ``pass`` — or
770
+ either with ``decided`` (which needs both) — is rejected at resolution
771
+ rather than silently degrading to a full run.
772
+ """
773
+ expected_yes = self.expected_skill == self.skill_name
774
+ return frozenset({"pass"}) if expected_yes else frozenset({"fail"})
775
+
647
776
 
648
777
  class LLMJudgeCriterion(BaseSuccessCriterion):
649
778
  """Have an LLM grade the task's final state against an author-supplied prompt.