Repository navigation
Examples: five Harbor benchmarks with baselines and their papers' methods - #106
Open
iamziyuzhao wants to merge 3 commits into
Open
iamziyuzhao wants to merge 3 commits into
iamziyuzhao wants to merge 3 commits into
Conversation
…hods Terminal-Bench 2.0, SWE-bench Verified, AlgoTune, Terminal-Bench-Science and LAB-Bench FigQA through Harbor, each a benchmark file (the registry's task set, locked), a baseline per profile (Codex with GPT-5.6-Luna on a ChatGPT login, Claude Code with Claude Haiku 5.5 on a Claude subscription) and the method whose paper's protocol fits it: the AHE Adapter on Terminal-Bench 2.0 in the AHE paper's in-sample protocol, trained on each task's rollouts #1 and #2 and tested on #3 and #4; its final adapter, frozen, on SWE-bench Verified and Terminal-Bench-Science against AHE's seed; SkillOpt in its paper's protocol on AlgoTune, a trial scored 1 - 1/speedup so that the mean gives AlgoTune's harmonic mean, and on LAB-Bench FigQA, whose download is patched: the published tasks save the shuffle's seed where the agent reads it, which gives the answer away. examples/README.md says what a machine needs and lists every run with its trials, to be handed out; tests hold the protocols to the committed files. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FcJCJanVqQuJyChDevJNYP
…AB's verifier and figures, tests) The post-PR audit of #106 found no P1; its three P2s and its P2 question, fixed: - AlgoTune's SkillOpt counted every rollout a failure: a trial's score, 1 - 1/speedup, never reaches SkillOpt's success_score of 1.0, so its analysts and slow update saw failures only. success_score is now 0.000001: a solver faster than the reference, as the verifier's own test has it. - SkillOpt's Codex trace summary, on by default, describes SkillOpt's own harness (task.md, SKILL.md, <answer>) and told the analyst that every Harbor rollout gave no answer: codex_trace_to_optimizer: false in the SkillOpt configs. - tests/core/test_harbor_examples.py now holds the configs to training and validation rows disjoint from the test's, the smoke's rows apart from the run's, the learners sandboxed, web search off, and SkillOpt's success and trace settings, and loads every config with no skip (neither tasks.jsonl nor skillopt is needed): each of 12 broken copies fails it. - LAB-Bench's split is by question, and FigQA asks up to three questions about a figure: 25 of the 127 test questions share a figure with a training question. utils/rows/test_new_figures.txt (written by utils/figures.py) lists the other 102 for a second score from the same trials. And its P3s. LAB-Bench's verifier ran /app/setup.py, the agent's to rewrite, when the mapping was missing: the patch (now patches.py:patch_tasks) removes that fallback too, re-locked from a fresh download. The SWE oracle command gets its own run name. The final adapter's export goes to a fresh git-ignored folder per profile. The claims the audit checked against the papers (Meta-Harness's leaderboard figures, AHE's rollback and efforts, RRSI's trials, GEPA's splits, NPUEval's score, SkillOpt's meta skill) and the trial counts are corrected. The READMEs say how Terminal-Bench 2.0's images are pulled, how infra trials count, and what the learners read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FcJCJanVqQuJyChDevJNYP
…eval `hermit eval --adapter final` after `hermit train` misses the trial cache: the training run's test rewrites the final adapter's card with its results (a new commit, the tag moved), so the eval the README gave would run the 102 questions again (as it did on the smoke's two rows). utils/figures.py now takes the score on the 102 rows from an eval's results.jsonl, as `hermit eval` takes a mean (infra trials left out and counted, rows it did not run counted), and the README gives that command for the three arms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FcJCJanVqQuJyChDevJNYP
This branch has not been deployed
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.
Change
#105, this PR's base, makes a Harbor task set the one way a benchmark enters Hermit, but packages no benchmark on it.
This PR adds five, each ready to hand to someone with a Docker host: the registry's task set in a
utils/benchmark.yaml(locked inutils/dataset.lock), a baseline config, and the method whose paper's protocol fitsthe benchmark, in that protocol. Nothing under
hermit/changes. The way in isexamples/README.md#harbor-benchmarks: what a machine needs (Docker,
bubblewrap, Harbor 0.25.0 in its own venv, the CLI's sign-in), the commands, and a run sheet of every run with its
trials, each of which can go to another person.
terminal_bench_2_0swebench_verifiedalgotuneterminal_bench_sciencelabbenchEvery config comes twice: Codex with GPT-5.6-Luna on a ChatGPT login and Claude Code with Claude Haiku 5.5 on a Claude
subscription, both at medium effort, acting and learning. Each README says why its method, with the paper's numbers,
compares its protocol with the paper's row by row, and has an empty results table.
Decisions:
hermit eval --adapter none,on exactly the rows the method's final adapter is tested on, in the same trial cache; the method's starting point
(
--adapter root: AHE's seed, SkillOpt's empty skill) is tested on them too, so that what the start gives and whatthe search adds are read apart.
tests/core/test_harbor_examples.pyholds the configs to it.iterations, the best by pass@1: in sample, its §4.1). The rows are
<task>#1to#4: the training steps run feat(tasks): package OfficeQA Pro paired GLM evaluation #1 andfeat(evolvers): GEPA and SkillOpt as built-in Evolvers, with the SkillOpt paper's OfficeQA setting #2, every adapter is tested on feat(tasks/OfficeQA): OfficeQA Pro as a harnessadapter Environment (stacked on #2) #3 and examples: a folder per method, tasks shared under examples/tasks (old folders kept) #4, which no step ran, so the trial cache never hands a test a training trial;
the paper's own in-sample number is the run's
best_ever.json. An hour a task, as the paper (the tasks' own limitsare 600-12,000 s). The rollback is the port's (
rollback: auto: an edit the next step judges HARMFUL), where thepaper's text reverts the edits whose predicted fixes do not materialize; the README's protocol table says so.
change
/testbed. With no adapter Codex answeredpsf__requests-1142in text and changed nothing (score 0); withAHE's seed, whose
ADAPTER.mdsays to edit files and finish the work, it fixed it. Kept as published, the numberscompare with Harbor's; the seed is the arm the transfer is read against (its README, Known limits).
utils/judge.py): the mean m of those scores is 1 - 1/H for AlgoTune'sharmonic mean H, so the Trainer's, SkillOpt's gate's and
hermit eval's means move with AlgoTune's own score.SkillOpt's gate is its soft metric (a speedup has no pass); the benchmark file gives the containers 64 GB (the
reference's timing was killed at the tasks' 16 GB), thread pools of the task's 8 CPUs, no core files, and the
verifier 7,200 s, a verifier timeout being the agent's result (
verifier_timeout: agent). A success, by whichSkillOpt's analysts and its slow update sort the rollouts, is a solver faster than the reference, as the verifier's
own test has it (
success_score: 0.000001); at SkillOpt's default of 1.0 no speedup would count, and every rolloutwent to the failure analyst.
utils/patches.py, run by prepare on every download and recorded in thelock): as published, each container saves the shuffle's seed in
/app/.letter_mapping.json, where the agent readsit, and the right choice is first before the shuffle, so replaying the shuffle gives the answer, in all 181 tasks.
The patch drops the seed (the verifier reads only the letters), and removes the verifier's fallback that runs
/app/setup.py, a file the agent can rewrite, when the mapping is missing (the mapping is always written beforethe agent starts: a missing one now scores 0); Harbor's oracle still scores 1. It changes no task unless it knows
every file (refused otherwise). The split is SkillOpt's, by question, and FigQA asks up to three questions about
one figure: 25 of the 127 test questions share a figure with a training question, whose verifier output the
learner reads, so
utils/rows/test_new_figures.txtlists the other 102 (utils/figures.py) for a second scorefrom the same trials.
codex_trace_to_optimizer: false, in both profiles' configs):the summary reads SkillOpt's own harness (
task.md,SKILL.md,<answer>), and told the analyst that everyHarbor rollout, right or wrong, gave no answer. SkillOpt's own Codex runs have it on; the protocol tables list it.
<task>#0, which no other run takes) with their owntrial cache; the AHE smokes set
target_pass_rate: 1.01so that the Debugger and the Evolve Agent run when bothtasks pass, and the AlgoTune and Terminal-Bench-Science smokes cap a session at 1,800 s.
Files: the five folders under
examples/;examples/README.md(the Harbor benchmarks section);CHANGELOG.md;tests/core/test_harbor_examples.py;examples/algotune/utils/tests/test_judge.py;examples/labbench/utils/tests/test_patches.py,test_figures.py.This PR is stacked on #105 (base
harbor-foundation); once #105 is merged it is retargeted tomain.Validation
All on one Linux host (Docker 29, bubblewrap, Harbor 0.25.0), on the branch's head.
Prepare, each benchmark from the registry:
python -m hermit.harbor.dataset prepare examples/<folder>/utils/benchmark.yamlwrote the task links,
tasks.jsonl, the splits and the locks committed here (LAB-Bench's lock records the patch:setup.py: 181 patched, 0 already patched; test.sh: 181 patched, 0 already patched, on a fresh download; themachine's earlier download, reused, matched it).
Oracle (Harbor's reference solutions,
acting_agent: {name: oracle}, the two smoke rows): Terminal-Bench 2.0 1.0,SWE-bench Verified 1.0, Terminal-Bench-Science 1.0, LAB-Bench 1.0 (with both patches, re-locked from a fresh
download), AlgoTune speedup 1x (the reference solver: score 0, the timing verifier ran).
Smokes (2 rows each; the scores say the pipeline ran, nothing about the methods):
psf__requests-1142in text)git archiveexport of Terminal-Bench 2.0's smoke: 1.0 / 1.0; AHE's seed ashermit/adapter/templates/ahe, Codex: 1.0ADAPTER.md,AGENTS.mdandmiddleware.py(Claude Code: and added a skill); transfer, Codex: 0hermit eval --adapter rooton LAB-Bench's smoke (Codex) took both trials from the trial cache (the smoke tests onits training rows). No smoke had an infra trial or an error.
hermit eval --adapter final --spliton LAB-Bench's smoke ran its two trials again: oncehermit trainhas testedthe final adapter, its card holds the results (a new commit, the tag moved), so the trial cache no longer matches it
(Harbor foundation: every CLI in a task's container, and eval, split and stream runs #105's behaviour, left as it is). The new-figure score is therefore read from each eval's results
(
python examples/labbench/utils/figures.py <eval dir>..., b6cf47b), not from a second eval. The adapter export(
mkdirof a new folder, thengit archive ... | tar -x -C) ran on Terminal-Bench 2.0's smoke tree, andmkdirrefused the folder a second time.
Tests. The new tests (25 in the two examples' files, 58 in
tests/core/test_harbor_examples.py, about a secondin all) pass on b6cf47b.
test_harbor_examples.pyfails on each of these broken copies: a test row feat(evolvers): GEPA and SkillOpt as built-in Evolvers, with the SkillOpt paper's OfficeQA setting #2, a swappedsplit, a method config on other rows, another cache, another model; and, since the audit, Terminal-Bench 2.0's AHE
trained on all four rollouts, a SkillOpt validation on the test split, a sandbox off or not enforced, a learner not
sandboxed, web search on in a benchmark file or a config, the trace summary on, no
success_scoreor one at 1x, asmoke row in the test, a new-figure row outside the test (12 copies). Every config also loads from an unprepared
copy without skillopt, as in CI. On dcc8915, the tests CI selects (
pytest --changed, 1,534): 1,469 passed, 61skipped, 4 failed; the 4 fail the same way on Harbor foundation: every CLI in a task's container, and eval, split and stream runs #105's head 2ca476a on this machine (the clbench parity tests read
another metaworld checkout here; a venv layout test), and Harbor foundation: every CLI in a task's container, and eval, split and stream runs #105's CI passed them. On c780fde the whole suite in 16
shards gave 1,938 passed, 84 skipped and the same 4 failed, and CI passed.
Secret scan of the committed files, of every run record above and of the smokes' trial folders, for the two
Claude tokens and the ChatGPT sign-in's tokens, once every run had ended: none found (a live session's own
auth.json, mode 600, exists only while it runs).Not verified: none of the full runs (the results tables are empty; examples/README.md lists them); an API key in
place of a login, and the CLIs other than Codex and Claude Code; another host than this one; SWE-bench Verified's 500
images on a small Docker disk (they accumulate in Docker's build cache; the disk gate holds trials below 25 GB free).
Review
examples/README.md the shared section, CHANGELOG the entry.
give ran here, on the smoke rows: prepare,
hermit eval --adapter nonewith--split examples/<folder>/utils/splits/smoke.txt,hermit eval --adapter root,--adapter <a directory>(thegit archiveexport of Terminal-Bench 2.0's smoke, andhermit/adapter/templates/ahe),hermit trainof every smokeconfig, the adapter export, the oracle's command,
utils/figures.pyon an eval's folder; the long runs' configsonly load (
Config.load).runs/and the tasklinks are git-ignored.
General checklist:
Core changes. None: no file under
hermit/changes.Implementation correctness and failures. The configs go through the real entry points (
hermit train,hermit eval) in the smokes, with their failure paths: the disk gate held trials at 24.7 GB free and released them;infra trials are retried (
eval.infra_retries: 2); a verifier timeout on AlgoTune is the agent's result.Real execution paths and tests. The smokes are the CLIs in Harbor's containers on real tasks, learners
included; the tests read the committed files and load every config with
Config.load, prepared or not.Documentation. Five READMEs, five
task-info/README.md(what the learners read: the task, the CLI, how theadapter is deployed; no answer or task-specific guidance), examples/README.md, CHANGELOG.
This description. Read against the files and the run records.
Independent review (post-PR audit). An agent that did not write the PR reviewed c780fde against the four
checklists, the framework code the configs rely on and the papers' texts. No P1. Fixed in dcc8915 (and b6cf47b):
success_scoreof 1.0): now a solver faster than the reference is a success.
rollout gave no answer: off in the SkillOpt configs.
search, and 26 of their 40 skipped in CI: now they do, with no skip.
second score.
writing over the baseline's results (its own run name); the adapter export mixing folders and covering Codex
only (a fresh git-ignored folder per profile); claims against the papers (Meta-Harness's leaderboard figures,
AHE's rollback, seed and efforts, RRSI's trials, GEPA's splits, NPUEval's score, SkillOpt's meta skill, SWE's
runs per task); the SkillOpt trial counts (at most 364 and 408); Terminal-Bench 2.0's image pulls, the infra
count, the learners' tokens and the senders' paths in the records (documented).
Left as they are: the AHE rollback at the port's reading (HARMFUL only;
rollback_verdicts: [HARMFUL, INEFFECTIVE]follows the paper's text), stated in Terminal-Bench 2.0's protocol table; the Codex AHE configs'
allowed_hosts,which the trainer also adds for a ChatGPT login (as OfficeQA's AHE configs have it); the SkillOpt Claude learner's
plan wait at its 12-hour default. Remaining: none of the full runs is done.
Test checklist: the tests are in
tests/core/(they read five examples' files: core runs for every change) and inthe examples' own
utils/tests/, named as behaviours, each file opening with what it covers; they write only totmp_path, use no network, sign-in or CLI, and none skips: a config loads without its benchmark's download.Method checklist: the templates (
ahe@1.0,prompt-only@1.0) and Evolvers (ahe_adapter,skillopt) are theexisting ones, as #105 runs them; the protocols' differences from the papers are each README's protocol table (model,
the acting agent being a CLI the adapter is deployed into, concurrency 6 against the AHE paper's 96, no Explore Agent,
the port's rollback, SkillOpt's starting skill a placeholder with no instructions and its analysts without the Codex
trace summary); the learners see the training rows' trajectories and the task-info only, the judge and the
test rows never; every config keeps the sandbox on (
sandbox.enabled: true,enforceat its defaultrequired) andweb_search: falsefor the acting agent and the learners. No experiment is reported: the smokes check the pipeline.Sandbox checklist: every process runs through #105's paths (the learners in the evolver sandbox, the acting agent in
the task's container); this PR adds none.
🤖 Generated with Claude Code
https://claude.ai/code/session_01FcJCJanVqQuJyChDevJNYP