Reference-harness grid: scoring convention, installed-harness support, producer fixes - #85
Open
varunursekar wants to merge 5 commits into
Open
Reference-harness grid: scoring convention, installed-harness support, producer fixes#85varunursekar wants to merge 5 commits into
varunursekar wants to merge 5 commits into
Conversation
Both harnesses ignore OPENAI_*/ANTHROPIC_*: openhands-sdk reads its own LLM_* pair, and goose reads OPENAI_HOST plus OPENAI_BASE_PATH, which it joins -- so the host must not already carry /v1 or the request lands on /v1/v1/chat/completions and the proxy 403s. The producer token is minted per run, so neither can be supplied through build.yaml agent_env; it has to be injected here. A harness that does not read these ignores them, so the rule stays unconditional. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An unqualified model group load-balances across deployments, and Responses-API encrypted reasoning is decryptable only by the deployment that produced it, so every turn after the first fails invalid_encrypted_content. Measured on swe-atlas: 8 of 8 replays failed against the bare group, 0 of 5 on azure_ai. It killed both gpt-5.6-sol cells at 2m58s under opencode as well as codex, so it is not the codex-only fault terminal-bench's instance suggested. Aliases apply after the allow-list check, so allowed_models still governs what an optimizer may ask for and a cell's label still means what it says. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
trial_rewards dropped every rewardless trial, which silently scored only the trials that survived and inflated any harness that crashed. Adopt runs/recompute.py's convention, the one that produced the pinned baselines: a harness kill scores 0, because the harness owns its install, its context management and its step budget and must pay for them exactly as a candidate does at finalization; a platform kill is dropped, because a retry cannot score a trial that never ran and zero-filling infra bakes outage luck into the number. An unrecognised exception is now a hard error rather than a quiet omission. Recovers 73 zeroes across the reference grid, worst on swe-atlas x mini-swe-agent where 28 of 150 trials were being ignored (0.0656 -> 0.0533). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A reference run swaps the seed program for a harness a practitioner could install
-- claude-code, opencode, goose, mini-swe-agent, openhands-sdk, terminus-2 -- and
changes nothing else: same dataset ref, same partition, same rounds, same
aggregation, same pinned target model. That makes the harness the only variable, so
the number stays comparable to baseline_reward and to every contestant.
Four flags the grid turned out to need:
--agent the harness to run instead of agent_import_path
--setup-timeout-multiplier opencode's nvm -> node 22 -> npm -g install is far
heavier than the seed's zero setup and overruns
harbor's default
--agent-env KEY=VALUE goose needs the proxy pointed at explicitly
--with-requirement SPEC harbor-native harnesses import their framework in
the orchestrator and harbor does not declare it, so
dspy-rlm dies on ModuleNotFoundError before the
agent starts
plus --harbor-requirement, which also relaxes the copied workspace's own harbor pin
so an override can resolve.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Greptile flagged that a rewardless trial with an unclassified exception exits the
script. The mechanism it proposed -- a qualified name like openai.RateLimitError
missing an exact match -- cannot happen: every write path goes through harbor's
ExceptionInfo.from_exception, which stores type(e).__name__, and none of the 16
distinct exception_type values across 4,586 trials on disk is dotted. The
qualified spelling it had in mind belongs to the retry config's
retry_exception_names, a different field.
The underlying risk is real, though, just via real types. Four rewardless trials
on disk carry a type in neither set, so scanning one of those rounds would abort.
Classified from harbor's own class hierarchy:
AgentAuthenticationError HARNESS -- subclasses NonZeroAgentExitCodeError; the CLI
reports no login, i.e. the harness never read a credential
surface we set, which is the defect this branch also fixes
AdapterParseError HARNESS -- dspy's own output parser gave up
UnknownApiError INFRA -- harbor's ApiError subclass for a provider error
it could not classify, like the two RateLimits
RewardFileNotFoundError INFRA -- the verifier ran and produced no reward file
CancelledError INFRA -- harbor cancelled the trial
ValueError stays in neither set on purpose: both instances on disk are harbor's
"ContextVar was created in a different Context" bug, which is platform-side, but the
name is generic enough that an agent-side ValueError would land there too. The abort
now prints the exception message so whoever hits one can classify it in a single look.
No published number moves: all 23 completed reference cells rescore byte-identical.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Four changes the reference-harness grid needed. Everything here is code and config;
the run artefacts live in the gitignored
runs/and are not included.1. Score a trial the harness killed as zero, not as absent
trial_rewardsdropped every rewardless trial, so a harness that crashed was scoredonly on the trials that survived. Now it follows
runs/recompute.py— the conventionthat produced the pinned baselines: a harness kill scores 0, a platform kill is
dropped, and an unrecognised exception is a hard error instead of a quiet omission.
This changes published numbers. It recovers 73 zeroes across the grid; the largest
single move is swe-atlas × mini-swe-agent, 0.0656 → 0.0533, where 28 of 150 trials were
being ignored.
2. Let rescore run an installed harness in place of the seed
--agentswaps the seed program for a harness a practitioner could install and changesnothing else — same dataset ref, partition, rounds, aggregation and pinned target model
— so the harness is the only variable and the number stays comparable to
baseline_reward. Four supporting flags, each added because a specific harness neededit:
--setup-timeout-multiplier(opencode's nvm → node 22 → npm -g install overrunsharbor's default),
--agent-env(goose needs the proxy pointed at explicitly),--with-requirement(harbor-native harnesses import their framework in theorchestrator, which harbor does not declare), and
--harbor-requirement.3. Pin gpt-5.x producers to one upstream deployment
An unqualified model group load-balances across deployments, and Responses-API
encrypted reasoning is decryptable only by the deployment that produced it, so every
turn after the first fails
invalid_encrypted_content. Measured on swe-atlas: 8 of 8replays failed against the bare group, 0 of 5 on
azure_ai. It killed both gpt-5.6-solcells at 2m58s under opencode as well as codex, so it is not the codex-only fault
terminal-bench's instance suggested.
Aliases apply after the allow-list check, so
allowed_modelsstill governs what anoptimizer may ask for and a cell's label still means what it says.
4. Give the producer the credential surfaces goose and openhands-sdk read
openhands-sdk reads its own
LLM_*pair and goose readsOPENAI_HOST+OPENAI_BASE_PATH, which it joins — so the host must not already carry/v1or therequest lands on
/v1/v1/chat/completionsand the proxy 403s. The producer token isminted per run, so neither can come from
build.yamlagent_env.Verification
tests/test_v05_cli.py: 21 passedbuild.yamls parse, withmodel_aliaseslanding underinference_gateway.producerrescore_candidate.pycompiles; the commit split was verified byte-identical to theworking version
🤖 Generated with Claude Code
Greptile Summary
This PR updates reference-harness rescoring and producer configuration.
Confidence Score: 4/5
The PR is not yet safe to merge because qualified infrastructure exceptions can still abort otherwise valid rescoring runs.
The current classifier compares persisted exception types directly against bare names, while existing Harbor result fixtures use qualified values such as
openai.RateLimitError; those failures therefore reach the unclassified-exception exit instead of being omitted from scoring.Files Needing Attention: harness-engineering-bench/scripts/rescore_candidate.py
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[Load benchmark build] --> B{Seed or installed agent?} B -->|Seed| C[Copy seed workspace] B -->|Installed| D[Configure Harbor agent] C --> E[Run fixed rounds and tasks] D --> E E --> F[Read trial results] F --> G{Reward present?} G -->|Yes| H[Include reward] G -->|No| I{Failure classification} I -->|Harness| J[Include zero] I -->|Platform| K[Drop trial] I -->|Unrecognized| L[Abort rescore] H --> M[Aggregate score] J --> M K --> MReviews (2): Last reviewed commit: "Classify the five failure types a rescor..." | Re-trigger Greptile