fix(tbench2_env): canonical test.sh scoring, real timeouts, task-image workdir#965
Open
nblintao wants to merge 1 commit into
Open
fix(tbench2_env): canonical test.sh scoring, real timeouts, task-image workdir#965nblintao wants to merge 1 commit into
nblintao wants to merge 1 commit into
Conversation
5 tasks
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 289b100. Configure here.
| ) | ||
| if not (workdir and Path(workdir).is_dir()): | ||
| workdir = str(task_dir) | ||
| self._workdir = workdir |
There was a problem hiding this comment.
Wrong cwd when WORKDIR exists
High Severity
During reset, the parsed task WORKDIR is kept whenever Path(workdir).is_dir() is true. On the OpenEnv server image, /app already exists but is not the task tree, so many tasks whose Dockerfile uses WORKDIR /app run agent and verifier commands in the server root instead of the resolved task directory.
Reviewed by Cursor Bugbot for commit 289b100. Configure here.
nblintao
force-pushed
the
tb2-local-mode-fidelity
branch
from
July 15, 2026 04:04
289b100 to
4745fd2
Compare
5 tasks
…ask env & workdir - _evaluate_task runs the task's official tests/test.sh (pinned uvx toolchain, /logs/verifier/reward.txt) when the task ships it; the bare pytest fallback (custom task dirs without the canonical harness) prefers uvx with a pinned pytest so it carries its own toolchain, and runs from the same workdir the agent worked in. - Pass timeouts through to every shell_exec call: camel's shell_exec has its own per-call default (20s) and ignores the constructor timeout, so agent commands and evaluations were silently truncated at 20s (circuit-fibsqrt's verifier declares 3600s and was cut mid-test). Agent execs use command_timeout_s (TB2_COMMAND_TIMEOUT_S-overridable); evaluate uses the task's own [verifier].timeout_sec budget. - Shell cwd resolves to the task image's own WORKDIR, parsed from the task's environment/Dockerfile (TB2_TASK_WORKDIR overrides): task images pin their own WORKDIR (fix-git: /app/personal-site, prove-plus-comm: /workspace) and both agents and oracle solutions assume commands run there. Falls back to the task source dir for plain local mode. - Drop install_dependencies=['pytest'] (evaluation carries its own pytest via uvx); with CAMEL_RUNTIME=true camel's .initial_env venv then stops hijacking PATH away from the task image's native python. - Serialize canonical evaluation under a lock so concurrent sessions on one server cannot clobber the official fixed verifier paths (/tests, /logs/verifier/reward.txt).
nblintao
force-pushed
the
tb2-local-mode-fidelity
branch
from
July 16, 2026 19:18
4745fd2 to
501a20c
Compare
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.


Summary
Makes local-mode
Tbench2Environmentfaithful to real Terminal-Bench-2 semantics:evaluatescores with each task's officialtests/test.sh(pinned uvx toolchain,/logs/verifier/reward.txt), command execution honors real time budgets, and commands run in the task image's own WORKDIR. Follow-up to #503, which fixed evaluate always returning 0 — this makes the returned reward match the official TB2 verifier.Details:
pytest tests/(current behavior) skips the toolchain the official harness pins (uvx: Python 3.13, pytest 8.4.1, ctrf) and mis-scores tasks that depend on it._evaluate_tasknow runstests/test.shwhen the task ships it; the bare-pytest fallback remains for custom task dirs, upgraded to preferuvx --with pytest==8.4.1so it carries its own toolchain too.shell_exechas a per-call default of 20s and ignores the constructor timeout, silently truncating agent commands and evaluations (e.g.circuit-fibsqrtdeclares a 3600s verifier budget and was cut mid-test, scoring a false 0). Agent execs now passcommand_timeout_s(overridable viaTB2_COMMAND_TIMEOUT_S); evaluate passes the task's own[verifier].timeout_sec./app(fix-git:/app/personal-site,prove-plus-comm:/workspace). The shell cwd now resolves from the task'senvironment/Dockerfile(TB2_TASK_WORKDIRoverrides), falling back to the task source dir for plain local mode.install_dependencies=['pytest']: evaluation now carries its own pytest via uvx; when the server runs withCAMEL_RUNTIME=true, camel's.initial_envvenv then also stops shadowing the task image's native python on PATH.Type of Change
Alignment Checklist
.claude/docs/PRINCIPLES.mdand this PR aligns with our principles (notably: rewards are computed inside the environment, per RFC 002).claude/docs/INVARIANTS.mdand no invariants are violated (Gym API signatures unchanged; server-internal changes only)bash .claude/hooks/lint.sh— the touched file is clean (pre-existing failures in other envs are untouched)RFC Status
Test Plan
Validated on real per-task TB2 containers (official task images), scoring official solutions under the official oracle convention:
setuptoolsfor pystan, etc. — happy to share the per-task evidence).circuit-fibsqrt/compile-compcert(timeouts),fix-git/prove-plus-comm(workdir), plus correct scoring across the suite via test.sh.Note: the canonical eval uses the official global paths (
/tests,/logs/verifier/reward.txt), which assumes one concurrent session per container — consistent with TB2's one-task-per-container model (and with one-env-one-trajectory); flagging for reviewers running multi-session servers against a single container.Claude Code Review
/alignment-review run on this change: Tier 1 (format) fixed; flags addressed during review — fallback now carries its own pytest toolchain; workdir resolution centralized server-side so all deployment modes agree. No principle or RFC conflicts identified.
Note
Medium Risk
Changes reward computation and execution semantics for TB2 local mode (timeouts, cwd, official harness); incorrect harness paths or multi-session-on-one-container setups could still mis-score, but Gym API surface is unchanged.
Overview
Aligns local
Tbench2Environmentwith official Terminal-Bench 2 verifier behavior so evaluate rewards match real TB2 runs.Evaluation now runs each task’s
tests/test.shwhen present (stages to/tests, reads/logs/verifier/reward.txt), with a thread lock so concurrent sessions don’t clash on shared harness paths. Tasks withouttest.shstill use a pytest fallback that prefersuvx --with pytest==8.4.1and uses the agent workdir; verifier runs use[verifier].timeout_secfromtask.toml.Shell cwd is resolved from the task
environment/DockerfileWORKDIR (TB2_TASK_WORKDIRoverride, else task dir), andshell_execpassescommand_timeout_sexplicitly (configurable viaTB2_COMMAND_TIMEOUT_S).install_dependencies=['pytest']is removed so scoring doesn’t rely on the toolkit venv.Reviewed by Cursor Bugbot for commit 501a20c. Bugbot is set up for automated code reviews on this repo. Configure here.