Conversation
…sses The env-server worker rebuilds each task from its wire data as the taskset's declared Task type, so a case authored as a subclass came back as the base class with the subclass's rewards, toolsets and hooks gone, and a served run scored it silently wrong while --no-serve scored it as authored. The runner now refuses before dispatch, naming the classes and the two ways out. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Member
Author
|
On the risk note in the summary: no bundled taskset trips the refusal. Every module under |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the silent half of #2570.
A served run (the default) rebuilds each task inside the env-server worker as the taskset's declared
Tasktype from its wire data. A taskset whoseload()builds some cases as aTasksubclass loses that subclass's rewards, toolsets and hooks on the served path and scores them silently wrong, while--no-servescores them as authored.This change makes the runner refuse before dispatch when any loaded task's type is not the taskset's
task_type(), naming the classes and the two ways out: dispatch on aTaskDatafield inside the declared class, or run in-process with--no-serve(which keeps the class; remote tunnel placement still sizes off the base class, see #2570). Nothing is written or spawned before the check. Whether per-case subclasses should become a supported authoring pattern (carrying the class over the wire) is left to #2570.verifiers/v1/cli/eval/runner.py: the refusal, after task selection.tests/v1/fixtures/subclass_task_v1.py: a two-case taskset whose second case is a subclass with its own reward and toolset.tests/v1/test_e2e.py: a deterministic test (no model, noe2emark) asserting theValueErrorand that no run directory is created.Validation, model-free: the new test passes;
uv run pytest tests/ -m "not e2e"81 passed; ruff check, ruff format and the pre-commit hooks pass; the in-process loader still yields both classes for the fixture. Reproduction of the underlying bug againstEnvServer._build_taskis in #2570.🤖 Generated with Claude Code
Note
Low Risk
Adds a pre-dispatch validation on the served eval path only; in-process runs are unchanged and the failure mode is an explicit error instead of silent mis-scoring.
Overview
Served eval runs now fail fast if the taskset’s
load()returns tasks whose runtime type is not the taskset’s declaredTaskclass. On the default served path, workers rebuild tasks from wire data using only that declared type, so per-case subclasses would lose extra rewards, toolsets, and hooks and score incorrectly without an obvious error.The check runs in
run_evalafter task selection and before any output directory or worker pool is created. The raisedValueErrornames the unexpected class(es) and points authors to branch onTaskDatainside the declared task type or use--no-servefor in-process runs that preserve the subclass instances.A
subclass-task-v1fixture (base task +SpecialTaskwith its own reward and toolset) and a model-free test assert the refusal message and that no run directory is written.Reviewed by Cursor Bugbot for commit a1514f6. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Refuse served runs when taskset loads per-case
Tasksubclasses inrun_evalrun_eval(runner.py) that checks whether any selected task's exact type differs from the taskset's declaredTasktype, raisingValueErrorbefore output setup or dispatch for served runs.TaskDatafield or--no-serve.subclass-task-v1fixture (subclass_task_v1.py) and an end-to-end test (test_e2e.py) that confirms theValueErrormentionsSpecialTaskand--no-serveand that no served output directory is created.ValueErrorinstead of proceeding; verify tasksets inverifiers/v1forSubclassTaskset-style loaders.Macroscope summarized a1514f6.