Skip to content

Commit fbf44b8

Browse files
rockymaddenclaude
andcommitted
docs(criteria): name the budget-breach trigger on the post-failure path
`_run_evaluation_with_failure_evidence` catches BudgetExceededError alongside AgentCrashError and TurnTimeoutError, so a `read_only` command also runs after a token or cost breach that stopped grading part-way. The field description, both guides and the method docstring said otherwise. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 24b2ab6 commit fbf44b8

5 files changed

Lines changed: 15 additions & 10 deletions

File tree

‎docs/REPORT_SCHEMA.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,9 @@ fields so subclass keys round-trip.
188188

189189
### Post-failure criterion evidence
190190

191-
When an agent crashes or its turn times out, coder-eval runs only deterministic,
192-
read-only artifact criteria while the sandbox is still live: `file_exists`,
191+
When an agent crashes, its turn times out, or a token/cost budget breach stops grading
192+
part-way, coder-eval runs only deterministic, read-only artifact criteria while the
193+
sandbox is still live: `file_exists`,
193194
`file_contains`, `file_matches_regex`, `file_check`, `json_check`,
194195
`reference_comparison`, and `classification_match`. A `run_command` criterion joins them
195196
only when the task author sets [`read_only: true`](TASK_DEFINITION_GUIDE.md#run_command)

‎docs/TASK_DEFINITION_GUIDE.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -905,7 +905,7 @@ Runs a command and checks the exit code, with optional stdout matching. **Binary
905905
stdout_match: "exact" # "exact" (default), "contains", or "regex"
906906
description: "Script must output the correct text"
907907
908-
# Graded even when the agent's turn times out or the agent crashes
908+
# Graded even when the turn times out, the agent crashes, or a budget breach cuts grading short
909909
- type: "run_command"
910910
command: "python graders/check_flow.py"
911911
read_only: true # declaration, not enforcement -- see below
@@ -920,7 +920,7 @@ Runs a command and checks the exit code, with optional stdout matching. **Binary
920920
| `expected_stdout` | `null` | When set, stdout is also checked |
921921
| `stdout_match` | `"exact"` | Match mode: `exact` (stripped), `contains` (substring), `regex` (pattern) |
922922
| `score_from_stdout` | `false` | Read a float score (0.0–1.0) from the first stdout line (remaining lines become details); a non-zero exit code or a parse failure scores 0.0. Mutually exclusive with `expected_stdout`. |
923-
| `read_only` | `false` | Declares the command inspects artifacts only. Its sole effect: the criterion is also graded after a terminal agent failure — see [Post-failure criterion evidence](REPORT_SCHEMA.md#post-failure-criterion-evidence). |
923+
| `read_only` | `false` | Declares the command inspects artifacts only. Its sole effect: the criterion is also graded on the post-failure diagnostic path — after a turn timeout, an agent crash, or a budget breach that stopped grading. See [Post-failure criterion evidence](REPORT_SCHEMA.md#post-failure-criterion-evidence). |
924924

925925
`read_only` is an author declaration, **not** a restriction. coder-eval cannot decide
926926
whether a shell command is pure, so it verifies nothing and confines nothing: the

‎plugins/coder-eval/reference/criteria.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ Optional:
249249
| `expected_stdout` | Expected stdout content. When set, stdout is also checked. |
250250
| `stdout_match` | How to match stdout: 'exact' (stripped), 'contains' (substring), 'regex' (pattern) |
251251
| `score_from_stdout` | When true, read a float score (0.0-1.0) from the first line of stdout. Remaining lines are captured as details. Non-zero exit code or parse failure -> score 0.0. Mutually exclusive with expected_stdout. |
252-
| `read_only` | The task author's DECLARATION that this command only inspects artifacts: it writes nothing, reaches no live service, and returns the same verdict every run. Its only effect is eligibility -- the criterion is also graded after a terminal agent failure (turn timeout or agent crash), while the sandbox is still live, so a timed-out run records what the artifacts were worth. That result is diagnostic and never moves final_status or weighted_score. UNVERIFIED AND UNENFORCED: purity of a shell command is not decidable here, the command runs exactly as it would normally, and nothing stops a mutating command from being marked. Leave it false for anything that writes state or calls a live tenant (e.g. 'uip maestro flow debug', which starts a cloud job). |
252+
| `read_only` | The task author's DECLARATION that this command only inspects artifacts: it writes nothing, reaches no live service, and returns the same verdict every run. Its only effect is eligibility -- the criterion is also graded on the post-failure diagnostic path, while the sandbox is still live, so a run that died mid-flight still records what the artifacts were worth. Three failures reach that path: a turn timeout, an agent crash, and a token or cost budget breach that stopped grading part-way. The command runs on every one of them. That result is diagnostic and never moves final_status or weighted_score. UNVERIFIED AND UNENFORCED: purity of a shell command is not decidable here, the command runs exactly as it would normally, and nothing stops a mutating command from being marked. Leave it false for anything that writes state or calls a live tenant (e.g. 'uip maestro flow debug', which starts a cloud job). |
253253

254254
### `skill_triggered`
255255

‎src/coder_eval/models/criteria.py‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -413,9 +413,11 @@ class RunCommandCriterion(BaseSuccessCriterion):
413413
description=(
414414
"The task author's DECLARATION that this command only inspects artifacts: it writes "
415415
"nothing, reaches no live service, and returns the same verdict every run. Its only "
416-
"effect is eligibility -- the criterion is also graded after a terminal agent failure "
417-
"(turn timeout or agent crash), while the sandbox is still live, so a timed-out run "
418-
"records what the artifacts were worth. That result is diagnostic and never moves "
416+
"effect is eligibility -- the criterion is also graded on the post-failure diagnostic "
417+
"path, while the sandbox is still live, so a run that died mid-flight still records "
418+
"what the artifacts were worth. Three failures reach that path: a turn timeout, an "
419+
"agent crash, and a token or cost budget breach that stopped grading part-way. The "
420+
"command runs on every one of them. That result is diagnostic and never moves "
419421
"final_status or weighted_score. UNVERIFIED AND UNENFORCED: purity of a shell command "
420422
"is not decidable here, the command runs exactly as it would normally, and nothing "
421423
"stops a mutating command from being marked. Leave it false for anything that writes "

‎src/coder_eval/orchestrator.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -893,8 +893,10 @@ async def _evaluate_post_failure_criteria(self) -> None:
893893
"""Evaluate diagnostic criteria before the live sandbox is torn down.
894894
895895
Results stay outside the canonical scored list. Only criteria that
896-
declare themselves deterministic and read-only run on this path. This
897-
excludes judges and checks that execute sandbox commands.
896+
declare themselves deterministic and read-only run on this path. That
897+
excludes judges and trajectory checks, and every ``run_command``
898+
criterion except one the task author marked ``read_only`` -- which DOES
899+
execute a sandbox command here.
898900
"""
899901
if self.result is None:
900902
return

0 commit comments

Comments
 (0)