Skip to content

fix(bench,arenabench): refuse a SUT binary too far behind the code it is reported as measuring - #2052

Merged
macanderson merged 8 commits into
mainfrom
worktree-fix-2032-sut-staleness
Aug 7, 2026
Merged

fix(bench,arenabench): refuse a SUT binary too far behind the code it is reported as measuring#2052
macanderson merged 8 commits into
mainfrom
worktree-fix-2032-sut-staleness

Conversation

@macanderson

@macanderson macanderson commented Aug 7, 2026

Copy link
Copy Markdown
Owner

What & why

Pinning and freshness are different properties, and until now only the first was
checked. ~/.arenabench/sut/stella — the path every runbook and launch script
exports as STELLA_BINARY — sat 291 commits and three days behind
origin/main while carrying its own sut_commit.txt naming that ancient
commit. So it looked pinned, passed everything #2016/#2020 added, and produced
perfectly scoreable trials attributed to code that had been rewritten underneath
them. A commit id answers which code; only a distance from a reference answers
whether it is the code anyone meant.

Closes #2032

The guard reads the artifact, not the paperwork

sut_commit.txt is extrinsic — a claim about a file, and precisely the thing
that went stale and that a symlink can silently repoint. crates/stella-cli/build.rs
stamps STELLA_BUILD_GIT_SHA into a single <version>-dev.<40-hex> literal, and
build_info.rs deliberately surrounds it with NUL bytes so LLVM's string pooling
cannot adjoin identifier characters to it — its doc comment says outright that
this exists so the identity can be attested without executing the binary. That
is intrinsic: it travels inside the artifact and no rename, copy, or symlink
can separate the two.

New bench/harbor_adapter/stella_harbor/freshness.py reads it and measures the
distance. A repointed path or a hand-refreshed sidecar cannot make an old build
look new, and a sidecar that disagrees with the binary is itself a refusal.
Reading the ELF rather than running stella --version is what lets this run on
the host before any container exists, on a macOS machine that cannot exec a
linux/amd64 binary at all — the same reasoning that made portability.py parse
.gnu.version_r in pure stdlib instead of shelling out to readelf.

Exemplar followed: stella_harbor/portability.py, deliberately and closely —
stdlib-only, standalone-runnable, 0 fresh / 1 stale / 2 undeterminable, a
check_* returning a list of violations, blocking on the host in env.sh rather
than per-trial in the container.

Wired at both launch paths

Path Where Posture
Terminal-Bench evidence runbook preflight() in bench/evidence/run/env.sh Fails closed — an unidentifiable binary is status 2 and fatal, because this path publishes numbers
Unpinned arena match sut.unpinned_problem() in arenabench/arenabench/sut.py Refuses only on positive evidence of staleness — a plain cargo build --release carries no stamp, cannot be dated, and must not block the local development loop

The difference is deliberate and follows from who reads the result, not from a
disagreement about what is safe. Clearing sut_ref opts out of pinning, not
out of every check: an unpinned match asks for whatever is current, so a binary
that is measurably not current contradicts the request rather than opting out of
it. Measuring older code on purpose is still available and is spelled the
supported way — pin sut_ref to that commit, which puts the answer in the
result.

The limit is a stated distance, measured not guessed

DEFAULT_MAX_BEHIND = 25. origin/main moved 654 commits in the seven days to
2026-08-07
(~93/day), so 25 is about six hours of drift: it tolerates a binary
staged at the start of a long run whose main moved underneath it, and refuses
the 291-commit artifact by a factor of twelve. It lives in the checker and is not
restated in shell, so the two copies cannot drift apart.

The build_sut.sh fetch race, from the issue comment

The script recorded origin/main only after its own git fetch, so a branch
that moved between your checkout and that fetch produced a drift list of files
nobody touched — reading as local contamination and sending you hunting for edits
that do not exist (observed on the issue: 44f4c63a9b502f1c).

It now takes an optional commit argument, so a wrapper that fetches and checks
out can build exactly what it prepared. Unargued, it records origin/main before
the fetch as well and separates the two causes: if the tree is byte-identical to
where the branch started, the refusal says so, names both SHAs and the distance,
and suggests build_sut.sh <that-commit>. It also verifies its own output —
--reference "$SUT" --max-behind 0 is an equality assertion on the binary's
compile-time stamp, catching a build that silently stamped something else.

The witness

  • This PR includes a witness test (fails on main, passes here)

TestAnUnpinnedMatchStillRefusesStaleCode::test_the_stale_runbook_binary_now_blocks_the_launch
is the witness the issue asks for verbatim: an unpinned Stella seat with
STELLA_BINARY pointing at a binary far behind origin/main must refuse, naming
the commit and the distance.

Checked the artisanal way, and checked behaviourally rather than by deletion —
reverting only the sut_problem_for dispatch line (leaving the new constants in
place, so the failure is not merely a collection error):

FAILED tests/test_sut.py::TestAnUnpinnedMatchStillRefusesStaleCode::test_the_stale_runbook_binary_now_blocks_the_launch
  AssertionError: an unpinned match asks for current code; this binary is not it
  assert None is not None

None means the launch proceeds — exactly the reported failure. With the change,
green.

bench/harbor_adapter/tests/test_freshness.py adds 33 more, including
TestCli::test_the_documented_witness (the issue's readlink -f scenario as a
CLI assertion), the symlink case (the rig's own mitigation — a guard reading the
link's directory would report the stale claim), and a stamp straddling the
1 MiB read boundary, which is the one input a naive reader loses and which fails
open onto the sidecar this module exists to distrust.

The gate

  • make guards-fast green (no Rust touched — this is the rung the pre-push
    hook picks for a diff that reaches no crate)
  • bench/harbor_adapter: 473 passed, 1 skipped
  • arenabench: full suite green
  • Docs updated: bench/RUNBOOK.md, bench/evidence/run/README.md,
    arenabench/README.md
  • Closes #2032 appears both here and as a commit trailer

Two mechanical notes for review, both flagged by guards rather than by me:

  1. freshness.py had to be added to _FIXED_ADAPTER_SOURCE_PATHS in
    secure_launcher.py. That tuple is enumerated by hand on purpose — the paid
    launcher byte-compares the running adapter against the published commit, so a
    globbed file would execute without ever being compared. Forgetting it failed
    closed with "public adapter tree hash differs from runtime identity", which is
    the guard doing its job.
  2. That one line pushed secure_launcher.py from 4293 to 4294, over its ceiling.
    Handled with make file-size-update, and the baseline diff is exactly +1 on
    that one row — the documented irreducible case (a required registration entry
    in an already-oversized file), not a ceiling raised to turn a gate green.

Nothing left behind

Anything reviewers should know?

The judgement call worth a second opinion is the arena's fail-open posture.
An unstamped cargo build --release is not blocked, because refusing it would
break the local development loop. That is a deliberate asymmetry with the
evidence runbook, argued in unpinned_problem's docstring — but it does mean the
arena still cannot catch a stale unstamped binary. If you would rather it fail
closed there too, say so; the change is one branch.

I did not implement the issue's option 1 ("delete sut/stella, make the bare
path an error"). sut_ref="" is an existing, documented affordance, and turning
it into a hard error is a behaviour decision I did not think was mine to make
silently. Option 3 was the issue's own note as strictly more general, and it is
what shipped. Option 2 is already applied rig-side and this PR's symlink test
pins that it keeps working.

MAX_BEHIND_UNPINNED and DEFAULT_MAX_BEHIND are two copies of 25 across the
two trees, documented as matching but not enforced to be. Cross-tree enforcement
is the wrong fix given the pending ejection; #2050 asks for an explicit decision
on whether they should stay coupled at all.

Summary by Sourcery

Enforce freshness checks for the Stella SUT binary across arena matches and Terminal-Bench runbook, measuring how far the compiled artifact’s embedded commit is behind the reference branch and refusing stale or inconsistent binaries, while tightening build tooling and documentation around SUT provenance.

New Features:

  • Add a standalone Python freshness checker that reads the Stella binary’s embedded commit, compares it to a reference branch, and exposes a CLI used by preflight to enforce a maximum allowed drift.
  • Introduce arena-side logic to inspect the ambient STELLA_BINARY, derive its identity without executing it, and gate unpinned Stella matches on evidence of staleness rather than only on pinning.

Bug Fixes:

  • Prevent unpinned runs from silently using Stella binaries that are far behind origin/main by refusing launches when the staged SUT is too stale or its bookkeeping disagrees with the binary’s own stamp.
  • Fix a race in build_sut.sh where origin/main could move between checkout and fetch, now allowing an explicit commit and clearly distinguishing remote branch movement from local contamination.

Enhancements:

  • Extend sut utilities with helpers to read an embedded commit from a binary, resolve the ambient SUT from STELLA_BINARY, and provide more informative warnings for unpinned runs based on whether the binary is stamped.
  • Clarify and strengthen arena and runbook documentation around STELLA_BINARY, pinning semantics, and how freshness limits relate to origin/main’s movement.

Documentation:

  • Update arenabench and bench runbook documentation to describe STELLA_BINARY’s role, the distinction between pinning and freshness, and how the new freshness checks are applied and configured.

Tests:

  • Add comprehensive tests for the new freshness checker module, its CLI, and its wiring into env.sh and build_sut.sh, plus arena tests that exercise unpinned-match behaviour with fresh, stale, unstamped, and symlinked SUT binaries.

… is reported as measuring

Pinning and freshness are different properties, and only the first was
checked. `~/.arenabench/sut/stella` — the path every runbook exports as
STELLA_BINARY — sat 291 commits and three days behind origin/main while
carrying its own sut_commit.txt naming that ancient commit, so it looked
pinned, passed everything #2016/#2020 added, and produced perfectly
scoreable trials attributed to code rewritten underneath them.

The new guard reads the commit out of the artifact's own compile-time
bytes rather than the sidecar beside it: build.rs stamps
STELLA_BUILD_GIT_SHA into a NUL-delimited literal precisely so the
identity can be recovered without executing a cross-compiled binary. A
repointed path or a hand-refreshed sidecar therefore cannot make an old
build look new, and a sidecar disagreeing with the binary is itself a
refusal.

Also names the build_sut.sh fetch race reported on the issue: the script
recorded origin/main only after its own fetch, so a branch that moved
mid-run produced a drift list of files nobody touched, reading as local
contamination. It now takes an optional commit argument, and when it
fetches it compares against where origin/main stood beforehand so the
refusal can say which of the two causes it is.

Closes #2032
Refs #2049, #2050, #2051
@vercel

vercel Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
stella-cli-docs Ready Ready Preview Aug 7, 2026 5:47am

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sorry @macanderson, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@sourcery-ai

sourcery-ai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds a binary-freshness guard for the Stella SUT, wiring it into both the Terminal-Bench runbook and arenabench so unpinned runs refuse binaries that are measurably too far behind origin/main, and fixes a build race in build_sut.sh; includes a standalone Python checker, new arena-side helpers, and comprehensive tests/docs.

Sequence diagram for unpinned arena match freshness check

sequenceDiagram
    actor Operator
    participant ArenabenchRunner as arenabench.runner
    participant SutModule as arenabench.sut
    participant GitRepo as git_checkout

    Operator->>ArenabenchRunner: create_match(spec with sut_ref="")
    ArenabenchRunner->>SutModule: sut_problem_for(spec)
    SutModule->>SutModule: unpinned_problem()
    SutModule->>SutModule: ambient_sut()
    SutModule->>SutModule: embedded_commit(path)
    SutModule->>GitRepo: resolve_ref("main")
    GitRepo-->>SutModule: target_commit
    SutModule->>GitRepo: drift_between(ambient.commit, target_commit)
    GitRepo-->>SutModule: Drift(behind, comparable)
    alt drift.comparable and drift.behind > MAX_BEHIND_UNPINNED
        SutModule-->>ArenabenchRunner: problem string (binary too far behind)
        ArenabenchRunner-->>Operator: refuse launch
    else not stale or not comparable
        SutModule-->>ArenabenchRunner: None
        ArenabenchRunner-->>Operator: launch proceeds (with warning logic)
    end
Loading

Sequence diagram for Terminal-Bench SUT build and freshness verification

sequenceDiagram
    actor Operator
    participant BuildScript as build_sut.sh
    participant EnvSh as env.sh
    participant Freshness as freshness.py
    participant GitRepo as git_checkout
    participant Binary as STELLA_BINARY

    Operator->>BuildScript: ./build_sut.sh [<commit>]
    alt commit argument given
        BuildScript->>GitRepo: git rev-parse --verify "<commit>^{commit}"
        GitRepo-->>BuildScript: SUT_commit
        BuildScript->>GitRepo: git diff --name-only SUT_commit -- RUST_INPUTS
    else no commit argument
        BuildScript->>GitRepo: git rev-parse --verify --quiet origin/main
        GitRepo-->>BuildScript: BEFORE
        BuildScript->>GitRepo: git fetch origin main
        BuildScript->>GitRepo: git rev-parse origin/main
        GitRepo-->>BuildScript: SUT_commit
        BuildScript->>GitRepo: git diff --name-only SUT_commit -- RUST_INPUTS
    end
    BuildScript-->>Operator: build SUT binary at STELLA_BINARY

    Operator->>EnvSh: preflight()
    EnvSh->>EnvSh: assert_portable_binary()
    EnvSh->>EnvSh: assert_fresh_sut()
    EnvSh->>Freshness: python3 freshness.py "$STELLA_BINARY" --repo "$TB_REPO" --reference "$SUT" --max-behind 0 (from build_sut.sh) or DEFAULT_MAX_BEHIND

    Freshness->>Freshness: read_identity(binary)
    Freshness->>Freshness: embedded_source_commits(path)
    Freshness->>Freshness: read_sidecar_commit(directory)
    Freshness->>GitRepo: measure_distance(identity.commit, repo, reference)
    GitRepo-->>Freshness: Distance
    Freshness->>Freshness: check_freshness(identity, distance, max_behind)
    alt violations found
        Freshness-->>EnvSh: exit status 1 or 2
        EnvSh-->>Operator: FATAL: binary not fresh - rebuild
    else no violations
        Freshness-->>EnvSh: exit status 0
        EnvSh-->>Operator: preflight succeeds - run may proceed
    end
Loading

File-Level Changes

Change Details Files
Introduce a standalone freshness checker for Stella SUT binaries that reads embedded commit stamps, compares against a reference branch, and exposes a CLI used by the bench runbook.
  • Add bench/harbor_adapter/stella_harbor/freshness.py implementing identity extraction from the ELF, distance measurement via git, and a verdict function with JSON/CLI modes
  • Define DEFAULT_MAX_BEHIND, DEFAULT_REFERENCE, and SIDECAR_FILENAME constants and safe ref handling, avoiding unsafe git invocation
  • Return exit codes 0 (fresh), 1 (stale), 2 (undeterminable) so shell callers can fail closed on nonzero status
bench/harbor_adapter/stella_harbor/freshness.py
Wire the freshness guard into the Terminal-Bench evidence run path and fix build_sut.sh’s origin/main fetch race while asserting the built binary’s stamp matches the requested commit.
  • Extend env.sh with assert_fresh_sut(), invoking the freshness checker before runs and treating any non-fresh/undeterminable verdict as fatal
  • Update build_sut.sh to accept an optional commit parameter, detect and report the origin/main fetch race vs local edits, and call assert_fresh_sut with --reference and --max-behind 0 as an equality check on the compile-time stamp
  • Document the new behaviour and CLI usage in bench/evidence/run/README.md and bench/RUNBOOK.md, including examples of calling freshness.py
bench/evidence/run/env.sh
bench/evidence/run/build_sut.sh
bench/evidence/run/README.md
bench/RUNBOOK.md
Teach arenabench to understand the intrinsic commit of the ambient STELLA_BINARY, enforce a max-behind limit for unpinned matches, and adjust warnings accordingly.
  • Add MAX_BEHIND_UNPINNED, STELLA_BINARY_ENV, and _VERSION_COMMIT_BYTES constants plus embedded_commit() and ambient_sut() helpers in arenabench/arenabench/sut.py
  • Implement unpinned_problem() that uses ambient_sut(), resolve_ref("main"), and drift_between() to refuse unpinned Stella seats whose binary is older than MAX_BEHIND_UNPINNED commits behind origin/main while failing open when the commit or repo is unavailable
  • Update sut_problem_for() to route unpinned Stella specs through unpinned_problem(), and enhance runner._agent_environment() to emit more precise warnings based on whether the ambient binary has an intrinsic commit stamp
  • Add README documentation explaining STELLA_BINARY behaviour, unpinned freshness checks, and how to deliberately measure older code via sut_ref pins
arenabench/arenabench/sut.py
arenabench/arenabench/runner.py
arenabench/README.md
Add regression tests around unpinned stale SUT binaries, the new freshness checker, and the wiring from shell preflight to Python checker.
  • Extend arenabench/tests/test_sut.py with fixtures and tests that construct stamped binaries and deep git histories to validate unpinned behaviour, symlink handling, unstamped builds, and multi-stamp cases
  • Introduce bench/harbor_adapter/tests/test_freshness.py to exercise embedded stamp parsing, sidecar precedence rules, distance measurement, CLI behaviour (including JSON output and exit codes), and the build_sut/env.sh wiring assumptions
  • Ensure tests cover edge cases like stamps crossing the 1 MiB read boundary, multiple compile-time stamps, incomparable commits, and explicit --max-behind / --reference usage
arenabench/tests/test_sut.py
bench/harbor_adapter/tests/test_freshness.py
Integrate the new freshness module into the secure launcher’s fixed adapter source set and update size baselines.
  • Register freshness.py in secure_launcher._FIXED_ADAPTER_SOURCE_PATHS so the paid launcher’s adapter-integrity check covers it
  • Adjust scripts/file-size-baseline.txt to bump secure_launcher.py’s tracked byte size by one line to accommodate the new registration
bench/harbor_adapter/stella_harbor/secure_launcher.py
scripts/file-size-baseline.txt

Assessment against linked issues

Issue Objective Addressed Explanation
#2032 Add a staleness refusal for the SUT binary by comparing its intrinsic commit stamp against origin/main, refusing or requiring override when it is too far behind.
#2032 Wire the staleness guard into all relevant launch paths and documentation (Terminal-Bench runbook, env.sh, build_sut.sh, arenabench behavior) so that runs launched per the runbook cannot silently use the stale ~/.arenabench/sut/stella path.
#2032 Provide a witness test showing that an unpinned match launched with STELLA_BINARY pointing at the stale legacy sut/stella binary now refuses to start, naming the commit and its distance behind origin/main.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@macanderson
macanderson merged commit 0867dde into main Aug 7, 2026
9 of 10 checks passed
@macanderson
macanderson deleted the worktree-fix-2032-sut-staleness branch August 7, 2026 05:46
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.

bench: the runbook's STELLA_BINARY path is 291 commits stale and passes the pinning check

1 participant