Add harbor_env — serve Harbor task directories as an OpenEnv environment - #1018
Open
thegovind wants to merge 9 commits into
Open
Add harbor_env — serve Harbor task directories as an OpenEnv environment#1018thegovind wants to merge 9 commits into
harbor_env — serve Harbor task directories as an OpenEnv environment#1018thegovind wants to merge 9 commits into
Conversation
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
A new environment,
envs/harbor_env, that runs any Harbor task directory as a Gymnasium-style OpenEnv environment.The task directory is the interface. A directory that
harbor runaccepts is served here unchanged — no conversion step, no re-authoring, no second copy of the data, and no producer-specific code in OpenEnv. That covers Terminal-Bench-lineage tasks and everything Repo2RLEnv generates from a GitHub repository, so a task set built for evaluation is also a training environment.Where this sits
Harbor and OpenEnv are not competitors — they sit at different layers, and they agree on the one contract that matters: the reward is produced inside the environment and only forwarded.
flowchart LR P["Task producers<br/>Repo2RLEnv · Terminal-Bench<br/>· hand-written"] T["Harbor task directory<br/><i>the format</i>"] H["harbor run<br/><i>batch evaluation</i>"] E["envs/harbor_env<br/><b>NEW</b> — episode loop"] TR["Trainer / RL loop<br/>reset · step · state"] P -->|emit| T T --> H T -->|"served unchanged"| E E --> TR style E fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px style T fill:#e3f2fd,stroke:#1565c0tests/test.sh→/logs/verifierObservation.reward, produced inside the envharbor_envis the bridge, and it generalizes the existingenvs/tbench2_env/pattern. The one real behavioural difference: tbench2 derives pass/fail from the verifier's exit code, while Harbor rewards are graded floats, soharbor_envreads the value the verifier wrote.An episode
sequenceDiagram participant TR as Trainer <br/>(infrastructure) participant E as HarborEnvironment participant S as Sandbox <br/>(local or docker) participant V as tests/test.sh TR->>E: reset(task_id="fix-sum-bug") E->>S: boot backend, seed working directory E-->>TR: Observation(instruction=instruction.md) loop agent works TR->>E: step(exec / read / write) E->>S: run in the working directory S-->>E: output end TR->>E: step(evaluate) E->>S: clear /logs/verifier, stage tests/ -> /tests E->>V: bash /tests/test.sh V-->>S: reward.json / reward.txt E-->>TR: Observation(reward=0.83, done=True) Note over E,V: reward.json first, then reward.txt —<br/>exactly Harbor's precedence Note over TR,E: evaluate + solve are infrastructure-only,<br/>never in the agent's action spaceInvariants held
reset/step/statestay on the infrastructure side.evaluateandsolveare orchestration controls, not agent actions — an agent that could grade on demand could end its own episode, and one that couldsolvecould hand itself the answer.harbor_envforwards whattests/test.shwrote and never computes a reward. If the verifier wrote no reward file, the result isreward=Noneplus an explicit error — not a0.0. A fabricated zero is indistinguishable from a genuine failure and would poison a training run.client.pyimports nothing fromserver/.readandwritego throughresolve_within(), confined to the working directory, so/testsand/solutionare unreachable./logs/verifieris wiped immediately before the verifier runs, so a reward file planted duringexeccannot survive into the score.Two execution modes
flowchart TD A["reset(task_id)"] --> B{"Where is the task's<br/>starting state?"} B -->|"ships environment/ seed files<br/><i>self-contained</i>"| C["local mode OK<br/><i>subprocesses, no Docker —<br/>works on HF Spaces</i>"] B -->|"Dockerfile / compose /<br/>docker_image"| D{"HARBOR_MODE"} D -->|docker| E["run inside the task's<br/>own image"] D -->|local| F["refuse with an actionable message<br/><i>rather than grading an empty directory</i>"] style C fill:#e8f5e9,stroke:#2e7d32 style E fill:#e8f5e9,stroke:#2e7d32 style F fill:#ffebee,stroke:#c62828localmode is documented as a filesystem boundary, not a security boundary —execruns as the server's own user with the server's own environment. Serve task sets you trust there; usedockerfor anything else.Verification
The interop claim is the whole point of this PR, so it was measured rather than asserted.
The bundled
examples/tasks/fix-sum-bugtask is written to run under every runtime (it prefers$HARBOR_*variables and falls back to Harbor's absolute paths). It grades identically in all three:solution/solve.shharbor run -a nop/-a oracle(harbor 0.20.0)harbor_envlocalmodeharbor_envdockermodeReproduce row one with
harbor run -p envs/harbor_env/examples/tasks/fix-sum-bug -a nop, and the others withexamples/validate_taskset.py.Separately, a real Repo2RLEnv-emitted
pr_runtimetask — produced by repo2rlenv's own emitter, soversion = "1.0"rather than Harbor'sschema_version, plus[metadata.repo2env],WORKDIR /workspace, and atests/test.shwriting/logs/verifier/reward.txt— scored 0.0 for a no-op agent and 1.0 for the oracle under bothharbor runandharbor_envdocker mode, withreward-details.jsonsurfacing intact asobservation.info["reward_details"].Note
High Risk
New environment runs attacker-controlled shell in local or Docker sandboxes and forwards training rewards; mis-grading or weak isolation could affect RL data and host security.
Overview
Introduces
envs/harbor_env, a new OpenEnv environment that serves Harbor task directories unchanged (including Repo2RLEnv output) over the standard reset/step API, with a FastAPI/WebSocket server,HarborEnvclient, and wire types forexec/read/writeplus infrastructure-onlyevaluateandsolve.Execution is split between
docker(task images, policy enforcement) andlocal(subprocesses under a per-episode tree for Spaces); local mode refuses tasks that need images or policies it cannot enforce. Rewards are read from verifier artifacts (reward.jsonthenreward.txt, withreward-details.jsonininfo); missing files yieldreward=None, not0.0. Sandboxing limits agent I/O to the workdir, stages/testsonly at verify time, and clears verifier logs before grading.Also adds a bundled
fix-sum-bugexample task,quickstart/validate_tasksetscripts, Docker image defaults, and docs entries (environments/harbor, catalog card, toctree).Reviewed by Cursor Bugbot for commit 5079a77. Bugbot is set up for automated code reviews on this repo. Configure here.