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.
- {coder_eval-0.9.2 → coder_eval-0.9.3}/CHANGELOG.md +21 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/CLAUDE.md +2 -2
- {coder_eval-0.9.2 → coder_eval-0.9.3}/PKG-INFO +1 -1
- {coder_eval-0.9.2 → coder_eval-0.9.3}/action.yml +1 -1
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/EXTENDING.md +10 -2
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/REPORT_SCHEMA.md +5 -2
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/TASK_DEFINITION_GUIDE.md +61 -5
- {coder_eval-0.9.2 → coder_eval-0.9.3}/pyproject.toml +1 -1
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/__init__.py +1 -1
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/base.py +21 -34
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/command_executed.py +1 -37
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/skill_triggered.py +5 -35
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/__init__.py +4 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/criteria.py +132 -3
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/limits.py +43 -7
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/results.py +52 -5
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/early_stop.py +204 -52
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestrator.py +55 -12
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/reports.py +8 -4
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/reports_experiment.py +4 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/reports_html.py +9 -3
- coder_eval-0.9.3/tasks/early_stop_decision_budget_exceeded.yaml +40 -0
- coder_eval-0.9.3/tasks/early_stop_weighted_high_weight_kills_run.yaml +55 -0
- coder_eval-0.9.3/tasks/early_stop_weighted_low_weight_absorbed.yaml +54 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/runner.py +0 -2
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_custom_lint.py +99 -56
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_early_stop.py +618 -58
- {coder_eval-0.9.2 → coder_eval-0.9.3}/uv.lock +110 -110
- coder_eval-0.9.2/tests/lint/rules/ce025_live_verdict_consistency.py +0 -111
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-code-review-full.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-code-review-wf.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-code-review.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-create-plan.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-implement-plan.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-review.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-run-analysis.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/commands/coder-eval-task-create.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/harness-candidates.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/shared/axes.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/shared/multi-model-review.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/shared/review-rubric.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/shared/run-layout.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/workflows/cr-axis.js +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.claude/workflows/cr-parent.js +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.env.example +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/CODEOWNERS +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/ISSUE_TEMPLATE/adopter.yml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/code_review.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/dependabot.yml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/pages-stub/index.html +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/scripts/release_notes.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/claude-pr-review.yml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/codeql.yml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/conventional-commits.yml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/docker-publish.yml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/docs.yml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/pr-checks.yml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/publish-testpypi.yml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.github/workflows/release.yml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.gitignore +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.pre-commit-config.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/.python-version +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/ADOPTERS.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/CODE_OF_CONDUCT.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/CONTRIBUTING.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/LICENSE +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/Makefile +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/NOTICE +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/README.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/SECURITY.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docker/Dockerfile +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docker/Dockerfile.runtime +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docker/coder_eval_entrypoint.sh +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docker/coder_eval_runtime_entrypoint.sh +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/AB_EXPERIMENTS.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/CI_GATE.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/DATASETS.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/DIALOG_MODE.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/DOCKER_ISOLATION.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/USER_GUIDE.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/agents/ANTIGRAVITY.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/agents/CLAUDE_CODE.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/agents/CODEX.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/assets/hero.gif +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/comparison.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/index.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/llms.txt +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/tutorials/01-first-evaluation.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/tutorials/02-ci-pipeline.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/tutorials/03-evalboard-local.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/tutorials/04-writing-a-task.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/tutorials/05-comparing-models.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/tutorials/06-use-docker-isolation.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/docs/tutorials/README.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/.gitignore +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/README.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/__tests__/harness-badge.test.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/__tests__/harness-selector.test.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/__tests__/search-box.test.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/col-help.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/collapsible-rail.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/harness-badge.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/harness-selector.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/scroll-table.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/search-box.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/unit-toggle.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_components/version-list.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/__tests__/harness-legend.test.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/__tests__/harness-series.test.ts +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/daily-chart.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/harness-legend.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/harness-series.ts +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/tag-rail.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/turn-budget-chart.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/_overview/window-summary.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/api/download/route.ts +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/api/file/route.ts +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/api/refresh/__tests__/route.test.ts +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/api/refresh/route.ts +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/error.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/globals.css +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/icon.png +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/layout.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/page.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/path-to-ga/page.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/trends/__tests__/trends-view.test.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/trends/actions.ts +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/trends/page.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/trends/trends-view.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/watchlist/__tests__/watchlist-view.test.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/watchlist/page.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/app/watchlist/watchlist-view.tsx +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/next-env.d.ts +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/next.config.mjs +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/package.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/pnpm-lock.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/postcss.config.mjs +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/public/harness/antigravity.png +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/public/harness/claude-code.png +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/public/harness/codex.png +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/public/uipath.png +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/tailwind.config.ts +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/tsconfig.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/vitest.config.ts +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/evalboard/vitest.setup.ts +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/experiments/default.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/experiments/early-stop-ab.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/experiments/model-comparison.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/experiments/permissions-smoke.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/experiments/plugin-comparison.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/experiments/prompt-mutations-example.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/experiments/smoke_variants.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/litellm/README.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/litellm/cost_logger.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/litellm/litellm-config.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/litellm/start-litellm.sh +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/mkdocs.yml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/osv-scanner.toml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/scripts/check_commit_msg.sh +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/.gitattributes +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agent.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/_logging.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/antigravity_agent.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/claude_code_agent.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/codex_agent.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/noop_agent.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/registry.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/agents/watchdog.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/analysis.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/aggregate_command.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/console.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/evaluate_command.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/plan_command.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/report_command.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/run_command.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/run_helpers.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/run_task_internal_command.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/cli/utils.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/config.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/_classification_aggregate.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/agent_judge.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/classification_match.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/commands_efficiency.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/file_check.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/file_contains.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/file_exists.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/file_matches_regex.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/json_check.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/llm_judge.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/reference_comparison.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/run_command.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/criteria/uipath_eval.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/agent.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/budget.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/categories.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/categorization.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/checker_misuse.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/executor.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/judge.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/retry.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/errors/timeout.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/checker.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_anthropic.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_bedrock.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_context.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_models.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_persistence.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/judge_usage.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/sub_agent.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/summaries.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/evaluation/verdict_tool.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/formatting.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/isolation/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/isolation/docker_runner.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/litellm_cost.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/logging_config.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/agent_config.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/container_paths.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/enums.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/experiment.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/judge.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/judge_defaults.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/merge_strategy.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/mutations.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/routing.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/sandbox.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/tasks.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/telemetry.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/models/templates.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/batch.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/config.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/config_merge.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/evaluation.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/experiment.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/overrides.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/orchestration/task_loader.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/path_utils.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/plugins.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/pricing.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/py.typed +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/reports_junit.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/reports_stats.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/resources/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/resources/default_ignore_patterns.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/resources/tags.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/sandbox.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/scoring/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/scoring/ast_similarity.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/scoring/complexity.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/scoring/quality.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/scoring/signature_similarity.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/scoring/similarity.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/scoring/token_similarity.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/simulation/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/simulation/termination.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/simulation/user_simulator.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/streaming/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/streaming/callbacks.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/streaming/collector.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/streaming/events.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/streaming/renderers.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/streaming/wire.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/telemetry.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/src/coder_eval/utils.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/README.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agentless_smoke_test.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/antigravity_hello_world.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/antigravity_hello_world_docker.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/claude_hello_world.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/claude_hello_world_docker.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/claude_parallel_single_gen.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/claude_subagent_test.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/codex_disallowed_tools_test.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/codex_hello_world.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/codex_parallel_commands.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/codex_parallel_single_gen.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/codex_skills_test.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/codex_string_utils.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/codex_subagent_test.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/subagent_bash_long_input.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/agents/subagent_merge_sort.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/byod_smoke_test.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/dataset_example.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/datasets/sentiment.jsonl +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/dockerfile_build_example/dockerfile_build_example.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/dockerfile_build_example/environment/Dockerfile +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/dockerfile_build_example/environment/Dockerfile.workdir +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/dockerfile_build_example/environment/input.txt +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/dockerfile_build_example/working_dir_auto_example.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/dockerfile_build_example/working_dir_concrete_example.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/fibonacci_with_template.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/hello_date.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/inline_starter_example.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/internal/session_resumption.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/mock_path_dirs_smoke.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/mock_path_dirs_template_dir/mock-cli-bins/README.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/mock_path_dirs_template_dir/mock-cli-bins/mocks/echo_args +0 -0
- {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
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/mock_path_dirs_template_dir/mock-cli-bins/mocks/say_hello +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/mock_path_dirs_template_dir/task.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/python_cli_simulated_judged/echo_simulated_judged.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/3d-scan-calc.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/environment/Dockerfile +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/environment/material_density_table.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/environment/scan_data.stl +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/verifier/test.sh +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/3d-scan-calc/verifier/test_outputs.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/README.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/court-form-filling/court-form-filling.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/court-form-filling/environment/Dockerfile +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/court-form-filling/environment/sc100-blank.pdf +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/court-form-filling/verifier/test.sh +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/court-form-filling/verifier/test_outputs.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/dialogue-parser/dialogue-parser.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/dialogue-parser/environment/Dockerfile +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/dialogue-parser/environment/script.txt +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/dialogue-parser/verifier/test.sh +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/samples/skillsbench/dialogue-parser/verifier/test_outputs.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/sentiment_classification.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/smoke_agent_judge.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/smoke_budget_exceeded.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/smoke_cost_budget_exceeded.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/smoke_llm_judge.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/smoke_negative_path.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/smoke_task_timeout.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/smoke_variants.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/test_sandbox.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tasks/token_check.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/templates/byod_smoke_test/Dockerfile +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/templates/fibonacci-starter/README.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/templates/fibonacci-starter/src/main.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/templates/fibonacci-starter/tests/test_main.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/_scrub.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/claude_fixtures.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/codex_fixtures.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_a_single_text_turn.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_b_tool_use_result.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_c_multi_emission_delta.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_d_subagent_terminal.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_e_model_usage_and_backfill.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_f_orphaned_tool.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_g_crash_format_placeholder.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_h1_timeout_process_error.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_h2_process_error_crash.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/claude_i_in_loop_deadline_break.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_a_agent_message_only.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_b_command_execution.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_c_reasoning_placeholder.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_d_cross_flush_is_error.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_e_orphan_tool.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_f_collab_fallback.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_g_items_rebuild.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/golden_streams/expected/codex_h_no_turn_completed_crash.json +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/_snapshot.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/experiment_2variant.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/experiment_3variant.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/experiment_replicates.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/run_full.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_fixtures/report_snapshots/run_minimal.md +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/_path_helpers.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/conftest.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/byoa_demo_plugin/byoa_demo.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/byoa_demo_plugin/pyproject.toml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/mock_agent.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/tasks/test_task_informational_criterion.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/tasks/test_task_multiple_criteria.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/tasks/test_task_pass.yaml +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/fixtures/text_stub_agent.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/dead_config_fields.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/doc_env_parity.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/doc_examples.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/doc_indexes.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/doc_schema_parity.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/__init__.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/base.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce014_merge_strategy_declared.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce015_create_subprocess_limit.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce016_no_computed_tokenusage_kwargs.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce017_models_lazy_agent_imports.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce018_no_final_status_name_denylist.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce019_telemetry_non_fatal.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce020_no_sdk_typed_base_agent_fields.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce021_guarded_evaluationresult_parse.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce022_dialog_loop_statement_cap.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce023_no_proxy_shim_import.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/ce024_discriminated_unions.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_agent_timing_access.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_blocking_io_in_async.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_cli_imports_in_core.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_silent_except.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_submodule_model_imports.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_top_level_run_limits_access.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_transcript_regex_in_eval.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/no_type_name_string_dispatch.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/open_explicit_encoding.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/read_text_explicit_encoding.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/register_criterion_required.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/subprocess_run_explicit_encoding.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/rules/yaml_models_forbid_extras.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/lint/violation.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_action_version_pin.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_config_no_timing_fields.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_config_optional_type.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_config_registry_dispatch.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_config_sdk_decoupling.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_golden_master.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_judge_criterion.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_telemetry.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_telemetry_advanced.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agent_timeout.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_agentless.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_aggregate.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_antigravity_agent.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_byoa_plugin.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_byoa_plugin_live.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_byod_feature.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_check_all_async.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_checker_logging.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_classification_match.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_claude_settings_enforcement_live.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cleanup_preservation_guard.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cli_backend_flag.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cli_empty_glob.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cli_sdk_options.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cli_set_overrides.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cli_telemetry.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cli_type_flag.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_code_review_bugs.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_codex_agent.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_codex_agent_live.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_codex_agent_unit.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_codex_token_mapping.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_command_executed.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_command_statistics.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_command_telemetry_result_data.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_commands_efficiency.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_config_lineage.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_config_merge_engine.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_config_precedence.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_continuous_scoring.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_cost_accounting_paths.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_criterion_result_round_trip.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_dataset_expansion.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_debug_logging.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_docker_build_failure.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_docker_litellm_env.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_docker_runner_container_death.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_docker_runner_mounts.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_docker_runner_stream_limit.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_docker_wildcard_env.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_docker_workdir_live.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_driver_resolver.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_error_handling.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_evaluate_command.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_evaluator.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_event_collector.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_experiment_cli.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_experiment_loader.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_experiment_models.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_experiment_reports.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_experiment_resolver.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_experiment_runner.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_file_check.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_file_contains_scoring.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_formatting.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_git_clone_failure.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_heartbeat_watchdog.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_ignore_patterns_negation.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_image_from_dockerfiles.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_integration.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_json_check.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_judge_anthropic.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_judge_bedrock.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_judge_burn_in_live.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_judge_context_builder.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_judge_models.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_judge_persistence.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_lint_no_top_level_run_limits.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_lint_runner.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_litellm_config.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_litellm_cost.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_litellm_cost_logger.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_litellm_route.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_llm_judge_criterion.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_log_tail_buffer.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_logging.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_logging_isolation.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_merge_characterization.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_merge_strategy_annotations.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_merge_unification.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_models.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_mutations.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_new_criteria.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_node_env_config.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_optional_dependencies.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_orchestrator.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_orchestrator_error_log_tail.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_orchestrator_telemetry.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_overrides_engine.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_parallel.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_path_utils.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_plan_command.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_plugin_processing.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_plugins.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_post_run.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_pr_review_workflow.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_pre_run.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_preservation_mode.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_pricing_registry.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reference_comparison_scoring.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reference_evaluator.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reference_missing_file.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reference_models.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reference_orchestrator.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_registry.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_release_notes.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_replicate_stats.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_report_command.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reports.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reports_experiment.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reports_html.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reports_junit.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reports_stats.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_reports_stats_nonfinite.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_resolve_task_files.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_resume.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_retry_logic_comprehensive.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_route_seam_exhaustiveness.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_routing.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_run_command_junit.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_run_command_stdout.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_run_limits_models.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_run_limits_orchestrator.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_run_limits_resolver.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_run_metrics.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_runtime_tool_versions.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sandbox.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sandbox_layer_builder.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sandbox_optional.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sandbox_security.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sandbox_symlink_preservation.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sandbox_templates.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_scorers.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_scoring_quality.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sdk_option_classification.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_simulation_config.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_simulation_integration.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_simulation_termination.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_simulation_trials.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_skill_triggered.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_agent_integration.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_batch.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_callbacks.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_cli.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_events.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_orchestrator.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_renderers.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_streaming_wire.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_sub_agent_runner.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_success_criterion_union.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_suite_rollup.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_summaries.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_tags.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_task_definition_unknown_fields.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_teardown_interrupt.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_telemetry.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_template_env_expansion.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_threshold_enforcement.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_timeout_batch.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_timeout_categorization.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_timeout_exceptions.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_timeout_models.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_timeout_orchestrator.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_token_usage.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_uipath_eval.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_user_simulator.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_utils.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_utterance_extraction.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_variant_prompt_file.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_verdict_tool.py +0 -0
- {coder_eval-0.9.2 → coder_eval-0.9.3}/tests/test_watchdog.py +0 -0
- {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 (
|
|
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.
|
|
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.
|
|
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**,
|
|
214
|
-
`
|
|
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.**
|
|
380
|
-
non-armed criteria become **advisory** and
|
|
381
|
-
per-criterion note + `stopped_early`
|
|
382
|
-
|
|
383
|
-
|
|
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.
|
|
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"
|
|
@@ -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).
|
|
430
|
-
|
|
431
|
-
|
|
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
|
|
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
|
|
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``
|
|
183
|
-
from first-engagement: a wrong
|
|
184
|
-
|
|
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(
|
|
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(
|
|
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.
|