How sde-bench tasks are built, and how to add a new one. Everything here lives in gen/ (vendored so
the dataset is self-contained). If you only want to run the benchmark, you don't need this file.
A task is a bug-fix where the obvious fix is wrong. Concretely, every task ships two tests:
- a repro (
regression_test.py) — the visible failure the user reports; red at HEAD. - a hidden test (
hidden_test.py) — held out from the agent; encodes the non-guessable policy.
A task is only valid if it discriminates — i.e. the hidden test can't be bluffed past:
| code state | existing/real tests | repro | hidden |
|---|---|---|---|
| HEAD (as shipped) | ✅ pass | ❌ fail | ❌ fail |
| correct fix | ✅ pass | ✅ pass | ✅ pass |
| naive fix (the obvious guess) | ✅ pass | ✅ pass | ❌ fail |
The naive column is the whole point: a plausible fix makes the reported bug go away but still violates the real policy. The policy is non-guessable — the only way to get it right is to have the decision in memory. The generator's validators assert exactly this table for every task before it's accepted.
Each task is tagged on three orthogonal axes (see DATASET.md for the full treatment):
- source — where the deciding rationale lives:
history— in the repo's git history (a real commit's rationale), later dropped by a regression. Reachable withgit log/blame. Example:boltons-omdset.conversation— only in a past developer chat (task.json.conversations), never written to the repo. Unreachable without a memory system that captured the chat. (9 of 10 tasks.)
- tier — how the trap is hosted (see next section).
- category — the kind of decision (
gen/categories.py): mapping, set-membership, numeric-policy, ordering, collection-merge, filter-rule, invariant.
Both tiers live inside the real boltons repo (so the agent gets real git-history noise and has to navigate a real codebase). The difference is what the buggy code is and what grades it:
The trap is a policy on an untested edge of an existing, real boltons function (e.g.
strutils.pluralize, strutils.slugify). Boltons' actual code doesn't implement your project's
policy — that gap is the bug. The agent edits the real function, and the fix is graded against
boltons' own real test suite (which must stay green) plus the repro and hidden tests.
- Authentic and harder: real code, real tests you must not break, nothing was fabricated for you.
build.py= check out boltons@979fa9b, trim the test suite to this module's real tests. No code is planted — the "bug" is simply that boltons never implemented the policy.- Defined in
gen/realfn_traps.py. Emitted bygen/emit_realfn.py.
The trap is a new, small module written into the boltons repo (e.g. retryx/retry.py,
pay/rounding.py) with a deliberately buggy implementation at HEAD. The agent fixes that module,
graded against the module's own tests + repro + hidden.
- Controlled: you author the code and the tests, so it's easier to make a clean, discriminating trap — but it still lives in the real repo (real history, real navigation).
build.py= check out boltons@979fa9b, write the package + buggy module + its existing test.- Defined in
gen/traps.py. Emitted bygen/emit_host.py.
One-line mnemonic: real-function = the bug is a real function that lacks your policy; planted = the bug is a new module you added. Real-function is graded by boltons' tests; planted by its own.
- Trap — a Python dict with everything needed to plant and validate the policy (fields below).
- Emit — an emitter turns a trap into a task directory (
build.py,tasks/main/{task.json, regression_test.py, hidden_test.py}). - Validate — rebuild the task and assert the discrimination table above.
real-function trap (gen/realfn_traps.py):
| field | meaning |
|---|---|
module |
the real boltons file to edit, e.g. boltons/strutils.py |
keep_tests |
boltons' real test files that grade this module (the pass_to_pass) |
anchor |
a unique snippet in the real function — the insertion point |
correct |
anchor replacement implementing the policy — validation only, not shipped |
naive |
anchor replacement = the obvious wrong guess — validation only |
repro_test, hidden_test, bug_report, conversation |
shipped in the task |
planted trap (gen/traps.py):
| field | meaning |
|---|---|
name, pkg, module, init, import_line |
the new module to plant |
bug / correct / naive |
full module sources (HEAD-buggy / right / obvious-wrong) |
existing_test |
the module's own test (stays green — the pass_to_pass) |
repro_test, hidden_test, bug_report, conversation |
shipped in the task |
decision_subject, decision_rationale, marker |
the H-commit text + answer-token (source isolation) |
correct/naive are never shipped to the agent — they exist only so the validators can prove the
task discriminates. The agent writes its own fix.
- Pick a real boltons function with an untested edge where your project needs a specific policy.
- Add an entry to
gen/realfn_traps.pywith the fields above.anchormust be a unique string in the current boltons source;correctmust make boltons' real tests + repro + hidden all pass;naivemust pass the repro but fail hidden. - Add the task's
categoryingen/categories.py. - Emit + validate:
Want
python gen/emit_realfn.py # emits every real-function task, then prints the discrimination tableHEAD=(True,False,False) CORRECT=(True,True,True) NAIVE=(True,True,False)for your task. python validate.py(structural) and commit.
- Add a trap dict to
gen/traps.py(a buggybugmodule, thecorrectpolicy,naiveguesses, and the tests) and include it in theTRAPS = {...}assembly at the bottom. - Add its
categoryingen/categories.py, and add its name to the emit loop ingen/emit_host.py. - Emit + validate:
python gen/emit_host.py # emits the planted tasks python gen/validate.py # proves discrimination + source isolation for the trap matrix
python validate.py(structural) and commit.
Note:
gen/emit_host.pyandgen/emit_realfn.pyoverwrite the task dirs they emit. They only run underif __name__ == "__main__", so importing them is safe, but running them regenerates tasks from the traps — re-run them only when you intend to (they are the source of truth going forward).
Both tiers build on top of a local clone of boltons, pinned at 979fa9b:
git clone https://github.com/mahmoud/boltons ~/dev/_sdebench_hosts/boltons
# or point elsewhere:
export SDEBENCH_BOLTONS_HOST=/path/to/boltonsBoltons is used unmodified as a fixture (cloned, not vendored) — its ~1600 real commits are the retrieval noise a memory system must rank against.
gen/core.py + gen/emit.py + gen/validate.py are an older, boltons-free path: they build a tiny
standalone library repo and plant a trap into its git history (source history) or only its conversation
(source conversation), emitting gen-<trap>-<source> dirs. The published dataset is entirely boltons-hosted,
so these aren't used, but the code is kept for authoring controlled synthetic tasks with full history.