Skip to content

fix: bundle harness eval flat-zero fixes (taxonomy + reasoning.effort + tau3 retries) - #56

Closed
shehabyasser-scale wants to merge 16 commits into
feat/swe-bench-pro-baseline-scaffoldfrom
fix/harness-flatzero-bundle
Closed

fix: bundle harness eval flat-zero fixes (taxonomy + reasoning.effort + tau3 retries)#56
shehabyasser-scale wants to merge 16 commits into
feat/swe-bench-pro-baseline-scaffoldfrom
fix/harness-flatzero-bundle

Conversation

@shehabyasser-scale

@shehabyasser-scale shehabyasser-scale commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

What

A single branch stacking the three harness eval fixes so both benchmarks can be re-run with all of them applied at once:

Commits are cherry-picked from those PRs (disjoint files, no conflicts), based on feat/swe-bench-pro-baseline-scaffold.

Purpose

One branch to re-run tau3 and swe-atlas-qna end to end with the full fix set. The individual PRs (#53, #54, #55) remain open for granular review.

Caveats for the rerun

🤖 Generated with Claude Code

Greptile Summary

This PR stacks three harness eval fixes from PRs #53, #54, and #55 to enable a clean combined re-run of tau3 and swe-atlas-qna. The individual changes are well-scoped and address real problems (a flat-zero masking bug, HTTP 400s from unconditional reasoning.effort, and transient Modal stream drops).

Confidence Score: 4/5

Safe to merge for the re-run; the three fixes are independently correct and the taxonomy change ships with good test coverage.

The taxonomy addition resolves the flat-zero masking problem with clear tests, the reasoning guard correctly prevents HTTP 400s on non-reasoning models, and the retry bump is a straightforward config change. Two minor concerns exist: the bare sandbox keyword in the new regex is the only term in the entry not anchored to Modal-specific context, risking occasional misclassification of task failures in non-Modal harnesses; and the model-detection block is copied verbatim into five agent files, making future model-list updates error-prone. Neither concern blocks the intended re-run.

Files Needing Attention: vero/src/vero/evaluation/error_taxonomy.py — review the sandbox keyword breadth before this taxonomy is used with harnesses that don't run in Modal.

Important Files Changed

Filename Overview
vero/src/vero/evaluation/error_taxonomy.py New SIGNAL_PATTERNS entry classifies Modal sandbox/container/tests-dir errors as TRANSIENT_INFRA. The bare sandbox keyword is the broadest term and could match non-infrastructure errors in other harnesses, but the risk is low in practice.
vero/tests/test_v05_error_taxonomy.py Two new test functions cover the added taxonomy patterns with concrete Modal error message fixtures and a regression guard for the flat-zero scenario; coverage is thorough.
harness-engineering-bench/tau3/baseline/target/src/tau3_agent/agent.py Removes always-on reasoning.effort and adds a model-name prefix guard. Same pattern duplicated across all five agent files; logic is correct for the listed prefixes.
harness-engineering-bench/gaia/baseline/target/src/gaia_agent/agent.py Identical reasoning-guard fix as tau3_agent; no additional issues.
harness-engineering-bench/officeqa/baseline/target/src/officeqa_agent/agent.py Identical reasoning-guard fix; no additional issues.
harness-engineering-bench/swe-atlas-qna/baseline/target/src/atlas_agent/agent.py Identical reasoning-guard fix but with effort: high (versus medium in the others); correct per the original value for this agent.
harness-engineering-bench/swe-bench-pro/baseline/target/src/swebench_pro_agent/agent.py Identical reasoning-guard fix with effort: high; no additional issues.
harness-engineering-bench/tau3/baseline/build.yaml max_retries raised from 1 to 3; straightforward configuration change to survive transient Modal stream drops.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Agent receives model name] --> B{Reasoning-capable model?\ngpt-5 / o1 / o3 / o4 / codex}
    B -- Yes --> C[Add reasoning.effort to request]
    B -- No --> D[Omit reasoning.effort\ne.g. gpt-4o avoids HTTP 400]
    C --> E[client.responses.create]
    D --> E

    F[Exception signal from harness run] --> G[classify_signal]
    G --> H{Budget pattern?}
    H -- Yes --> I[INFERENCE_BUDGET_EXHAUSTED\nTerminating]
    H -- No --> J{Auth pattern?}
    J -- Yes --> K[AUTH_FAILURE\nTerminating]
    J -- No --> L{Transient pattern?\nrate-limit OR sandbox/streamterminated\naddtestsdirerror/fetchspec added PR53}
    L -- Yes --> M[TRANSIENT_INFRA\nRetryable - excluded from aggregate]
    L -- No --> N[TASK_FAILURE\nInformative sample - scored at 0]
Loading

Fix All in Cursor Fix All in Claude Code Fix All in Codex

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
vero/src/vero/evaluation/error_taxonomy.py:170-176
**Bare `sandbox` term is over-broad in a global taxonomy**

`sandbox` alone will match any exception message or type name that contains the word across all harnesses, not just Modal-specific ones. If a task in gaia or officeqa involves agent code that raises an error from a library with "sandbox" in its name or message (e.g., a Python security sandbox, a custom execution environment, any tool named `*Sandbox*`), the case would silently be reclassified from `TASK_FAILURE` to `TRANSIENT_INFRA` — excluded from the aggregate and counted toward invalidity instead of being scored. The other terms in this entry (`streamterminated`, `addtestsdirerror`, `loading.?container`, `fetchspec`) are Modal-specific enough to be safe. Consider anchoring the bare `sandbox` match more tightly, e.g. `modal.*sandbox|sandbox.*unavailable|sandbox.*not.?found`, to reduce false-positive risk for harnesses that don't use Modal sandboxes.

### Issue 2 of 2
harness-engineering-bench/tau3/baseline/target/src/tau3_agent/agent.py:301-304
**Model-detection logic duplicated across five agents**

The identical three-line block (`_model = …`, `startswith(…)`, `request["reasoning"] = …`) is copy-pasted into `gaia_agent`, `officeqa_agent`, `atlas_agent`, `swebench_pro_agent`, and `tau3_agent`. When the set of reasoning-capable models changes (e.g., a new `o5` or `gpt-6` prefix), all five files must be updated in sync. A shared helper or constant in a common `base_agent` module would make this a single-point update.

Reviews (1): Last reviewed commit: "fix: raise tau3 optimizer trial max_retr..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

varunursekar and others added 16 commits July 23, 2026 23:41
Bring the benchmark harness with each benchmark as a top-level sibling of
gaia/ (ale-bench, officeqa, swe-atlas-qna, tau3), flattening the former
candidates/ grouping.
The floor gates a ship on a validation comparison while gaia's reward is on
the test partition (different distributions), so keep it opt-in / off. Now
that the harbor default is false this is explicit-for-clarity.
Now that the sidecar image pre-warms the harness uv cache, the inner eval
runs as the unprivileged harness user again, so the candidate harness cannot
read the held-out records, budgets, or admin token.
Move each benchmark to harbor 0.20.0 in lockstep so the eval resolves:
build.yaml harbor_requirement (the evaluator's --with harbor[modal]) and
target/pyproject.toml (the candidate's own harbor dep) must match, else
`uv run --project <target> --with harbor[modal]==0.20.0` is unsatisfiable.
uv.lock regenerated with `uv lock` (not hand-edited). Covers gaia,
officeqa, swe-atlas-qna, tau3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Follow-up to the pr2 rename: instructions, READMEs, and the ale-bench
reference solution now teach `evals run/status/result/submit` and the
.evals/tasks + .evals/results paths; baseline gitignores cover .evals/.
Compiled trees are build outputs (not committed) and pick this up on rebuild.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All four vero-compiled benchmarks pass --ek app_name=harness-engineering-bench
so their Modal sandboxes are grouped under one app instead of __harbor__.
Docker inner environments ignore the kwarg.
The task's verifier runs inside the Modal task container and templates
EVAL_BASE_URL from OPENAI_API_BASE, unreachable-from-Modal gateway URLs
aside. Enable task_services_use_upstream so the judge gets the real
upstream on OPENAI_*, and point the baseline agent at the metered
gateway via VERO_AGENT_INFERENCE_* (falling back to OPENAI_* locally).
The Modal app-name commit added a second extra_harbor_args key; YAML
last-key-wins silently dropped --no-force-build, which would have
force-built the guard Dockerfile instead of pulling the prebuilt
corpus image.
Killing the outer harbor process leaves the compose topology and any
in-flight Modal sandboxes running (each layer's cleanup lives in the
layer above). Cap sandbox idle lifetime at 1h via --ek, and add
scripts/cleanup_orphans.sh to tear down task__* containers and
terminate sandboxes in the dedicated Modal app.
WIP scaffold: a working agent + build/config skeleton for a SWE-bench-Pro
optimization target, mirroring the gaia baseline layout. Two things are
stubbed and must be completed before it runs: (1) the task_source digest in
baseline/build.yaml is a clearly-marked placeholder that must be pinned to the
real SWE-bench-Pro Harbor task package, and (2) the partitions/ files are empty
placeholders that must be regenerated from the real task list via
scripts/partition_swe_bench_pro.py. The agent wraps responses.create in a
retry-with-backoff helper from the start (the unguarded call is what scored the
gaia baseline 0.0). See harness-engineering-bench/swe-bench-pro/README.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The harbor backend's error taxonomy records any unrecognized case failure as
TASK_FAILURE: an informative, scoreable sample at the failure value with status
SUCCESS. That is right for a candidate that crashes on its own, but Modal
sandbox lifecycle failures and a missing held-out tests fixture are
infrastructure the candidate did not cause.

Seen on a swe-atlas-qna run (2026-07-24): all 396 cases returned status=success,
error_category=task_failure, score=0.0. Terminal exceptions were AddTestsDirError
x144, Modal sandbox NotFound x125, RuntimeError x67, BadRequestError x60.
Classified as task failures, the aggregate reported error_rate 0.0 and objective
feasible at 0.0, so a fully broken environment looked like a real, shippable
zero and the optimizer ran with no gradient (baseline and every candidate 0.0).

Add the harness/Modal environment-loss signals (sandbox lifecycle,
AddTestsDirError / "failed to add tests directory", container fetch failures,
StreamTerminatedError) to the TRANSIENT_INFRA patterns. Those cases are now
excluded from the aggregate and counted toward invalidity, so a collapsed
environment surfaces as an invalid run instead of a silent zero. A candidate's
own bug (ValueError, KeyError, no answer) is still a task failure, unchanged.
Covered by two new tests; existing behavior asserted unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Each harness-engineering-bench target agent builds its Responses API request
with a hard-coded "reasoning": {"effort": ...} on every call, regardless of the
configured model. Reasoning models (gpt-5.x, o-series, *-codex) accept it, but
gpt-4o and other non-reasoning models reject the whole request with HTTP 400:
"Unsupported parameter: 'reasoning.effort' is not supported with this model".

On a swe-atlas-qna run pointed at a gpt-4o agent model this produced a wall of
400s (60 cases died with BadRequestError). The gaia and tau3 configs point their
agent model at gpt-4o in the same setup, so they share the latent bug.

Gate reasoning.effort on the model family: send it only when the resolved model
is a reasoning model (gpt-5.x / o1 / o3 / o4 / *-codex), otherwise omit it. Each
agent keeps its own effort level (high for atlas and swe-bench-pro, medium for
gaia, officeqa and tau3). No behavior change for reasoning models; gpt-4o stops
400ing. Applied uniformly to all five bench agents.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…l drops

A tau3 optimizer run (2026-07-24) died about 25 minutes in when the Modal
command-router gRPC stream dropped mid-optimization (grpclib
StreamTerminatedError: Connection lost). With max_retries: 1 the whole trial
errored and nothing was scored, even though the drop was transient
infrastructure and the run had already committed candidates.

Raise max_retries from 1 to 3 so a transient stream drop retries the trial
instead of failing the run. This matches infrastructure_max_attempts: 3 already
set for per-case infra. A deeper fix (running the eval under the Modal VM runtime
to remove the single host-networking gRPC stream SPOF) is noted for follow-up
but not applied here, since it needs validation against harbor 0.20.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment on lines +170 to +176
r"sandbox|streamterminated|"
r"failed.?to.?add.?tests.?directory|addtestsdirerror|"
r"loading.?container|fetchspec",
re.IGNORECASE,
),
ErrorCategory.TRANSIENT_INFRA,
),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Bare sandbox term is over-broad in a global taxonomy

sandbox alone will match any exception message or type name that contains the word across all harnesses, not just Modal-specific ones. If a task in gaia or officeqa involves agent code that raises an error from a library with "sandbox" in its name or message (e.g., a Python security sandbox, a custom execution environment, any tool named *Sandbox*), the case would silently be reclassified from TASK_FAILURE to TRANSIENT_INFRA — excluded from the aggregate and counted toward invalidity instead of being scored. The other terms in this entry (streamterminated, addtestsdirerror, loading.?container, fetchspec) are Modal-specific enough to be safe. Consider anchoring the bare sandbox match more tightly, e.g. modal.*sandbox|sandbox.*unavailable|sandbox.*not.?found, to reduce false-positive risk for harnesses that don't use Modal sandboxes.

Prompt To Fix With AI
This is a comment left during a code review.
Path: vero/src/vero/evaluation/error_taxonomy.py
Line: 170-176

Comment:
**Bare `sandbox` term is over-broad in a global taxonomy**

`sandbox` alone will match any exception message or type name that contains the word across all harnesses, not just Modal-specific ones. If a task in gaia or officeqa involves agent code that raises an error from a library with "sandbox" in its name or message (e.g., a Python security sandbox, a custom execution environment, any tool named `*Sandbox*`), the case would silently be reclassified from `TASK_FAILURE` to `TRANSIENT_INFRA` — excluded from the aggregate and counted toward invalidity instead of being scored. The other terms in this entry (`streamterminated`, `addtestsdirerror`, `loading.?container`, `fetchspec`) are Modal-specific enough to be safe. Consider anchoring the bare `sandbox` match more tightly, e.g. `modal.*sandbox|sandbox.*unavailable|sandbox.*not.?found`, to reduce false-positive risk for harnesses that don't use Modal sandboxes.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Cursor Fix in Claude Code Fix in Codex

@shehabyasser-scale

Copy link
Copy Markdown
Collaborator Author

This bundle is now stale — superseded by the PR set below. Recommend closing it once the individual PRs are reviewed.

It carries #53 + #54 + the original #55, and that third one has since been proven wrong (max_retries is the nested per-case retry, not the outer optimizer trial, which is where the stream actually drops). #55 has been re-scoped, and the investigation it enabled found two further root causes that were not in this bundle at all.

Current state, all based on feat/swe-bench-pro-baseline-scaffold:

PR what status
#53 classify Modal sandbox / tests-dir loss as transient_infra validated live 2026-07-25
#54 send reasoning.effort only to models that support it now load-bearing (gpt-4o is the only usable eval model); live A/B in flight
#55 optimizer_harbor_args → tau3 --ek modal_vm_runtime=true re-scoped; live A/B in flight
#57 scheme-less WANDB_BASE_URL + record swallowed sink failures root cause reproduced at $0
#58 swe-atlas-qna → gpt-4o, off the undeployed model model half solid; infra half under test
#59 preflight allow-listed models before launching a trial verified live against the endpoint
#60 new UPSTREAM_MODEL_UNAVAILABLE category (stacked on #53) unit-tested against the run's literal strings

The two things this bundle was built without knowing:

  1. gpt-5.4-mini-2026-03-17 is not deployed on the configured Azure resource. Only gpt-5.3-codex and gpt-4o answer. 145 of swe-atlas-qna's 469 cases died on 404 DeploymentNotFound and were recorded as candidate task failures. gaia, officeqa and tau3 still point at it.
  2. WANDB_BASE_URL was missing its scheme, so wandb.init() raised before any network call and every run's reporting was silently disabled.

Neither was visible from a diff, and both were cheap to find once the exported session.tar.gz was read instead of result.json.

@shehabyasser-scale
shehabyasser-scale force-pushed the feat/swe-bench-pro-baseline-scaffold branch from ccc7d07 to ec708e9 Compare July 26, 2026 06:28
@shehabyasser-scale

Copy link
Copy Markdown
Collaborator Author

Closing as superseded. This was a rollup of #53 + #54 + a tau3 max_retries bump. #53 is restacked and open on its own; #54 is restacked and narrowed to the two agents that still lack a reasoning-effort gate; the max_retries bump was the wrong layer and was reverted out of #55. Nothing here is left unrepresented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants