Skip to content

Commit c8b6871

Browse files
Merge pull request #55 from scaleapi/fix/tau3-trial-resilience
feat: let a build configure its outer optimizer trial's harbor flags
2 parents 2aff9f4 + 5f63149 commit c8b6871

6 files changed

Lines changed: 111 additions & 2 deletions

File tree

harness-engineering-bench/tau3/baseline/build.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ model: fireworks_ai/deepseek-v4-flash
5656
environment_name: ${inner_env:-modal}
5757
# inner eval sandboxes share a dedicated Modal app instead of the __harbor__ default
5858
extra_harbor_args: ["--ek", "app_name=harness-engineering-bench", "--ek", "sandbox_idle_timeout_secs=3600"]
59+
# NOTE: tau3's optimizer trial reliably dies at ~38-40 min with grpclib
60+
# StreamTerminatedError ("Connection lost"). Four live experiments (default
61+
# DinD, --ek modal_vm_runtime=true, --ek modal_sandbox_v2=true, and
62+
# --max-retries 1) all failed identically, so no `optimizer_harbor_args` value
63+
# is set here: none of them is a fix, and a config value that claims to be one
64+
# is worse than nothing. Tracked upstream; see the PR that added this field.
5965
harbor_python_version: "3.12"
6066
n_attempts: 1
6167
max_retries: 1

vero/src/vero/harbor/build/config.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ class _HarborEvaluationFields(StrictModel):
164164
expose_attempt_detail: Report per-attempt detail, not just the aggregate.
165165
extra_harbor_args: Extra flags for the evaluation sub-run. Rejected if
166166
they override a flag the compiler controls.
167+
optimizer_harbor_args: Extra flags for the outer harbor run that hosts
168+
the optimizer trial. Distinct from extra_harbor_args, which tunes
169+
the nested evaluation sub-run. Rejected if they override a flag
170+
`vero harbor run` controls.
167171
task_agent_timeout_seconds: Wall clock declared for the target agent.
168172
Grouped here rather than with the other timeouts because it bounds
169173
the target, which only a Harbor backend runs.
@@ -198,6 +202,13 @@ class _HarborEvaluationFields(StrictModel):
198202
feedback_max_bytes: int = Field(default=3000, ge=0)
199203
expose_attempt_detail: bool = False
200204
extra_harbor_args: list[str] = Field(default_factory=list)
205+
# Extra flags for the OUTER `harbor run` that hosts the optimizer trial
206+
# (`vero harbor run`). Distinct from `extra_harbor_args`: that one tunes the
207+
# nested eval sub-run, this one tunes the environment the optimizer itself
208+
# lives in. A build declares here what its optimizer trial needs to survive,
209+
# e.g. `--ek modal_vm_runtime=true` for a long trial whose teardown keeps
210+
# losing the DinD gRPC stream.
211+
optimizer_harbor_args: list[str] = Field(default_factory=list)
201212
task_agent_timeout_seconds: float = Field(default=600.0, gt=0)
202213
task_environment: dict[str, str] = Field(default_factory=dict)
203214
task_services_use_upstream: bool = False
@@ -239,6 +250,22 @@ def validate_extra_harbor_args(cls, value: list[str]) -> list[str]:
239250
)
240251
return value
241252

253+
@field_validator("optimizer_harbor_args")
254+
@classmethod
255+
def validate_optimizer_harbor_args(cls, value: list[str]) -> list[str]:
256+
# `vero harbor run` owns the outer command's task, agent, environment and
257+
# model; a build must not fight the CLI over them.
258+
controlled = {"-a", "-e", "-m", "-p"}
259+
conflicts = [
260+
argument for argument in value if argument.split("=", 1)[0] in controlled
261+
]
262+
if conflicts:
263+
raise ValueError(
264+
"optimizer_harbor_args override controlled flags: "
265+
+ ", ".join(conflicts)
266+
)
267+
return value
268+
242269

243270
# The fields a command build must not set, derived from the class above so the
244271
# two cannot drift. Setting one is a mistake worth reporting: it would be

vero/src/vero/harbor/cli.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,9 @@ def run_command(config_path, agent, model, environment, params, env_file, extra)
611611
for key in sorted(config.agent_env):
612612
command.extend(["--ae", f"{key}={config.agent_env[key]}"])
613613
command.extend(_opencode_gateway_args(agent, model, task))
614+
# Build-declared outer-trial flags first, so a command-line arg can still
615+
# override them (harbor's `--ek` takes the last value for a key).
616+
command.extend(config.optimizer_harbor_args)
614617
command.extend(extra)
615618
click.echo(shlex.join(command))
616619
completed = subprocess.run(

vero/tests/test_v05_cli.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,3 +496,62 @@ def test_preflight_does_not_block_on_inconclusive_upstream_failures(monkeypatch)
496496
monkeypatch.delenv("OPENAI_API_KEY")
497497
harbor_cli._preflight_models(_Build(_Gateway(["a"], ["b"])))
498498
harbor_cli._preflight_models(_Build(None))
499+
500+
501+
def test_harbor_run_forwards_build_declared_optimizer_args(tmp_path, monkeypatch):
502+
"""`optimizer_harbor_args` tunes the OUTER trial, `extra_harbor_args` the nested eval.
503+
504+
Regression guard for the tau3 teardown failure: the build declared
505+
`--ek modal_vm_runtime=true` and it has to reach the `harbor run` that hosts
506+
the optimizer, not the `harbor run` that scores a candidate.
507+
"""
508+
from vero.harbor import build as harbor_build
509+
from vero.harbor import cli as harbor_cli
510+
511+
config_path = tmp_path / "build.yaml"
512+
config_path.write_text("name: org/task\n", encoding="utf-8")
513+
514+
class _Config:
515+
harbor_requirement = "harbor[modal]==0.20.0"
516+
agent_env: dict[str, str] = {}
517+
optimizer_harbor_args = ["--ek", "modal_vm_runtime=true"]
518+
extra_harbor_args = ["--ek", "app_name=nested-only"]
519+
520+
monkeypatch.setattr(harbor_build, "load_harbor_build_config", lambda *a, **k: _Config())
521+
monkeypatch.setattr(harbor_build, "compile_harbor_task", lambda config, output: output)
522+
monkeypatch.setattr(harbor_cli.shutil, "which", lambda name: "/usr/bin/uvx")
523+
monkeypatch.setattr(
524+
harbor_cli, "_compiled_run_environment", lambda task, overrides: {}
525+
)
526+
527+
recorded: list[list[str]] = []
528+
529+
def _record(command, env=None):
530+
recorded.append(command)
531+
return subprocess.CompletedProcess(command, 0)
532+
533+
monkeypatch.setattr(harbor_cli.subprocess, "run", _record)
534+
535+
result = CliRunner().invoke(
536+
main,
537+
[
538+
"harbor",
539+
"run",
540+
"--config",
541+
str(config_path),
542+
"--agent",
543+
"codex",
544+
"--model",
545+
"gpt-5.3-codex",
546+
"--yes",
547+
],
548+
)
549+
550+
assert result.exit_code == 0, result.output
551+
assert len(recorded) == 1
552+
command = recorded[0]
553+
assert "modal_vm_runtime=true" in command
554+
# The nested-eval flags stay out of the outer command.
555+
assert "app_name=nested-only" not in command
556+
# Build-declared flags come first so a command-line `--ek` can override them.
557+
assert command.index("modal_vm_runtime=true") < command.index("--yes")

vero/tests/test_v05_harbor_build.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,12 @@ def test_build_config_requires_pins_and_valid_partition_references(tmp_path):
407407
_config(tmp_path / "unknown", selection_partition="missing")
408408
with pytest.raises(ValidationError, match="controlled flags"):
409409
_config(tmp_path / "flags", extra_harbor_args=["--jobs-dir=/forged"])
410+
with pytest.raises(ValidationError, match="controlled flags"):
411+
_config(tmp_path / "outer-flags", optimizer_harbor_args=["-a", "forged"])
412+
assert _config(
413+
tmp_path / "outer-ek",
414+
optimizer_harbor_args=["--ek", "modal_vm_runtime=true"],
415+
).optimizer_harbor_args == ["--ek", "modal_vm_runtime=true"]
410416
with pytest.raises(ValidationError, match="explicit version"):
411417
_config(tmp_path / "source", task_source="org/unversioned")
412418

vero/tests/test_v05_harbor_http.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,11 @@ def test_harbor_run_uses_current_python_and_pinned_harbor_extra(tmp_path, monkey
260260

261261
config_path = tmp_path / "build.yaml"
262262
config_path.write_text("task_name: unused\n")
263-
config = SimpleNamespace(harbor_requirement="harbor[modal]==0.20.0", agent_env={})
263+
config = SimpleNamespace(
264+
harbor_requirement="harbor[modal]==0.20.0",
265+
agent_env={},
266+
optimizer_harbor_args=[],
267+
)
264268
observed = {}
265269

266270
def compile_task(_config, output):
@@ -313,7 +317,11 @@ def test_harbor_run_env_file_secrets_reach_subprocess_not_command_line(
313317
config_path.write_text("task_name: unused\n")
314318
env_file = tmp_path / "secrets.env"
315319
env_file.write_text("MODAL_TOKEN_ID=mt-id\nMODAL_TOKEN_SECRET=mt-secret\n")
316-
config = SimpleNamespace(harbor_requirement="harbor[modal]==0.20.0", agent_env={})
320+
config = SimpleNamespace(
321+
harbor_requirement="harbor[modal]==0.20.0",
322+
agent_env={},
323+
optimizer_harbor_args=[],
324+
)
317325
observed = {}
318326

319327
def compile_task(_config, output):

0 commit comments

Comments
 (0)