Skip to content

refactor(terminal-bench-4): per-task Compose service overrides in the profile config - #5159

Merged
gwarmstrong merged 2 commits into
NVIDIA-NeMo:mainfrom
gwarmstrong:georgea/tb4-compose-service-overrides
Oct 28, 2026
Merged

gwarmstrong merged 2 commits into
NVIDIA-NeMo:mainfrom
gwarmstrong:georgea/tb4-compose-service-overrides

Conversation

@gwarmstrong

Copy link
Copy Markdown
Contributor

What does this PR do?

terminal_bench_4 patched three tasks' Compose services in code, keyed by task name: Terminal-Bench 4's medical-claims-processing and payments-pipeline-fix, and Terminal-Bench-Science's protein-active-learning (#4879). Each has a service that runs as a non-root user, which cannot edit /etc/hosts or su. So the patch turns off host-file injection, resolves a peer URL through x-sandbox where the service needs one, and drops the service's explicit user. As yaoyu-33 suggested in the #4879 review, this PR moves the patches into the benchmark profiles, so each benchmark carries its own and the server no longer names tasks.

The new setting environment.compose_service_overrides maps a short task name and a Compose service to a JSON merge patch for that service in the agent's generated Compose YAML: mappings merge, other values replace, and null removes a setting. As with verifier_timeout_overrides and task_images.by_task, a task name that the manifest lacks stops the server at startup. A service that the task's Compose file lacks fails the task at seed. As before, the patches apply only to the agent environment, not to verifiers or to the pinned packages.

compose_service_overrides:
  protein-active-learning:
    submission:
      environment: {ASSAY_STATUS: 'http://assay:8080/status'}
      x-sandbox: {hosts: [], resolve_environment: [ASSAY_STATUS]}
      user: null

benchmarks/terminal_bench_4/resources.yaml carries the two Terminal-Bench 4 entries, and benchmarks/terminal_bench_science/resources.yaml carries protein-active-learning. The resources server README documents the setting.

No issue: follow-up to yaoyu-33's review comment on #4879.

Validation

  • Unit: terminal_bench_4 261 passed, tests/unit_tests/test_environment_validation.py 45 passed. The two existing tests for these patches keep their expected Compose output and now read the overrides from the shipped profiles. New tests cover the merge rules, a service that the task lacks, and a misspelled task name at startup.
  • Same output on the real packages: for the three pinned packages, the agent Compose YAML that Environment.start() writes is byte-identical on main and on this branch. Each run used its benchmark's resources.yaml and compose-images.json, with only the sandbox client mocked.

Rollouts

N/A: the generated Compose YAML is unchanged.

Compatibility and benchmark impact

No change for either shipped profile. A custom profile that runs medical-claims-processing, payments-pipeline-fix or protein-active-learning on terminal_bench_4 without these profiles' resources.yaml must now add the overrides itself.

… profile config

Move the three task-name Compose patches out of Environment.start() into a
profile setting, environment.compose_service_overrides: short task name ->
Compose service -> JSON merge patch applied to the agent's generated Compose
YAML. The Terminal-Bench 4 profile carries medical-claims-processing and
payments-pipeline-fix; the Terminal-Bench-Science profile carries
protein-active-learning. A task name the manifest lacks stops the server at
startup, and a service the task lacks fails the task at seed.

The generated YAML for the three pinned packages is byte-identical to main.

Signed-off-by: gwarmstrong <gwarmstrong@users.noreply.github.com>
Signed-off-by: gwarmstrong <gwarmstrong@users.noreply.github.com>
@copy-pr-bot

copy-pr-bot Bot commented Oct 27, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@gwarmstrong

Copy link
Copy Markdown
Contributor Author

/ok to test b5eee78

@nemo-automation-bot
nemo-automation-bot Bot requested review from a team October 27, 2026 22:10
@svcnvidia-nemo-ci svcnvidia-nemo-ci added area:environment Individual environments, benchmarks, verifiers, and environment-specific resources servers feature New capabilities, enhancements, or enablement work needs-review PR is ready for code review and waiting on a reviewer labels Oct 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

@svcnvidia-nemo-ci svcnvidia-nemo-ci left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SHIP — LGTM — no concerns found.

Reviewed all nine changed files and their directly affected configuration, Compose-consumer, and session-cleanup paths. The override application preserves agent-only scoping and removes inherited users after OCI normalization. The shipped profiles retain the three previous non-root adaptations, and the regression tests retain verifier/unrelated-task isolation and package immutability checks.

Static review only: tests and rollouts were not executed, and the reported byte-identical output on downloaded task packages was not independently reproduced.

Note: formal approval is not available for this request, so this review is posted as a comment only.

Review generated by codex. This was a full review. Request a full review with /review reset=true.

@yaoyu-33 yaoyu-33 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for picking this up. Moving the three non-root patches into the profiles keeps task names out of the shared server, and I found no blockers or risks. One note is inline.

What I checked

  • I ran main's hard-coded patches and merge_patch side by side, with the shipped YAML, for all three services. They produce the same Compose output. x-sandbox is now merged instead of replaced. That only matters if a task's own Compose file sets x-sandbox, and none of the pinned packages do.
  • user: null reaches EnvironmentConfig as None through Gym's real config loading, for both miniswe.yaml entry points and configs/terminal_bench_4.yaml. Every in-repo config that runs these tasks layers the profile's resources.yaml.
  • Test results:
    • resources_servers/terminal_bench_4/tests: 261 passed, 1 skipped.
    • tests/unit_tests/test_environment_validation.py: 45 passed.
    • Breaking any one of these makes a test fail: the shipped override blocks, the agent-only gate, the short-name lookup, the startup key check, or the missing-service check.

Other observations (no action needed here)

  • nemo_gym/sandbox/compose_config.py:522 already has adapt_non_root_sidecars, which the Harbor environment server uses to derive this same adaptation from image metadata. It wouldn't drop in as is: protein-active-learning still needs its ASSAY_STATUS patch. So it's at most a follow-up.
  • CI: the one failing unit test, tests/unit_tests/test_process_supervisor.py::test_only_detached_services_survive_harness_group_termination[True-timeout], is in the process supervisor and looks unrelated to this change.

PR hygiene (nit): AGENTS.md asks for an imperative title, e.g. refactor(terminal-bench-4): move per-task Compose service overrides into the profile config. The validation list could also include the pre-commit run --all-files result.

submission["x-sandbox"] = {"hosts": [], "resolve_environment": ["ASSAY_STATUS"]}
# Use the image's default submission user without an explicit su.
submission.pop("user", None)
overrides = self.config.compose_service_overrides.get(self.task.name.split("/")[-1], {})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resources_servers/terminal_bench_4/environment.py:288

These overrides are read only inside if self.uses_compose: (L265). An entry keyed to a manifest task that has no Compose file therefore passes the startup check (app.py:106) and is ignored without an error, so the README's "a service that the task's Compose file lacks fails the task at seed" doesn't hold for that case. Could __init__ raise when the agent role has overrides but no Compose file? It could sit next to the existing "Sidecar artifacts and hooks require Compose" check (L186-L189). Alternatively, startup could reject keys whose manifest category isn't compose. The shipped entries are all Compose tasks, so nothing is affected today.

@yaoyu-33 yaoyu-33 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving at b5eee7846. The inline note on overrides for tasks without a Compose file is non-blocking and fine as a follow-up. The one failing unit test (test_process_supervisor.py) is unrelated to this change. Thanks!

@yaoyu-33 yaoyu-33 added ready-to-merge PR is approved, current, and waiting for final CI or merge and removed needs-review PR is ready for code review and waiting on a reviewer labels Oct 28, 2026
@gwarmstrong
gwarmstrong added this pull request to the merge queue Oct 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔄 Merge queue validation started! You can track the progress here: https://github.com/NVIDIA-NeMo/Gym/actions/runs/40730741784

Merged via the queue into NVIDIA-NeMo:main with commit 5dc560d Oct 28, 2026
85 of 92 checks passed
@gwarmstrong
gwarmstrong deleted the georgea/tb4-compose-service-overrides branch October 28, 2026 17:33

This branch was previously deployed

1 inactive deployment
public — b5eee784 Deployed Oct 27, 2026 by copy-pr-bot[bot] via release / finalize / notify #7703
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:environment Individual environments, benchmarks, verifiers, and environment-specific resources servers feature New capabilities, enhancements, or enablement work ready-to-merge PR is approved, current, and waiting for final CI or merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants