swe_env/anyswe: address @ffrujeri review on #1572 (fixes + gold baseline) - #1802
Merged
adil-a merged 16 commits intoJun 29, 2026
Merged
Conversation
…ng tests) - docker provider: configurable default exec timeout + bounded close/cp so a hung in-container command can't block a rollout; clear error when docker is missing (wrap FileNotFoundError); classify only rc 125 (not 126/127 user-command codes) as an infra failure. - verify_task: mask SandboxCreateError / image-pull failures (error_kind=sandbox) so infra hiccups on the docker pull-on-demand path don't depress resolve rate. - swe_rebench: empty-required guard (consistent with compute_resolved) so a degenerate row no longer inflates to reward 1.0. - anyswe _setup_params: accept instance_dict as str OR dict (mirror _build_swetask). - shlex.quote dataset values interpolated into bash -c (nv_internal/harness/ swe_bench_ext). - r2egym docstring: missing eval_script is unmasked reward-0, not an eval-error mask. - openclaw config: select the apptainer provider for its .sif formatter; drop dead apptainer_memory_limit_mb/skip_eval fields. - tests: add test_parsing_frameworks.py (jest/maven/cargo/pytest/unknown); docker regression tests (rc125-only, 126/127 user-errors, default timeout, missing-docker); split verify_task into sandbox-masked vs generic-unmasked; swe_rebench empty-required. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Codex <codex@openai.com>
Adds fern/ Agent Server page covering the harness-agnostic SWE environment (anyswe runner + swe_env library: harnesses, sandbox lifecycle, inline verify_task, self_drive) and selecting the docker vs apptainer sandbox provider. fern check clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Codex <codex@openai.com>
… anyswe mask) anyswe's truncation mask (resolved AND status==incomplete) was inert because no inner agent set the top-level status. Now each self-reports: - hermes: status=incomplete when run_conversation reports completed=False (max-iterations). - claude_code: parse_stream_json flags incomplete on a CLI result event that is_error or has a non-"success" subtype; an internal subprocess timeout (which can fire before anyswe's outer agent timeout) emits a synthetic result event so it self-reports incomplete rather than slipping through both guards. - openclaw: documented that it exposes no internal stop-reason signal (status left unset); its subprocess-timeout truncation is masked upstream by agent_timed_out. Verified end-to-end: top-level status survives the response.json round-trip (model_dump_json -> model_validate_json) and anyswe masks resolved+incomplete. Tests: claude_code result-subtype + synthetic-timeout incomplete cases. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Codex <codex@openai.com>
… under-resolution) The full SWE-bench Verified gold-patch census on docker exposed a host-side parse gap: swebench 4.1.0's per-repo eval command for some families (sphinx via tox, several sklearn) runs pytest without -rA, so passing tests print only as progress dots. The host-side parser (parse_log_pytest_v2) keys off 'PASSED <nodeid>' lines, so it saw zero passes and marked those instances unresolved even for the gold patch (census: ~45 sphinx + 5 sklearn missed -> 445/500 vs the .sif/nested reference 492/500). Forcing PYTEST_ADDOPTS=-rA in the flat eval makes every test's result visible to the parser; non-pytest families (django's runner) ignore it. Verified: sphinx-doc__sphinx-7440 gold went status_map 1->14, resolved False->True. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Codex <codex@openai.com>
Reward-profiling evidence (review #4): the docker gold-patch census resolves 486/500 (after the PYTEST_ADDOPTS=-rA flat-grading fix; 445 before), in line with the apptainer/.sif reference 492/500; the empty patch resolves 0/500. The remaining ~14 are instance-specific (documented astropy/django upstream flaky gold-failures + a few where a single required test does not run in the container), not a systematic grader defect. Includes a docker/apptainer repro snippet. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Codex <codex@openai.com>
Contributor
|
🌿 Preview your docs: https://nvidia-preview-swe-env-review-fixes.docs.buildwithfern.com/nemo/gym Here are the markdown pages you've updated: |
…ld images)
The docker gold census's residual misses vs the .sif/nested 492 reference were NOT concurrency
or a docker-vs-apptainer difference — they were a flat-grading reconstruction bug. Older instance
images' git cannot parse GIT_CONFIG_GLOBAL=/dev/null ('bad config line 1 in file /dev/null'), so
the eval script's git checkout + test-patch git apply FAIL, the gold fix's new tests are never
added, and the required tests come back 'absent' -> false unresolved. swebench's nested eval
(which produced 492) doesn't null the config. Dropping it (keeping GIT_PAGER=cat) lets git work
on all images. Confirmed: sklearn-14629 gold resolved False->True (27/27 required, 0 bad-config
errors). Applied across all 5 harnesses.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Codex <codex@openai.com>
…sted parity) The docker gold census reaches 493/500 after the GIT_CONFIG_GLOBAL fix (445 -> 486 with -rA -> 493 with the git-env fix), matching the apptainer/.sif nested reference 492/500 to within environment noise. Documents the docker<->apptainer parity (both use the flat grader) and the two reconstruction gaps the census surfaced + closed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Codex <codex@openai.com>
ffrujeri
self-requested a review
June 28, 2026 02:45
ffrujeri
approved these changes
Jun 28, 2026
Add responses_api_agents/anyswe_agent/gold_census.py, a standalone gold-patch census driver (no model, no agent) that feeds each SWE-bench instance's gold patch through the flat grader and tallies resolves -- the tool that produces the README baseline. Resumable + checkpointed; docker --rmi bounds disk. The apptainer path injects --writable-tmpfs to mirror anyswe's grading provider (the read-only base .sif otherwise fails the eval's git checkout / patch apply, scoring every instance unresolved). Reference it from the swe_env README's Reproduce section. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Codex <codex@openai.com>
The apptainer provider bind-mounts the host $HOME by default, so in-container matplotlib reads the host's matplotlib config + font cache. That flips image- comparison tests (e.g. test_axes.py::test_pcolormesh_small[eps]) vs docker: an 8-instance matplotlib gap where the gold patch resolved on docker-flat but failed on apptainer-flat. swebench's own nested .sif path avoided this with --no-mount. Add --no-mount home to the apptainer grading + agent sandboxes (_grading_provider, _provider) and to gold_census.py, alongside --writable-tmpfs. Validated: matplotlib- 24149 768/768 (was 767/768); all 8 matplotlib misses resolve under the fix, giving exact docker==apptainer parity on the graded set. --cleanenv / --no-mount tmp,bind- paths were too aggressive (broke the eval's conda/PATH env -> empty test log); HOME= /root alone is insufficient (apptainer reasserts HOME). Add 3 unit tests (19 pass). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Codex <codex@openai.com>
…efault 1800s)
flat_run_eval ran the eval command with timeout_s=task.metadata.get('tests_timeout')
-> None when unset -> the eval inherited each sandbox provider's exec default. Those
differ enormously: docker 3600s vs apptainer 180s. So any test suite taking >180s
(scikit-learn, sympy, or any suite slowed under concurrency) was silently masked as a
'timeout' on apptainer while resolving on docker -- a spurious docker<->apptainer
grading gap that has nothing to do with the patch. Evidence: a tmpfs-vs-disk overlay
A/B made no difference (both hit ~180s); the cap, not I/O, was the wall.
Default to 1800s (matches swe_rebench's harness, anyswe's swebench_tests_timeout, and
swebench run_evaluation's own per-repo budget) so the per-command budget is identical
on every backend. Add 2 regression tests asserting the eval command carries 1800s (not
None) and that an explicit tests_timeout still overrides.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Codex <codex@openai.com>
Follow-up to the flat_eval timeout fix: close the same gap in the rest of the library so the fix is complete, not just on the SWE-bench-Verified flat path. - verify_task: propagate the caller's eval_timeout_s into task.metadata['tests_timeout'] when unset, so the configured budget reaches the in-sandbox eval command itself (not just the outer wall-clock guard). Otherwise raising eval_timeout_s/swebench_tests_timeout had no effect on the command, which fell back to the provider exec default. - swe_bench_ext + nv_internal: run the eval command with timeout_s=tests_timeout (default 1800s), matching flat_eval + swe_rebench. Previously they passed no timeout, so the command inherited the provider exec default -- apptainer 180s vs docker 3600s -- masking long suites (scikit-learn/sympy/etc.) as timeouts on apptainer only. (r2egym already routes through flat_eval, so it inherits the fix.) - 3 verify_task regression tests (default 1800s budget; eval_timeout_s propagates to the command; explicit tests_timeout preserved). 163 swe_env tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Codex <codex@openai.com>
Rewrite the reward-profiling baseline with the docker-flat / apptainer-flat / official-nested numbers and an evidence-backed overcount analysis: - docker-flat 493/500 and apptainer-flat 490/500 use the identical host-side grader; apptainer never over-resolves. The 3-instance gap is non-grading: psf/requests-1724/2317 (external httpbin.org returning 503 at run time -- docker fails them identically when httpbin is down) and scikit-learn-14710 (eval-timeout under --concurrency 12; resolves in isolation -- verified). - 493 is NOT an overcount: it exceeds official run_evaluation 4.1.0 (490) because that tool runs sphinx-via-tox pytest without -rA and undercounts sphinx-8595/9711 (genuinely passing, tox exit 0) -- which flat correctly resolves. flat is in fact conservative (misses sphinx-8120/8265/8269). ~496/500 truly resolvable; the only genuine gold failures are astropy-7606/8707/8872 + django-10097 (real fail, confirmed once the 1800s timeout let its ~1900-test suite finish). - Document the two apptainer parity fixes (--no-mount home, 1800s eval-command timeout) and that gold_census.py applies them automatically. Add the run_evaluation cross-check command with its -rA/httpbin caveats. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Codex <codex@openai.com>
The 492 reference was swebench's NESTED run_evaluation on .sif (a different grader), not this flat grader. Spell out that docker-flat and apptainer-flat are the same grader (miss the identical 7) and both reach 493; apptainer's measured count is lower only by transient run-time conditions: psf/requests-1724/2317 hit httpbin.org while it was returning 503 (docker fails them identically when down), and sklearn-14710 hit a CONC=12 eval timeout (re-graded in isolation it resolves -> folded in, 490->491). Grading parity is exact; the gap is never the grader. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Codex <codex@openai.com>
…t parity Make the documented tool able to reproduce the FULL apptainer census without pre-staging 500 .sif files, and to run both providers under identical conditions: - --apptainer-build: build each missing .sif on-demand from docker://swebench/... (apptainer pull --disable-cache); with --rmi only the on-demand-built sifs are deleted afterward (pre-existing sifs are kept). Smoke: docker 2/2, apptainer 2/2, built sifs auto-removed. - --tests-timeout: pass a per-eval budget (default 1800) so heavy suites aren't masked by a concurrency-induced timeout when comparing providers for exact parity. - README: document running both providers in the same httpbin window + --tests-timeout 3600 for an identical passing set. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Codex <codex@openai.com>
…each) Re-ran both providers via gold_census.py in one window (same httpbin.org state) with --tests-timeout 3600 to remove the two non-grading confounds (external httpbin + a concurrency-induced eval timeout). Result: docker-flat and apptainer-flat resolve the IDENTICAL 493/500 and miss the IDENTICAL 7 (astropy-7606/8707/8872, django-10097, sphinx-8120/8265/8269) -- same passing set, same failing set, zero over-resolves either way. The earlier 493-vs-491 split was purely httpbin.org flapping 503->200 mid-run (the psf/requests instances graded at different moments on each provider) + one sklearn CONC=12 timeout; reconciling the 8 psf ids on both providers in the same window with httpbin up resolves all of them on both. Update the baseline table + state the parity-measurement recipe (one window, --tests-timeout 3600). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Codex <codex@openai.com>
…=493 The gold_census.py docstring still cited 'apptainer/.sif 492/500' (the OLD nested run_evaluation reference); update it to the verified flat result (docker-flat == apptainer-flat == 493/500, identical set). Tighten the Fern SWE-Environment note from 'equivalent resolve rates' to the verified identical 493/500 set, and point at the README for the reproduce recipe. README itself already carries the verified numbers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Codex <codex@openai.com>
j-nolan
added a commit
to j-nolan/Gym
that referenced
this pull request
Jun 30, 2026
New nemo_gym/sandbox/providers/enroot: an EnrootProvider implementing the
SandboxProvider Protocol via the enroot CLI (import/create/start --rw/remove),
registered as the "enroot" builtin. Scheduler-agnostic (no Slurm/pyxis/path
assumptions; ENROOT_* read from env). Unlike apptainer it needs no writable
overlay (enroot rootfs is writable) and no host-$HOME isolation.
anyswe_agent._provider: add an enroot branch injecting the per-instance binds
(/trajectories_mount, /nemo_gym_mount, /agent_deps_mount) into exec.default_binds,
parity with the apptainer/docker branches.
anyswe_openclaw.yaml: sandbox_provider {enroot}, .sqsh container_formatter,
nemotron-3-ultra. Lets OpenClaw+SWE-bench (PR NVIDIA-NeMo#1802) run on enroot-only clusters.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
j-nolan
added a commit
to j-nolan/Gym
that referenced
this pull request
Jun 30, 2026
New nemo_gym/sandbox/providers/enroot: an EnrootProvider implementing the
SandboxProvider Protocol via the enroot CLI (import/create/start --rw/remove),
registered as the "enroot" builtin. Scheduler-agnostic (no Slurm/pyxis/path
assumptions; ENROOT_* read from env). Unlike apptainer it needs no writable
overlay (enroot rootfs is writable) and no host-$HOME isolation.
anyswe_agent._provider: add an enroot branch injecting the per-instance binds
(/trajectories_mount, /nemo_gym_mount, /agent_deps_mount) into exec.default_binds,
parity with the apptainer/docker branches.
anyswe_openclaw.yaml: sandbox_provider {enroot}, .sqsh container_formatter,
nemotron-3-ultra. Lets OpenClaw+SWE-bench (PR NVIDIA-NeMo#1802) run on enroot-only clusters.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
elisam0
pushed a commit
to elisam0/Gym
that referenced
this pull request
Jul 20, 2026
The committed config (from NVIDIA-NeMo#1802) hardcoded model nvinf/nvidia/qwen/qwen3.6-35b-a3b and set the OpenClaw workspace to /testbed. Against a serve that does not serve that model, OpenClaw gets no responses and emits only its bootstrap scaffolding, and workspace=/testbed makes that scaffolding pollute the graded diff. Points the model at ${policy_model_name} (follows run_eval's -m flag), moves OpenClaw's workspace and run dir off /testbed (workspace_root /tmp/openclaw_ws, workspace .) to keep the /testbed diff clean, and adds node_bin_dir /agent_deps_mount/bin so the portable Node 22 wins over a task image's Node 18. Validated on a 5-task smoke (nemotron-nano-3.5-ea2): 3/5 resolved with genuine repo edits, 0 scaffolding pollution, 0 node failures. Full verified500 run in progress. Draft for review.
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.
Addresses @ffrujeri's review on #1572 (all 13 inline comments) plus the reward-profiling baseline. Targets
cmunley1/anyswe.Review-comment fixes (@ffrujeri)
status="incomplete"on internal max-turns/context/timeout; anyswe masksresolved AND incomplete(verified the status round-trips throughresponse.json). openclaw exposes no internal signal → documented..sifformatter; drop deadapptainer_memory_limit_mb/skip_evalfields.exectimeout + boundedclose/cpso a hung in-container command can't block a rollout._setup_paramsassumes strinstance_dict_build_swetask).eval_scriptis unmasked reward-0, not an eval-error mask.FileNotFoundError→ clearSandboxCreateError.shlex.quotedataset values inbash -c(nv_internal/harness/swe_bench_ext).compute_resolved).SandboxCreateError/image-pull (error_kind="sandbox").test_parsing_frameworks.py(the 7 reviewer cases).Gold-patch baseline (review #4) — at parity with the nested reference
A full 500-instance SWE-bench Verified gold-patch census on docker resolves 493/500 (
patch_exists500/500, 0 infra errors), matching the apptainer/.sifnested reference 492/500 to within environment noise; empty patch 0/500. (docker and apptainer both use the host-side flat grader here, so they're 1-1; the.siffigure is swebench's nestedrun_evaluation.)The census surfaced + fixed two real flat↔nested reconstruction gaps (445 → 486 → 493), verified with 0 regressions:
PYTEST_ADDOPTS=-rA: swebench 4.1.0's eval for some families (sphinx viatox, several sklearn) runs pytest without-rA, so passing tests print only as dots and the host-side parser saw zero passes → ~45 unresolved even for gold (445→486).GIT_CONFIG_GLOBAL=/dev/null: older images' git can't parse/dev/null, so the eval'sgit checkout+ test-patchgit applyfailed → required tests "absent" (486→493).The remaining 7 misses are a small symmetric difference with
.sif(4 shared genuine env-flaky: astropy-7606/8707/8872, django-10097; 3 docker-only sphinx instance-specific quirks; docker also resolves 4 that.sifmisses).Validation
fern checkclean.#1truncation logic was adversarially verified end-to-end (top-levelstatussurvives the container→host round-trip; the mask is live).🤖 Generated with Claude Code