Engineering

Four tries, still ahead: stock Qwen3.8 pass@4 60/89 (67.4%) and the two tasks that flipped

Round-4 (pass@4) Terminal-Bench 2.1 results for stock Qwen3.8 Flash Next mixed-4-8bit: 2 recoveries out of 31 retries, and why 29 still fail — repetition loops, premature submits, near misses

삽질하는개발자

시냅스 일러스트

TL;DR

Part 1 took the stock model from 45 (single pass) to 53 (two trials); Part 2 reached pass@3 58/89 and overtook the Uncensored (ARC4NUM, abliterated) build’s best-of-3 of 56. Round 4 reran the remaining 31 tasks under exactly the same conditions.

Result: pass@4 = 60/89 (67.4%). Two recoveries; 29 tasks failed all four times.

Trials Stock ddalcu Uncensored ARC4NUM
1 (pass@1) 45 / 89 (50.6%) 41 / 89 (46.1%)
2 cumulative 53 / 89 (59.6%)
3 cumulative 58 / 89 (65.2%) 56 / 89 (62.9%, best-of-3)
4 cumulative (pass@4) 60 / 89 (67.4%)

The increments are shrinking fast: 8 → 5 → 2. The curve is saturating, which means the remaining 29 are not failing on bad luck.

What happened in round 4

31 tasks: 2 recovered, 9 FAIL, 20 timeouts. 12h59m wall clock, 23.3 minutes per task on average. Both recoveries are tasks the Uncensored build failed all three times, so the stock-only column grows from 8 to 10.

extract-elf (2.6 min, 11 turns) — the reason it failed three times is instructive. The task asks for a Node.js parser that extracts memory words from an ELF binary. In round 3 the model noticed that the example values in the prompt (things like 0x6a617e69) did not match the file bytes, concluded the reference implementation “must generate fresh random values via angr symbolic execution”, and then repeated that same analysis paragraph for 15 minutes until timeout. In round 4 it decoded the example 1784774249 = 0x6A56F589 byte-swapped as 89 F5 56 6A = endbr64; push rbp — the start of .text — within two turns, walked the section headers, emitted 240 words, and passed. One initial hypothesis was the difference between a 15-minute loop and a 2.6-minute pass.

train-fasttext (full 60 min, 62 turns) — train a fastText classifier under accuracy and model-size constraints. Round 3 failed at 22 minutes on the size limit. Round 4 grid-searched dim/epoch/wordNgrams for accuracy, then quantized the model down to 65.4 MB at 0.6218 accuracy and saved it — and the clock ran out right after. The record says AgentTimeoutError, but the saved model passed both test_accuracy and test_model_size, so reward > 0 = PASS. Same “submitted just before the buzzer” pattern as mcmc-sampling-stan in Part 2.

Where they diverge (stock 4 trials vs Uncensored 3, all 89 tasks)

Bucket Count Tasks
Both pass 50
Both fail every trial 23 path-tracing family, regex-chess, feal-linear, make-*-mips, install-windows-3.11, compile-compcert, schemelike, …
Stock only 10 circuit-fibsqrt, custom-memory-heap-crash, dna-insert, llm-inference-batching-scheduler, mteb-leaderboard, qemu-startup, sparql-university, tune-mjcf, extract-elf, train-fasttext
Uncensored only 6 feal-differential-cryptanalysis, filter-js-from-html, model-extraction-relu-logits, overfull-hbox, polyglot-rust-c, winning-avg-corewars

All six Uncensored-only tasks failed again in round 4. winning-avg-corewars in particular — the Uncensored build passed it on its 1.0× rerun, while the stock model burned 60 minutes, 146 turns and 127K of context and timed out for the fourth time. At this point those six look like a real difference between the two models, not a trial-count artifact.

Anatomy of the 29 that still fail

The three buckets from Part 2 are unchanged, but round 4 made the specific shape of each much clearer.

① Repetition loops — this round’s main culprit. Three of the 20 timeouts were blatant loops.

  • schemelike-metacircular-eval 40 min · 188 turns · ctx 92K. The first 26 turns were legitimate work on a Scheme evaluator; the remaining 162 turns were the same message repeated. 0 of 63 tests passed.
  • winning-avg-corewars 60 min · 146 turns · ctx 127K. 39 normal turns, then 107 in a loop — again repeating, as in Part 2, a sentence about needing to “break out of this loop”.
  • regex-chess 60 min · 156 turns · ctx 120K. Better than round 3’s 322 turns, but the last 65 were a loop.

They share a signature. The loop always starts after 25–40 turns of normal work; once it starts, the model adds 0.4–1K tokens of context per turn and issues no new commands. terminus-2’s context summarization at ~122K occasionally breaks the loop, but the timeout usually arrives first. My conclusion has hardened: what a model this size needs is not more context, but a harness-side guard that forces a different action after N identical messages.

② Near misses. Two tasks failed just under the grading threshold.

  • rstan-to-pystan 18.2 min — port a Stan model to PyStan. The port works; posterior correlation ρ = 0.8813 against a threshold of ≥ 0.886. One sampling seed away.
  • query-optimize 9.2 min — 5 of 6 tests pass. The last one measures the optimized query at 0.970 s against a limit of 1.05× the golden query’s 0.759 s. In all four trials the model declared it “fast enough” and submitted.

③ Premature confident submits. Still there. overfull-hbox 3.8 min, raman-fitting 3.4 min, sanitize-git-repo 3.9 min — under a fifth of the budget, then “verified and complete”. video-processing spent 17.9 minutes building a pipeline and submitted, only to hit the grader’s assert 240 <= 223 (too many frames). Every round adds evidence that the model’s self-verification is looking at something other than what the grader checks.

23 of the 29 are tasks the Uncensored build also failed every time. And both of this round’s recoveries came from Uncensored-all-fail tasks — which also says the stock model is the one with more headroom left under retries.

Ops notes

Thirteen hours, zero server restarts, zero wedges, zero 400 context-overflow errors. Server uptime passed 2 days 12 hours. While the 100K+ context tasks ran (filter-js-from-html 101K, path-tracing-reverse 123K, regex-chess 120K, corewars 127K), the kernel swapped mlx-serve pages out and memory headroom dropped to 18%, recovering to the 80s once each task finished. Nothing in Part 2’s infrastructure (120-second watchdog timeout, automatic image cleanup) needed touching.

One lesson: the watchdog had been restarting the server into a new log file, and I was tailing the old one when I suspected a “server stall”. Diagnose stalls from the log the server is actually writing. The seven minutes without a new turn was the agent running a long command, not the server.

Next

Round 5 (pass@5) on the remaining 29 is already running. The official Terminal-Bench protocol is 5 trials, so this completes the stock side. Expectations match round 4 — zero to two recoveries, and if any, from the near-miss (rstan, query-optimize) or premature-submit buckets.

One-line summary: on the fourth try the stock model is still ahead — 60 vs 56 — and both tasks that flipped were ones the Uncensored build never solved.