Repository navigation
feat(tasks): add Ag-LiveCodeBench-X — multi-language LiveCodeBench - #123
Merged
Merged
Conversation
19 of 21 tasks
…language LiveCodeBench v5's 499 stdin/stdout problems, prepared by Agnostics (ICLR 2026, arXiv:2508.04865) so the same problem and the same test cases score a solution in any language. Ships `status="experimental"`: faithful on the axes below, but no run has been aligned against a published number. The language is a task argument, not a property of the data, so `language` is required with no default — the benchmark measures a different thing per language, and a silent default would let two runs of one task name mean different things. `container_lang` (the verifier tag) defaults to `language`'s first word lowercased and stays overridable, because upstream keeps the two independent and warns nothing checks them against each other. Both are recorded in `report.json`, which the task name cannot do. The prompt is a frozen dspy==3.0.0b2 ChatAdapter rendering of upstream's ChainOfThought(SolveProblem), captured by running it: two of its properties are invisible in the signature — the instructions are re-inserted into the system message still carrying the source docstring's 8-space indent, and the field list is stripped as a block so the first line keeps a trailing space and the last loses it. Frozen rather than depending on DSPy at runtime, so a patch release cannot re-word the fleet's prompts; pinned by sha256 in the tests. Response parsing and code extraction are reimplemented, not vendored (upstream ships no license), including an upstream offset bug that leaks `]]` out of an indented field header. Enumerated divergence with a consequence: upstream's ChatAdapter retries a failed parse through JSONAdapter with a differently shaped prompt and this port makes one call, so a reply missing either marker scores 0 here. The number is a lower bound whose gap is exactly `n_unextracted`. Execution goes through the code-evaluator's new `agnostics` source rather than from the task process, so sieval keeps one code-execution boundary and a client cannot name an arbitrary container to run. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… names `ghcr.io/nuprl/agnostics` publishes exactly `lua, r, python, jl, java, cpp, ml, f90` — Julia is `jl`, OCaml is `ml`, Fortran is `f90`. Deriving the tag by lowercasing the language's first word, as this shipped, named no published image for three of the five languages the paper reports, so every rollout would have come back `infra:exit` (no such image) and the task would have scored a hard 0 for reasons that look like an infrastructure outage. `_CONTAINER_TAG_BY_LANGUAGE` maps the extension-tagged half and leaves the rest falling through to the lowercased first word, which is correct for `lua` / `r` / `python` / `java` and the only sensible guess for a container the table has never seen. `container_lang` still overrides it, which is what a private registry needs. Found by querying the registry's tag list rather than by assuming it mirrors the framework repo's directory names, which are spelled out in full (`executors/julia`, `executors/ocaml`, `executors/fortran`). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The verifier decides scores, so it gets what a dataset revision gets. A
tag can be moved under a finished leaderboard without anything on disk
changing, which is exactly the drift `--resume` and pinned revisions exist
to prevent everywhere else in this repo.
`_IMAGE_DIGESTS` maps each of upstream's eight published tags to a digest
resolved from the registry on 2026-08-23, each verified against the
manifest's own `Docker-Content-Digest`. A language with no pinned digest
is REFUSED (`infra:unpinned-lang`) rather than falling back to the
floating tag: an unpinned verifier scores silently, which is the failure
the table exists to prevent. All eight are single-platform linux/amd64
manifests, so the pin binds the architecture too — arm64 needs the
command override.
A pin nothing records is not a pin, so the resolved reference travels back
as `data.verifier_image`, onto each rollout's judgement, and is surfaced
once as `report()`'s `verifier_image`. Two verifiers in one run (an
evaluator re-pointed mid-run) are both reported rather than one being
picked to stand for the rest, and an unrecorded one is omitted rather than
blanked — an empty string would read as "ran unpinned", a different claim.
Under a command override the field is `None` unless the override's
template actually contains `{image}`: naming a digest that did not run is
worse than reporting nothing.
Verified live on both paths: lua/jl/ml/f90 resolve and report their
digests, `julia` and `rust` are refused, and a `{lang}`-templated override
reports no image.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`verifier_command` enforced the digest-pin contract only on the default
(podman) path. The override branch returns early with `_IMAGE_DIGESTS.get`,
so a language with no pinned digest had `""` substituted into the `{image}`
slot instead of raising -- the documented `infra:unpinned-lang` refusal never
fired there.
podman is the one runtime that needs no override, so *every* other deployment
-- upstream's own apptainer included -- ran the branch where the guarantee was
missing. Nothing scored silently (an empty argv slot makes most runtimes
error), but the operator read whatever the runtime said about a missing
argument rather than the diagnostic that names the cause, which is exactly the
classifier split this module exists to make.
A template containing `{image}` is asking this table for a pinned digest, so
it is now refused the same way as the default path. A template *without*
`{image}` names its own image and is untouched -- that is the override taking
responsibility, which is the point of having one.
Verified end-to-end through the real `ghcr.io/nuprl/agnostics` lua verifier at
its pinned digest, run under udocker: `rust` now returns
`infra:unpinned-lang: 'rust'` where it previously surfaced as `infra:exit 64`.
All five override/default x pinned/unpinned combinations behave as documented.
VENDORED.md also records what that validation run established, since the file
still claimed the container hop was only exercised against a stub: the real
verifier returns `success` / `fail:wrong-output` / `fail:error` verbatim, a
hand-written correct Lua solution scores `success` on a real decoded
LiveCodeBench suite while a deliberately wrong variant does not, and all eight
pinned digests still matched the registry on 2026-09-11. Plus the two things
podman gives for free that a udocker deployment has to rebuild -- a private
workdir per invocation (19 of 40 verdicts were wrong without one) and
`--quiet`, because `udocker run` banners land on stdout and this module
json-decodes the whole stream.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The module docstring and the test's name both said the rendering keeps "the source docstring's 8-space indentation". Upstream's docstring is indented **4** in the class body, and `Signature.instructions` dedents it to zero before the adapter ever sees it; the 8 comes from `ChatAdapter` joining the instruction lines with a newline plus a hard-coded eight spaces. The frozen bytes were always correct -- independently confirmed by rendering upstream's signature under a real `dspy==3.0.0b2` install, which reproduces both the system and the user message byte-for-byte. Only the stated reason was wrong, and it is the kind of wrong that misleads whoever re-captures the prompt on the next DSPy bump: they would go looking at upstream's source indentation, find 4, and conclude the capture had drifted. The hash test cannot catch this, because it pins this file's own literal against itself. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The rebase puts this task on top of the metrics rework, whose `sampling_report` now returns interval and unit-declaration keys (`*_ci95` as a list, `ci95_units` as a dict). `metrics` was annotated `dict[str, float | str]`, so `metrics.update(rolled)` no longer type-checks -- two `ty` diagnostics, both in this file, and neither visible until the branch sat on current main. Widening the annotation is the whole of the type fix. The rest adopts the convention that rework introduced and that every sibling pass@1 task now follows (`human_eval_0shot_gen` is the structural twin): `score_key="pass@1"` so the headline's interval is also published as `score_ci95` -- the same estimate over the same values, not a second measurement -- and `ungated_intervals` to lift `score` / `pass@1`'s intervals out of the `n > 1` gate, because the metrics they bracket are published at every budget. `grouping=self.problem_groups(finals)` is inert when one sample is one problem and correct if a run configures `Dataset.repeat`. Verified on a live 20-sample run, which is the only thing that exercises it: the runner validates interval/unit pairing at report-write time and raises there, so a green unit suite says nothing about it. The report now carries `score_ci95` / `pass@1_ci95` = [0.0, 16.84], `n_problems` 20 and `ci95_units` naming `n_problems` for both, with no raise. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ethan-scitix
force-pushed
the
worktree-ag-livecodebench-x
branch
from
September 11, 2026 08:01
27c67b5 to
db74c27
Compare
The PR shipped `experimental` with its own promotion criterion stated: "one paper cell reproduced within its noise". That has now been done, so both the status and the prose explaining it were stale. **Table 1, Qwen 3 8B x Lua: published 11, measured 10.42** (52/499) -- 0.58 pp, or 0.30 combined binomial sigma (sigma_D = 1.96 pp). Run at upstream's README settings for Qwen 3 (temperature 0.2, top_p 0.95, max_tokens 2048, language "Lua /nothink", one completion), against the real `ghcr.io/nuprl/agnostics` lua verifier at the digest this branch pins -- not a stub. Verdict mix: 74.5% fail:error, 11.7% fail:wrong-output, 10.7% success, 3.1% infra:timeout, which matches the paper's own qualitative finding that base models on low-resource languages fail mostly on syntax and input parsing. Three caveats travel with the number, all in the shipped docstring and `reference_impl.notes` rather than only here, and none of them moves it out of noise: - the paper served `qwen3_8b_awq` (AWQ 4-bit) where this used the only OpenRouter provider for the checkpoint, which reports quantization unknown; - 13 of 499 rollouts never generated (12 provider rate-limits, one content filter) and count as failures, as upstream's `pass1` counts a generation that produced no solution -- biasing the result down from 10.70 to 10.42; - the no-JSONAdapter-retry divergence cost exactly one row (`n_unextracted` 1). Also recorded: a hand-written correct Lua solution scores `success` on a real decoded LiveCodeBench suite while a deliberately wrong variant scores `fail:wrong-output`, which is what rules out the decode and whitespace paths as an explanation for the score; and all eight pinned verifier digests still matched the registry on 2026-09-11. The remaining four languages and every other model in the table are unmeasured and the docstring says so. `meta/index.json` regenerated. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…retry note
Three review findings on the same file, one behavioural and two declarations
the file makes about itself.
**The grade deadline was not outside the evaluator's own budgets.** It was
sized `timeout + 300`, but the evaluator spends those two in *series*, not one
covering the other: `exec_agnostics` writes the payload under its own 300s
`_STDIN_WRITE_TIMEOUT` -- upstream's `stdin_write_timeout`, kept because a
decoded suite is tens of MB -- and only then arms the container wall, plus
spawn and the monitor's teardown. So the client's deadline expired while the
server was still entitled to answer, and the `infra:stdin` verdict that budget
exists to report could never arrive.
The cost is larger than the lost diagnostic: a verdict fails one rollout,
whereas the transport error a too-tight deadline raises propagates out of
`feedback` and fails the whole sample, which `DENOMINATOR_REQUESTED` charges as
wrong. A narrow tail -- it needs a pathologically slow write, and the 499-problem
alignment run never hit it -- but it deflates a score rather than erroring, which
is the class worth closing. The two budgets are now named constants and the
margin is explicit; the sibling `livecodebench_code_generation_0shot_gen` states
the same invariant ("provably outside it") over its own whole-suite wall.
The test asserts the inequality as well as the literal, so the reason survives a
later change to either budget rather than reading as an arbitrary constant.
**The report slot was narrower than what `report()` returns.** It declared
`dict[str, float | str]` while `ungated_intervals` contributes `score_ci95` and
`pass@1_ci95` (`list[float]`) and `ci95_units` (`dict[str, str]`) -- verified by
dumping a real report. All 21 sibling tasks calling `ungated_intervals` declare
the full union, and this file's own local at the `metrics` assignment already
did; the class slot was missed when the report was adapted to the interval API.
Nothing catches it: the stage methods carry no return annotations, so the
generic slot is unchecked and a wrong declaration is simply wrong.
**The JSONAdapter divergence note overstated upstream's retry.** `__call__`
re-raises `ContextWindowExceededError` instead of retrying it. The lower-bound
claim is unaffected -- that case fails on both sides -- and the note now says so
rather than leaving the reader to find the exception.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`exec_agnostics` carries the guarantee the whole port rests on -- the verifier
is scoring data, so it is pinned by digest and an unpinned language is refused
rather than floated -- and had no test. That guarantee has already regressed
once: `verifier_command` enforced it on the default podman path while the
override branch substituted an empty string into the `{image}` slot, so the
documented `infra:unpinned-lang` never fired under any non-podman runtime,
upstream's own apptainer included. It was caught by a manual validation run,
not by CI, which is the gap this closes.
33 tests, none of which spawns a container: `verifier_command` is a pure
function of the environment, and the two `execute_agnostics` cases asserted here
both return before the spawn. They cover the digest table against upstream's
published tag list (spelled out rather than derived from the table, so a
misspelled tag cannot agree with itself), digest well-formedness, and all four
path/pin combinations -- default and `{image}`-override refusing an unpinned
language, an override naming its own image left alone and reporting no image,
and the pinned digest reported on both paths.
Verified discriminating by reverse-mutation: restoring the pre-fix module
(49f07b1) fails exactly the five override-refusal cases with
`DID NOT RAISE <class 'KeyError'>`, and passes the other 28.
Placed under `tests/` rather than beside the code, which is what VENDORED.md's
convention prescribes for an upstream-bound patch, because `[tool.pytest]
testpaths` covers `tests/` only -- a test under `vendor/code-evaluator/tests/`
is never collected by this suite and gates nothing. The file's docstring says
so, and asks a future re-vendor to leave an equivalent gate behind. This is the
placement the `quotebench` source already uses for the same reason.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A pass over the prose added by the two preceding commits. No behaviour, no assertions, no test names change -- 78 lines out, 45 in. - **The report slot now uses the family's own wording.** 49 of the 50 tasks declaring this union carry one verbatim three-line comment; the version added here was a bespoke six-line one that also explained why the generic slot goes unchecked. That reasoning belongs to whoever is deciding the convention, not to the fiftieth site following it. - **The deadline reasoning is stated once, at the constants.** It was in both the constant block and the call site, in different words -- "in series", "strictly outside" and "entitled to answer" each appeared twice. The call site now carries no comment at all: `self._timeout + _EVALUATOR_STDIN_WRITE_BUDGET + _HTTP_DEADLINE_MARGIN` already reads as the invariant, which is what naming the budgets was for. This is the sibling's shape, where the wall's derivation is commented and the `+ 2` at the call site is not. - **The `ContextWindowExceededError` note is an inline clause** rather than a trailing parenthetical restating the exception it had just named. - **Test comments that restated the test name are gone**, and the two that duplicated `verifier_command`'s own docstring with it. What is kept is what a reader cannot recover from the code: the REGRESSION marker (so the override case is not "simplified" away), why the published tag list is spelled out instead of derived from the table under test, why an override reports no image even for a language the table could name, and that the `lang` pattern is not a sandbox. Checked the rest of the PR rather than assuming: prose density is 44% for the task, 51% for `exec_agnostics` -- inside the band its recent siblings already occupy (`multipl_e/_base.py` 41%, `exec_quotebench.py` 59%), so the port's own comments are not outliers and are left alone. The module-docstring / `reference_impl.notes` overlap is likewise deliberate: shipped metadata has to carry the divergences on its own, and `meta/index.json` embeds the notes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
21 tasks done
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.
Type
Summary
status="stable"on a reproduced paper cell — see "Alignment" below.languageis required with no default: the benchmark measures a different thing per language, so a silent default would let two runs of one task name mean different things.report.jsoncarrieslanguage/container_lang/verifier_image, because the task name cannot hold them and a column that doesn't say which language it ran isn't comparable with anything.dspy==3.0.0b2ChatAdapter rendering of upstream'sChainOfThought(SolveProblem), captured by running it: two properties are invisible in the signature (an 8-space instruction indent inside the system message; a trailing space on the first field-list line and not the last). Frozen rather than depending on DSPy at runtime, so a patch release can't re-word the fleet's prompts; pinned by sha256 in tests.LICENSE) — including an upstream offset bug where an indented[[ ## field ## ]]header leaks]]into the field body. Reproduced deliberately; "fixing" it would move scores.vendor/code-evaluatorgainssource="agnostics", forwarding a submission to a per-language verifier container over the Agnostics protocol (one JSON line each way). That's what makes Lua / R / Julia / OCaml / Fortran reachable without installing five toolchains in the evaluator image. Purely additive — no existing source changes behaviour.infra:unpinned-lang) rather than floated. Rationale and the re-pinning procedure are invendor/code-evaluator/VENDORED.md.Since the first review pass (rebased onto
main, 19 commits): two defects found by the validation run are fixed, and the report was adapted to the interval API that landed onmainin the meantime.verifier_commandenforced the digest-pin refusal only on the default podman path — the override branch substituted an empty string for{image}instead of raisinginfra:unpinned-lang. podman is the one runtime needing no override, so every other deployment (upstream's ownapptainerincluded) ran the branch where the documented guarantee was missing.Signature.instructionsdedents it to zero — the 8 isChatAdapter's own constant. Bytes were always right; the stated reason would mislead whoever re-captures the prompt on the next DSPy bump.Enumerated divergence with a consequence: upstream's
ChatAdapter.__call__retries a failed parse throughJSONAdapterwith a differently-shaped prompt; this port makes one call. A reply missing either marker scores 0 here, so the number is a lower bound whose gap is exactlyn_unextracted.Alignment (updated — this section previously said neither had been done): the container hop is now exercised against the real
ghcr.io/nuprl/agnosticslua verifier at the digest this branch pins, and one paper cell is reproduced.0.58 pp, or 0.30 combined binomial σ (σ_D = 1.96 pp) — inside noise, which was the promotion criterion this PR set for itself. Upstream's README settings for Qwen 3:
temperature 0.2,top_p 0.95,max_tokens 2048,language "Lua /nothink", one completion. Verdicts: 74.5%fail:error, 11.7%fail:wrong-output, 10.7%success, 3.1%infra:timeout— the error-dominated mix the paper's own Figure 6 describes for base models on low-resource languages.Three caveats, all carried in the shipped docstring and
reference_impl.notesrather than only here, none of which moves the number out of noise:qwen3_8b_awq(AWQ 4-bit); OpenRouter's only Qwen3-8B provider reports quantization unknown. Same checkpoint, possibly different precision — recorded, not controlled;pass1counts a generation that produced no solution. They bias the number down: at the observed rate it would be 10.70;n_unextracted= 1).The other four languages and every other model in the table are unmeasured, and the docstring says so.
Test Plan
Automated
ruff check && ruff format --check)ty check) —mypyerrors on the new files are exactly the 8+1 repo-wideno-untyped-defstage-method pattern the siblinglivecodebench_code_generation_0shot_genalready has, no moremain, 48 of them new;check_preflight.py25/25 PASS (incl.check_links --level deep,check_meta_index_sync,check_reference_kind,check_report_declarations,check_dep_coverage)Manual
ChatAdapter.parse— all 10 parametrised expectations were produced by runningdspy==3.0.0b2's own parser on the same inputs, the indented-header offset bug included.uvicorn+ghcr.io/nuprl/agnosticsat its pinned digest, run underudocker(this box has no podman):success/fail:wrong-output/fail:errorcome back verbatim from the container,infra:timeout/infra:bad-lang/infra:no-testall fire, anddata.verifier_imagecarries the digest that ran. Control: a hand-written correct Lua solution scoressuccesson a real decoded LiveCodeBench suite while a deliberately wrong variant scoresfail:wrong-output— which is what rules out the base64→zlib→pickle→JSON decode and the whitespace handling as an explanation for any score.dspy==3.0.0b2— not just against its own hash. Installing the pinned library and rendering upstream's signature reproduces both the system and the user message byte-identically. (It also caught a mis-attributed comment: the 8-space indent isChatAdapter's own constant, not the source docstring's 4-space indent, whichSignature.instructionsdedents away. Fixed.)lua/jl/ml/f90resolve to their digests and report them;juliaandrustare refused asinfra:unpinned-lang; a{lang}-templated override reports no image (naming a digest that didn't run would be worse than naming none).Checklist
Required (all PRs)
type(scope): description)AI-Generated Code - <model> (<provider>)in module docstring — on all threesieval/+tests/files. Deliberately absent onvendor/code-evaluator/app/exec_agnostics.py: no file undervendor/carries it, and that patch is written to be landed inscitix/code-evaluatorupstream.core/—core/is untouchedIf: New or Modified Benchmark
15bef6bfwas downloaded and loaded: 5 parquet shards, 499 rows intest, exactly the loader's threestringcolumns. (Loaded via the pinned revision's snapshot rather than staged withsieval dataset download, to avoid a second 3.9 GB copy on a box at 96% disk.)check_taskssees 66 exports,__init__.pyiandmeta/index.jsonregeneratedIf: New Dependency
datasetsand the task onlyhttpx, both core;check_dep_coveragepasses with no new group.