Retry transient benchmark infrastructure failures - #175
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
bmsaadat
left a comment
There was a problem hiding this comment.
Review
Verdict: Request changes (two fixes, one question; direction is right)
The design is sound: trial-level retry is the correct boundary (harbor-hypeman constructs the SDK client with max_retries=0, so the PR body's claim checks out), the strict gate closes a real hole (harbor exits 0 even with infra-errored trials, and the old .scored > 0 floor passed with a single graded trial), and running both arms through one runner removes a real tooling confound. I verified the retry mechanics against the pinned harbor 0.21.0: failed attempts' trial dirs are removed before retry and stats.n_retries matches the ingestion, so the gate and Retries column are wired correctly.
Requested changes
-
The retry list misses the common transient REST classes. The hypeman SDK maps 429 to
RateLimitErrorand any 5xx toInternalServerError(_make_status_error), and neither is in the include list, so a transient 502 oninstances.create/waitis still an unretried infra error, which the new strict gate turns into a red multi-hour run. Suggest adding both; harbor's default exclude list still protects grading-semantics errors since exclude takes precedence. (The exec path looks well covered as-is:ConnectionRefusedErrormatches refused websocket connects, andhypeman/lib/exec.pywraps recv-side stream drops intoExecProtocolError.) -
The report and the gate now disagree about "complete". The jq gate requires
scored == trials, butrenderMarkdown's incomplete check only looks at statuses/infra/ungraded, and publish still gates onscored === 0. Two consequences: an arm with a trial dir missingresult.jsonrenders unsuppressed deltas with no warning while the workflow fails on the gate, andscored == trialsis vacuously true at zero trials where the old.scored > 0floor failed. Suggest computing one per-armcompleteboolean (plus reasons) inreport.ts, rendering and gating from that single field, and keeping a nonzero-trials floor.
Question
Instance names are stable across retry attempts (trial_name is minted once and reused; the name is harbor-{session}-{envhash[:8]}), and a create whose response is lost leaves _instance_id unset so cleanup can't delete it. Does Hypeman enforce per-org name uniqueness? If yes, retries after a lost create response hit 409 ConflictError (not in the include list, and not transient) in exactly the restart scenario this PR targets; if no, orphaned instances can accumulate per flaky trial. Either way the README's "the whole trial is the safe retry boundary" line may be worth softening.
Non-blocking notes
- Backoff is effectively a constant 1s (
RetryConfigmin_wait 1.0, multiplier 1.0), so fast-failingConnectionRefusedErrorburns all five retries within seconds of an outage.harbor run --configcan setretry.min_wait_sec/wait_multiplierif we want spacing; timeouts (40m single-task, 4h CI) also now bound up to 6 attempts. - Since the harness runs from main, this PR's own benchmark won't exercise these flags (its run would use main's runner: candidate arm with retries, baseline without), so first real validation is post-merge. Worth noting in the PR body, and worth validating the two
.image.envkeys right after sourcing; extracting just those keys instead ofsource-ing arm-generated content would also keep a future extra key from overriding harness pins. - Retried attempts' cost/tokens are deleted with their attempt dirs, so the Cost column under-reports on flaky runs, and candidate-caused flakiness (e.g. exec wedging) is absorbed silently except for the Retries column. A mention of nonzero retries in the warning area would keep that visible.
|
updated in c413ad2: added |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c413ad2. Configure here.
bmsaadat
left a comment
There was a problem hiding this comment.
Verdict: Approve. Both requested changes landed cleanly: the retry list now covers the REST 5xx/429 classes (verified the class names against the hypeman version the constraint actually resolves), and the per-arm complete/incompleteReasons unification with the nonzero-trial floor is exactly the single-source-of-truth shape we hoped for, with good edge-case tests.
The harbor-hypeman 0.1.2 detached-exec design deserves a callout: decoupling the running command from the control-plane session, with the 60s reconnect window, solves the restart scenario more fundamentally than retry classes could. Nice.
One open question from last round, non-blocking since the failure mode is a loud red run: after a lost instances.create response, the trial retry reuses the same instance name (trial_name is stable across attempts). If Hypeman enforces name uniqueness, those retries would die on ConflictError, which isn't in the include list. Is that a real path, and if so is ConflictError worth including (or the name worth salting per attempt)?
Two small observations, fine as-is: the 0.1.2 poll raises bare RuntimeError when a job vanishes (e.g. VM death), which the trial retry won't catch; and the unified publish gate now skips Braintrust publication for incomplete runs, so the markdown report is the only artifact for exactly the runs we'd debug. If both are intentional, no changes needed.

summary
why
A brief control-plane restart can otherwise turn the remaining task queue into infrastructure failures. Per-request retries stay disabled because create/build requests may have succeeded before their responses were lost; the whole trial is the safe retry boundary.
testing
bun test(277 passed)go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.7 .github/workflows/benchmark-clawbench.ymlbash -n benchmarks/harbor/clawbench/run.shbunx prettier --check ...git diff --checkbunx tsc --noEmitremains blocked by the existingreasonfield error insrc/lib/mcp/tools/auth-connections.test-fixtures.tsonmain.