| # | Finding | Status |
|---|---|---|
| 1 | A 14-task, single-run grid cannot rank these builds. 16 of 17 fall in one band; 1 separates from the rest. | reproducible |
| 2 | Truncation moves scores. 14 task results are incomplete (cut off at the token cap, or errored). 4 of them satisfied a rule on their visible text and used to be counted as passes. They are now unknown, not passes. | reproducible |
| 3 | Task 1 does not measure obedience to a tool contract. The model is never told the sequence it is scored against. Of 14 failing answers, 7 contain sed and most never emit write_file. | reproducible |
| 4 | Where builds differ, they differ by task, not along a single axis (matrix below). | reproducible |
Sorted by passes out of all tasks: an incomplete answer counts against, because a build that cannot finish a task inside the cap has not delivered it. The ceiling is the rate if every incomplete answer had passed. A build joins the current band while its 95% Wilson interval overlaps its band leader's. The interval reflects only which 14 tasks were chosen; run-to-run noise needs repeated runs. Builds in one band are not ranked against each other.
| Band | Build | Pass | Fail | Inc. | Rate | 95% interval | Ceiling | Old* |
|---|---|---|---|---|---|---|---|---|
| 1 | kat-coder-v2.5-dev-35b-a3b-mtp-abliterated-i1 | 14 | 0 | 0 | 1.00 | 0.79–1.00 | 1.00 | 14 |
| 1 | dirk-qwen3.8-27b | 13 | 1 | 0 | 0.93 | 0.69–0.99 | 0.93 | 13 |
| 1 | ista-daslab-qwen3.8-27b-gsq-rco-unsloth-mtp | 13 | 1 | 0 | 0.93 | 0.69–0.99 | 0.93 | 13 |
| 1 | qwen3.8-27b-cold-fusion-gain-v1.1-nm-dau-neo… | 13 | 1 | 0 | 0.93 | 0.69–0.99 | 0.93 | 13 |
| 1 | qwen3.8-27b-twin-turbo-fable-cold-fusion-709… | 13 | 1 | 0 | 0.93 | 0.69–0.99 | 0.93 | 13 |
| 1 | tiel-coder-35b-a3b-mtp | 13 | 1 | 0 | 0.93 | 0.69–0.99 | 0.93 | 13 |
| 1 | gemma-4-26b-a4b-it-qat-claude-opus-distill-v2 | 12 | 2 | 0 | 0.86 | 0.60–0.96 | 0.86 | 12 |
| 1 | nex-agi_nex-n2.5-mini | 12 | 2 | 0 | 0.86 | 0.60–0.96 | 0.86 | 12 |
| 1 | swift-qwen3.8-27b | 12 | 2 | 0 | 0.86 | 0.60–0.96 | 0.86 | 12 |
| 1 | minicpm5-2b | 12 | 1 | 1 | 0.86 | 0.60–0.96 | 0.93 | 12 |
| 1 | qwen3.8-27b@q4_k_s | 12 | 1 | 1 | 0.86 | 0.60–0.96 | 0.93 | 13 |
| 1 | gemma-4-a4b-98e-v7-coder-it | 11 | 3 | 0 | 0.79 | 0.52–0.92 | 0.79 | 11 |
| 1 | nvidia-nemotron-3.5-lightning-30b-a3b-mtp | 11 | 3 | 0 | 0.79 | 0.52–0.92 | 0.79 | 11 |
| 1 | qwen3.8-27b@q4_k_xl | 11 | 2 | 1 | 0.79 | 0.52–0.92 | 0.86 | 12 |
| 1 | qwen3.8-27b@q5_k_m | 11 | 2 | 1 | 0.79 | 0.52–0.92 | 0.86 | 12 |
| 1 | qwopus3.8-27b-flash-1m | 8 | 0 | 6 | 0.57 | 0.33–0.79 | 1.00 | 8 |
| 2 | qwen3.8-27b-gsq-rco | 3 | 7 | 4 | 0.21 | 0.08–0.48 | 0.50 | 4 |
* "Old" counts an incomplete answer as a pass when its visible text satisfies the rule. It is what the earlier hand-written table used, shown for continuity only.
P passed · · failed · ? incomplete (cut off or errored). Rows keep band order; read across a row, not down to a rank.
| Build | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| kat-coder-v2.5-dev-35b-a3b-mtp-abliterated-i1 | P | P | P | P | P | P | P | P | P | P | P | P | P | P |
| dirk-qwen3.8-27b | P | P | P | P | P | P | P | P | P | P | P | P | · | P |
| ista-daslab-qwen3.8-27b-gsq-rco-unsloth-mtp | · | P | P | P | P | P | P | P | P | P | P | P | P | P |
| qwen3.8-27b-cold-fusion-gain-v1.1-nm-dau-neo… | · | P | P | P | P | P | P | P | P | P | P | P | P | P |
| qwen3.8-27b-twin-turbo-fable-cold-fusion-709… | P | P | P | P | P | P | P | P | P | P | P | P | · | P |
| tiel-coder-35b-a3b-mtp | · | P | P | P | P | P | P | P | P | P | P | P | P | P |
| gemma-4-26b-a4b-it-qat-claude-opus-distill-v2 | · | P | P | P | P | P | P | · | P | P | P | P | P | P |
| nex-agi_nex-n2.5-mini | · | P | P | P | P | P | P | · | P | P | P | P | P | P |
| swift-qwen3.8-27b | · | P | P | P | P | P | P | · | P | P | P | P | P | P |
| minicpm5-2b | · | P | P | P | ? | P | P | P | P | P | P | P | P | P |
| qwen3.8-27b@q4_k_s | · | P | P | P | P | P | P | P | P | P | P | P | ? | P |
| gemma-4-a4b-98e-v7-coder-it | · | P | P | P | P | P | P | · | P | P | P | P | · | P |
| nvidia-nemotron-3.5-lightning-30b-a3b-mtp | · | P | P | P | P | P | P | · | P | · | P | P | P | P |
| qwen3.8-27b@q4_k_xl | · | P | P | P | P | P | P | · | P | P | P | P | ? | P |
| qwen3.8-27b@q5_k_m | · | P | P | P | · | P | P | P | P | P | P | P | ? | P |
| qwopus3.8-27b-flash-1m | ? | ? | P | P | P | P | P | ? | P | P | P | ? | ? | ? |
| qwen3.8-27b-gsq-rco | · | P | · | · | ? | · | ? | · | · | ? | P | ? | P | · |
| # | Task | Pass | Incomplete | Old* |
|---|---|---|---|---|
| 1 | Structured Tool-Call Generation | 3/17 | 1 | 3/17 |
| 2 | Multi-Step Agentic Planning | 16/17 | 1 | 16/17 |
| 3 | Code Repair with Context | 16/17 | 0 | 16/17 |
| 4 | API Contract Extraction | 16/17 | 0 | 16/17 |
| 5 | Dependency Analysis | 14/17 | 2 | 14/17 |
| 6 | Refactoring with Safety | 16/17 | 0 | 16/17 |
| 7 | Error Recovery Simulation | 16/17 | 1 | 17/17 |
| 8 | Test Generation | 9/17 | 1 | 9/17 |
| 9 | Concurrency Reasoning | 16/17 | 0 | 16/17 |
| 10 | Schema Inference | 15/17 | 1 | 15/17 |
| 11 | Prompt-to-Code (Agentic) | 17/17 | 0 | 17/17 |
| 12 | Debugging with Evidence | 15/17 | 2 | 15/17 |
| 13 | Architecture Decision | 10/17 | 4 | 13/17 |
| 14 | Security Audit | 15/17 | 1 | 15/17 |
Task 1 — Structured Tool-Call Generation. The prompt asks for "the exact tool-call sequence" to find Python files importing requests and replace requests.get with httpx.get. The scoring rule requires search → read → write. That sequence appears only in the hidden pass criteria; the runner removes them before the prompt is sent.
| What the answer did | Builds |
|---|---|
| never reaches write_file | 13 |
| pass | 3 |
| incomplete (cut off or errored) | 1 |
A failing answer from qwen3.8-27b@q5_k_m — one command, which does what the request says:
{"tool":"run_command","args":{"cmd":"grep -RlE 'import requests\\b' --include='*.py' . | xargs -r sed -i -E 's/\\brequests\\.get\\b/httpx.get/g'"}}
A passing answer from dirk-qwen3.8-27b:
{"tool":"search_code","args":{"pattern":"import requests","glob":"*.py"}}
{"tool":"read_file","args":{"path":"<each file from search result>"}}
{"tool":"write_file","args":{"path":"<same file path>","content":"<original content with all 'requests.get' replaced by 'httpx.get'>"}}
From a previous hand-written report; the raw data is not in this repository. Treat these as claims.
PASS = the final report holds all four facts (Java version, 74 tests, APK size, "no file changed"), the project was not touched, the session ended on its own. ~ PARTIAL = at least two facts. x FAIL = anything else (did not finish, endpoint error, 10-minute timeout, wrote into the project, fewer than two facts). Bands use the same rule as the grid above: a model joins the band while its 95% Wilson interval overlaps the band leader's. With three runs the intervals are wide, so expect few bands; models in one band are not ranked against each other.
Repeated models. 14 models ran at least twice; 2 passed every run; 4 had the same verdict in every run. Across the 42 runs of these models: pass: 17, partial (2 or 3 facts): 14, 10-minute timeout: 6, wrote into the project: 4, report holds fewer than 2 facts: 1.
Even the best against the worst separate only weakly: 3 of 3 against 0 of 3 gives a Fisher exact two-sided p = 0.10. Three runs per model can order the extremes, not the middle.
2 of the 16 qualifying models (nail-qwen3.6-35b-a3b-mtp, qwen3.8-27b-omnimerge-v6-mtp) were no longer installed in LM Studio when runs 2 and 3 were made, and keep their single run-1 result.
| Band | Model | Runs | Verdicts | PASS · 95% interval | Median s | Median tokens | VRAM GB | Context | Repeats |
|---|---|---|---|---|---|---|---|---|---|
| 1 | holo4-35b-a3b-i1 | 3 | P P P | 3/3 · 0.44–1.00 | 176 | 44192 | 20.2 | 100000 | yes |
| 1 | cyber-tiel-coder-35b-a3b-apex-i-nanoplus | 3 | P P P | 3/3 · 0.44–1.00 | 368 | 54395 | 15.4 | 100000 | yes |
| 1 | kat-coder-v2.5-dev-apex-i-miniplus-v2.1 | 3 | P x P | 2/3 · 0.21–0.94 | 200 | 66490 | 16.8 | 100000 | no |
| 1 | qwen3.8-27b-twin-turbo-fable-cold-fusion-709-l | 3 | P ~ P | 2/3 · 0.21–0.94 | 207 | 37992 | 23.2 | 100000 | no |
| 1 | dirk-qwen3.8-27b | 3 | P P ~ | 2/3 · 0.21–0.94 | 301 | 78740 | 19.3 | 100000 | no |
| 1 | orchestra-o1-8b | 3 | ~ P ~ | 1/3 · 0.06–0.79 | 195 | 31953 | 20.0 | 100000 | no |
| 1 | neohorse-1-4b | 3 | ~ ~ P | 1/3 · 0.06–0.79 | 334 | 82865 | 6.9 | 100000 | no |
| 1 | aztec-coder-4b | 3 | x P x | 1/3 · 0.06–0.79 | 358 | 65831 | 6.6 | 100000 | no |
| 1 | kiwen1.1-27b-mtp | 3 | P x ~ | 1/3 · 0.06–0.79 | 400 | 67764 | 20.4 | 100000 | no |
| 1 | neohorse-1-9b | 3 | P ~ x | 1/3 · 0.06–0.79 | 484 | 114450 | 9.0 | 100000 | no |
| 1 | oxcoder-9b-mernik | 3 | x ~ ~ | 0/3 · 0.00–0.56 | 264 | 73509 | 8.9 | 100000 | no |
| 1 | orchestrator_v1_gguf | 3 | ~ ~ ~ | 0/3 · 0.00–0.56 | 269 | 95701 | 5.6 | 100000 | yes |
| 1 | nex-n2.5-mini-apex-i-miniplus-v2.1 | 3 | x ~ x | 0/3 · 0.00–0.56 | 543 | 75315 | 17.5 | 100000 | no |
| 1 | minicpm5-2b | 3 | x x x | 0/3 · 0.00–0.56 | – | – | 5.6 | 100000 | yes |
Screened once, not repeated. These did not meet the repeat rule in run 1. One run is an observation, not evidence that a model fails reproducibly.
| Model | Runs | Verdicts | PASS · 95% interval | Median s | Median tokens | VRAM GB | Context | Repeats |
|---|---|---|---|---|---|---|---|---|
| qwen3.8-27b-omnimerge-v6-mtp | 1 | P – – | 1/1 · 0.21–1.00 | 345 | 64150 | 23.2 | 80000 | n=1 |
| nail-qwen3.6-35b-a3b-mtp | 1 | ~ – – | 0/1 · 0.00–0.79 | 134 | 50787 | 23.0 | 100000 | n=1 |
| spark-x2.5-4b | 1 | x | 0/1 · 0.00–0.79 | – | – | 7.4 | 100000 | n=1 |
| hunter-4b | 1 | x | 0/1 · 0.00–0.79 | – | – | 17.5 | 100000 | n=1 |
| tiel-coder-35b-a3b-apex-i-miniplus-v2.1 | 1 | x | 0/1 · 0.00–0.79 | – | – | 17.2 | 100000 | n=1 |
| vibe-coder-7b-max | 1 | x | 0/1 · 0.00–0.79 | – | – | 10.5 | 100000 | n=1 |
| nvidia_orchestrator-8b | 1 | x | 0/1 · 0.00–0.79 | – | – | 19.1 | 100000 | n=1 |
| captaineris-davidau-fusion-12b-i1 | 1 | x | 0/1 · 0.00–0.79 | – | – | 22.8 | 100000 | n=1 |
| lfm2.5-8b-a1b-qwen3.8-turbo-brilliance-power-x | 1 | x | 0/1 · 0.00–0.79 | – | – | 10.5 | 100000 | n=1 |
| liquid/lfm2.5-1.2b | 1 | x | 0/1 · 0.00–0.79 | – | – | 3.1 | 100000 | n=1 |
| ornith-1.5-9b-nvfp4-mtp | 1 | x | 0/1 · 0.00–0.79 | – | – | 9.4 | 100000 | n=1 |
| triumvirate-qwopus-mimo-ornith-9b-coder | 1 | x | 0/1 · 0.00–0.79 | – | – | 9.8 | 100000 | n=1 |
| nemotron-orchestrator-8b | 1 | x | 0/1 · 0.00–0.79 | – | – | 19.3 | 100000 | n=1 |
| humo-coder-35b-a3b | 1 | x | 0/1 · 0.00–0.79 | – | – | 19.6 | 65000-auto-offload | n=1 |
| plano-orchestrator-4b | 1 | x | 0/1 · 0.00–0.79 | – | – | 17.6 | 100000 | n=1 |
| qwen3.8-27b-orcarouter-gsq-rco-uncensored | 1 | x | 0/1 · 0.00–0.79 | – | – | 19.0 | 100000 | n=1 |
Addendum: the two missing models, one extra run each. Both were reinstalled after runs 2 and 3 and run once, same prompt and settings, outside the registered protocol. They do not change the table above.
| Model | Verdict | Seconds | Tokens | Tool calls | Context | Note |
|---|---|---|---|---|---|---|
| nail-qwen3.6-35b-a3b-mtp | x | 350 | 171328 | 28 | 100000 | wrote into the project |
| qwen3.8-27b-omnimerge-v6-mtp | P | 278 | 66904 | 12 | 80000 |
| Configuration | Model | Verdicts | Median s |
|---|---|---|---|
| KV cache q8_0; sampling from the model cards (temperature 0.6, top_p 0.95, top_k 20, repeat 1.0; min_p 0 for holo4, 0.05 for cyber-tiel) | holo4-35b-a3b-i1 | ~ P ~ | 149 |
| KV cache q8_0; sampling from the model cards (temperature 0.6, top_p 0.95, top_k 20, repeat 1.0; min_p 0 for holo4, 0.05 for cyber-tiel) | cyber-tiel-coder-35b-a3b | x ~ P | 339 |
| KV cache q4_0; sampling from the model card (temperature 0.6, top_p 0.95, top_k 20, min_p 0, repeat 1.0) | holo4-35b-a3b-i1 | ~ ~ x | 156 |
| KV cache q8_0; sampling as the owner normally sets it (temperature 0.7, top_p 0.90, top_k 20, min_p 0, repeat 1.0) | holo4-35b-a3b-i1 | ~ ~ P | 158 |
Each was downloaded later and run with a fixed LM Studio configuration saved next to the result: context 100000, KV cache q8_0, temperature 0.7, top_k 20, top_p 0.90, min_p 0, repeat penalty 1.0. Only one model, Qwen3.8 27B GSQ RCO (IQ3_S), got repeats: it passed in two of three confirmatory runs and in its first screening run. The dense Holo4 27B was run once at the registered 10-minute limit and three times at 20 minutes; the extra time did not change the outcome. Published benchmark scores for that model are for computer-use tasks, which this verification task is not. One run per model is an observation, not a ranking.
| Model | Runs | Verdicts | Median s | VRAM GB | Limit | Note |
|---|---|---|---|---|---|---|
| qwen3.6-35b-a3b | 3 | x ~ P | 209 | 21.9 | 10 min | |
| qwen3.8-27b | 3 | P P P | 244 | 22.1 | 10 min | |
| qwen3.8-27b-gsq-rco | 4 | P x P P | 335 | 18.2 | 10 min | |
| holo4-35b-a3b-i1@q4_k_m | 1 | ~ | 217 | 22.2 | 10 min | |
| cyber-tiel-coder-35b-a3b.apex-i-miniplus-v2.1 | 1 | x | 601 | 17.0 | 10 min | |
| eikos-27b | 1 | x | 600 | 23.3 | 10 min | |
| holo4-27b | 4 | x x x x | 974 | 20.2 | 20 min (3 runs) and 10 min (1 run) | |
| holotron-12b | 1 | x | 601 | 9.8 | 10 min | |
| hcompany.holotron4-30b-a3b | 1 | – | – | 0.0 | 10 min | does not fit in 24 GB VRAM |
| qwen3.8-27b-iu4-kairic-edge | 1 | – | – | 0.0 | 10 min | not loadable: the installed engine rejects its tensor type |
| qwen3.8-27b-turbo-fable-cold-fusion-735-882-he | 1 | – | – | 0.0 | 10 min | does not fit in 24 GB VRAM |
| Model | v1 · before | v2 · first corrections | v3 · regression corrected | v4 · quoting corrected | v5 · latest outputs | v6 · closing after refusals | v7 · replan, write rule, probes | v8 · verifier, whole task | v9 · after the review | v10 · shell inspection | v11 · audit items, OS overlay | v12 · gate and detectors (scorer 3) | v13 · external patch (scorer 3) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| qwen3.8-27b | P P P | x x ~ | ~ ~ P | P P P | x P x | P x ~ | P P x | ~ P P | x P P | ~ P ~ | ~ x ~ | P ~ ~ | P x ~ |
| qwen3.8-27b-gsq-rco | P x P | x P x | P P P | ~ P P | P P ~ | P x P | P P x | P x ~ | ~ ~ P | x P P | P x P | P P ~ | P P P |
| cyber-tiel-coder-35b-a3b-apex-i-nanoplus | n/a | P P ~ | P P P | ~ P P | P P P | P P P | P x P | P P P | P ~ P | P P P | P ~ P | x ~ P | P ~ P |
| holo4-35b-a3b-i1 | ~ ~ P | P ~ P | P P ~ | ~ P ~ | ~ P P | ~ ~ P | P P ~ | ~ ~ ~ | ~ ~ ~ | ~ x ~ | ~ P ~ | ~ ~ ~ | ~ P ~ |
v1 has no run of cyber-tiel under these exact settings; v1 for holo4 is the replication cell with the same settings. Each cell is three runs, in order.
| Arm version | Runs | PASS | Wrote into the project | Commands refused by the read-only policy | Report with 2 or 3 of 4 facts |
|---|---|---|---|---|---|
| v1 · as first run | 9 | 6 | 0 | not recorded | 2 |
| v2 · first corrections (with a regression) | 12 | 5 | 1 | not recorded | 5 |
| v3 · regression corrected | 12 | 9 | 0 | 6 | 3 |
| v4 · quoting and scratch paths corrected | 12 | 8 | 0 | 0 | 4 |
| v5 · report step given the latest command output | 12 | 8 | 0 | 14 | 4 |
| v6 · tool use closed after repeated refusals | 12 | 7 | 0 | 1 | 5 |
| v7 · replan, one definition of a write, early probes kept | 12 | 8 | 0 | 0 | 3 |
| v8 · verification lane given the whole task | 12 | 6 | 0 | 0 | 5 |
| v9 · corrections after the outside review | 12 | 5 | 0 | 1 | 6 |
| v10 · a read-only shell command counts as inspection | 12 | 6 | 0 | 0 | 4 |
| v11 · audit items, capability model, OS overlay | 12 | 5 | 0 | 0 | 5 |
| v12 · gate sees what the policy refuses, detector fixes, noise fixes (scorer 3) | 12 | 4 | 0 | 0 | 8 |
| v13 · external patch applied unmodified, new flags off (scorer 3) | 12 | 7 | 0 | 0 | 5 |
What the tables show. The pass count moves within noise from v3 to v14 (9, 8, 8, 7, 8, 6, 5, 6, 5, 4, 7 and 7 of 12; three runs per model neither show a decline nor exclude one), so the corrections cannot be credited with a better model score. What changed is the mechanism: in v4 no run wrote into the project and the read-only policy refused no command, where v3 had six refusals of read-only commands and v2 refused the builds the task asked for. A correction was judged by the failure it removed, not by the pass rate. v5 did not do what it was meant to: giving the report step the latest command output left the number of reports lacking a fact at 4 of 12 (the missing test count fell from 4 to 3 runs, other facts went missing instead). In v5 the policy refused 14 calls, all of them the same model asking again and again to write a file into the read-only project in one run, which ended at the time limit: the refusal was right, and the model had no way out of it.
v6 closes tool use for the rest of a step after five refused calls. It was judged against four criteria written before the runs: no run writes into the project (met, 0 of 12); no read or build command is refused wrongly (met, one refusal in twelve runs, a real attempt to create a source file); a closed step ends in text (not exercised: the limit was never reached, so it is shown by a unit test and not by a live run); no clear fall in passes (met, 7 of 12 against 8 in v5). The same open faults showed again: one run ended at the time limit after the evidence gate refused the final step three times, and the test count was missing from two of three reports of one model.
v7 let a replan depend on steps already done, gave the evidence gate and the read-only policy one definition of a write (a log written to a temp directory is not a change to the project), and kept early command output for the report step. Its four criteria, written before the runs, were all met: no write into the project; no "files changed: none" refused because of a temp-directory write; fewer than four reports with two or three of four facts (three); at least six passes (eight).
v8 corrected a real fault found by reading the logs: the lane that revises a draft was shown only the tool output of the last step, which runs nothing, so it saw "none" and softened true reports into "unable to report"; its evidence summary also kept the first eight items, which cut the build and the listing at the end of a task. Its live result did not show the expected effect, and its criteria were not met: no write into the project (met), but one "no change" contradiction (not examined), six reports with a fact missing against a target of at most two, and six passes against a target of eight. The missing fact is the test total in six of twelve runs; reading the reports shows that part of this is a model listing the per-class counts without adding them up, which the check does not accept. The check is a stricter proxy than the wording of the task, so this measure mixes two things. The correction stays because the fault was real and a test shows it; the live data do not show that it helped.
v9 carried the corrections made after the outside review (the read-only filter, the evidence gate for a report backed by a test run, the labelling of command output, the scope of the data given to another endpoint). It was judged against four criteria written before the runs. Met: no run wrote into the project (0 of 12); no read or build command was refused wrongly (one refusal, a real attempt to use a writing tool). Not met: the evidence gate refused in at most three of twelve runs (it refused in seven, as in v8) and at least seven passes (five). The correction to the gate for a report backed by a test run therefore did not lower the number of refusals in live runs: that defect does not explain most of them, and their cause stays open. No correction made after the review had, at that point, shown an effect in a live run.
v11 carries the open items of the outside audit: more shell writers denied; a core of "writes the project" (the writer commands, touch, the scratch rule) shared by the tool policy and the evidence gate, which still differ on a substitution, a delete after a pipe and an interpreter write; a quoted absolute path counts as scratch only under the workspace's own scratch directories; a capability model that refuses a tool nobody classified; secrets replaced before text leaves for a different verifier endpoint; and, switched on by a flag for this batch, the workspace of a read-only task mounted by the operating system as a throwaway overlay (checked first on one real project: the build and the unit tests ran inside it and the project on disk did not change; it was applied in all 12 runs). Criteria written beforehand: no write into the project (met, 0 of 12); at most three runs with a gate refusal (met: two); at least six passes (not met: five; the second scorer, which also accepts per-class test counts, gives eight); no read or build command refused wrongly and no build broken by the overlay (met). All eleven refusals came from one rule that read the word "wrote" in a shell command or its output as a file write; it was corrected afterwards, which is why the pass count fell short. The gate diagnostics found two defects of the same kind while this batch was prepared: a write the runner had recorded to a scratch directory counted as a change (a first attempt was stopped after three runs and is not counted), and the same wording rule. A confirmation batch of the corrected build is registered before its runs. What is and is not shown: the overlay was checked on one project, whose Android SDK lies inside it; a project with a toolchain in the home directory needs it left off. The capability model refuses unknown tools in a read-only task, which a custom tool may need to be told to pass. Read-only remains a best-effort guard, not a security boundary.
One more model, collected as data only (arm-iterations/v11-kat-addendum, same task, same settings, 100,000 tokens of context loaded, 23.7 GB of 24): a code model of about 22 GB passed 3 of 3 runs, 185 to 255 seconds, no write and no refused command. Three runs do not rank it.
A batch that measured the wrong thing, and a change of instrument. A confirmation batch of the arm after v11 came out with every report scored PARTIAL, with only the test total missing. It was not the arm: between two batches the project had gained a test (the owner had asked a model to add one in the application window), so it now held 75 tests, and the two earlier scorers look for the literal 74 or for four fixed class counts. The reports said 75, and were right. The batch was set aside as invalid for scoring (seven complete runs, published separately as v12-invalid-ground-truth-75-tests, one interrupted run recorded as interrupted and not as a failure) and not repeated as if nothing had happened. Scorer 3 reads the expected test counts from the project's own result files at the start of each run and stores them with the run; it was fixed before the next batch, v1 and v2 stay as they were, and only runs that carry scorer 3 are scored with it (the v12 and v13 columns). Recomputing the seven invalid runs after the fact with 75 gives 4 passes; that is labelled as such and not counted in any column.
v12 (build with the wording-rule fix, a detector that no longer reads "explain how to fix" as a request to change, a gate that sees what the policy refuses, scratch targets written with $PWD, an overlay that refuses symlinked scratch directories, and two noise fixes: no ghost banner on a plan step that is already done, middle steps told not to write the final report). Criteria written beforehand: no write (met, 0 of 12); at most three runs with a gate refusal (met: none, the first batch with no refusal at all); at least six passes (not met: four); no command refused wrongly (met). Four reports were incomplete in a fact other than the test total, against one or two in the three earlier batches; the cause is not established (a planner change that tells middle steps not to write the report is the candidate, twelve runs do not show it) and it is stated as open.
v13 applies an external audit patch unmodified (hashes of the ten files equal to the manifest of its author; type check, its own 146 tests, the golden regression and the full suite equal to the recorded red baseline apart from one check that needs the new files committed). It budgets the tool schemas offered to a local model, validates the arguments of a hidden target tool before it runs, gives the count request its own deadline, and widens the loopback detector. Its two opt-in flags were left off, so the batch measures only the default-on changes. Criteria written beforehand: no write (met), at most three runs with a refusal (met: none), at least four passes, the v12 figure (met: seven of twelve), nothing new in the logs about schemas, validation or the count hook (met). Seven against four is not an improvement that twelve runs can separate, and with the flags off the new paths barely run: this shows that the patch did not break the task, not that it helps. The effect of the two flags is not measured.
v14 applies a second external audit patch unmodified, its new flags off: 7 of 12 passes, the same as v13; no run wrote into the project; two runs hit the 600 s limit and two did not finish. No criteria were frozen for this batch, so it is reported as it came out (arm-iterations/v14-external-patch-v3).
cmp1, a head-to-head with the rules frozen first (comparisons/criteria-cmp1.txt): the previous line of the arm against the next one, three runs per model, interleaved. 7 of 12 passes against 3 of 12; Fisher exact two-sided p = 0.214, so there is no separable difference, and the direction does not favour the next line. Latency (median 325 s against 304 s) is also not separable. No write, no refusal, no new failure kind in the logs. Success and latency are reported apart, and unfinished runs and 600 s limits stay in the denominators as the harness scored them.
cmp2 was stopped early by the operator after 25 of its 40 planned runs, so it has no verdict. Partial counts, noise at this size: on the prompt where the patch's new report lane can engage, 5 of 8 passes without the patch and 2 of 8 with it (the lane engaged in 4 of those 8); on the control prompt, 3 of 5 and 2 of 4 (lane never engaged, as designed). Nothing was written into the project. The patch was adopted for a different reason, not because of this comparison.
Five more external patches were applied one at a time, each unmodified in its own commit, every repair in a separate commit, each compared by failing-test identity against the same baseline and against a golden set. The checks found tests that pinned source text rather than behaviour and, in my own earlier repair, a refusal recognised by its output text, which a second review showed could hide a real write; it is now a typed signal. No live gain from these patches is measured. Manual runs in the application window then found four faults in the interface layer that scripted runs cannot see (a missing Stop control during a session's first run, an internal refusal code quoted to the user, a finished task's report thrown away, an approved plan run as one turn); three are fixed and tested, one is open. See field-notes/2026-10-10-manual-runs-what-the-harness-missed.md.
Correction 9. The per-version table recomputed a verdict that cannot see whether a run finished. One cell was wrong (v12, holo4, run 2 should be x); no pass count changed. See CORRECTIONS.md.
One scenario in the application window (an owner-run check of a build with the corrections, one model, one coding task: add one unit test to an existing class): the read-only policy did not switch on, every step after the first received the record of files written, no ghost banner appeared, the file list in the report was correct and explained, and the test count on disk matched the report. A report-like message still appeared in one middle step, so the report showed twice, down from three or four times. The test the model added asserted on a local value and did not call the code under test, in the style of the class it was added to; it was replaced afterwards by one that calls the real method. This is one scenario, so it is "validated on one scenario", not on the build.
A second batch of the v10 arm (same behaviour; the gate log gained diagnostics, the harness stores the full report and a second test fact that also accepts the four per-class counts, fixed before the runs). Criteria written beforehand were all met: no write (0 of 12), gate refusals in 2 of 12 runs, 7 passes against a target of 6, no wrongful refusal. Scorer v2 changed no verdict (7 of 12 under both): the reports that lacked the test fact gave one class count (three holo4 runs) or counts the model itself said it had inferred, so the limit seen in v10 did not recur as a formatting problem. The diagnostics located the refusals: all three fell on the first step of a plan, before that step had run a tool, and the earlier lead of a refusal with a counted write did not recur. Reading the logs resolved it: in those runs step 1 ended twice with text and no tool call, and the gate correctly refused text that claimed results without evidence; on an intermediate step the runner treats the refusal as advisory, so it did not stop the run. It is the model answering before running anything, not a gate defect, and the criterion counts these advisory refusals too.
v10 followed from a measurement, not a guess. The gate was made to report the conditions of its read-only exemption, and for a report whose only evidence was a listing it said that no inspection had happened: its evidence text holds tool outputs, not commands, and models inspect almost only through the shell. A shell command that writes nothing and prints something now counts as an inspection, as it already did in the read-only policy. Criteria written before the runs: no write into the project (met, 0 of 12); the gate refused in at most three of twelve runs (met: two, against seven in v8 and v9, the first correction that showed its effect live); at least seven passes (not met: six); no read or build command refused wrongly (met, none). The gate is therefore not what held the pass count down. In five of the twelve runs the only missing fact is the test total, and in four of them it is the only fact missing: a report listing the per-class counts without adding them up is scored as missing it. The scorer is a stricter proxy than the task's wording, so most of what separates six passes from ten is a property of the measurement, not of the arm; a scorer that accepts the per-class counts would have to be fixed beforehand and applied to every version, and has not been written. The two refusals left (one run where the gate saw a mutation although the policy refused no write, one where it was handed a single observation) are leads, not explanations.
| # | Defect in the arm | How it showed | Correction | State |
|---|---|---|---|---|
| 1 | Bookkeeping calls (plan, report) counted as file writes by the evidence gate | A truthful "no files changed" report was refused five times in one run | Those calls are left out of the free-text write heuristic | fixed |
| 2 | A "write a file now" directive sent to a task that forbade writes | A verification step was told to write | The directive is never sent on a read-only task | fixed |
| 3 | "Do not modify any file" was only a request | Models wrote report files or unpacked artefacts into a read-only project; one used about 790k tokens | Tool-level read-only policy on by default | fixed (see 4) |
| 4 | That policy refused the builds the task ordered | A stderr merge was read as a file redirect; the dense base model went from 3 of 3 to 0 of 3 | Descriptor duplication and scratch or build directories are not writes; a test for this was added | regression found by the rerun, fixed |
| 5 | A quoted character and a log under the project's own scratch directory were refused | Six refusals of read-only commands in one model's runs | Quoted text is data; a payload passed to a shell is judged on its own | fixed |
| 6 | The runner wrote a note into the project it was told not to change | One run counted as modified | The note is not written on a read-only task | fixed |
| 7 | A model that could not be loaded was reported as a protocol problem | HTTP 400 with a hint pointing at the wrong settings | A message that names memory, context and quantization | fixed |
| 8 | The final step does not receive the raw output of earlier steps | Four of twelve reports lack one fact (usually the test count) in v4 and again in v5 | v5 passed the last lines of the latest commands to the report step, v7 kept the early ones too, v8 fixed the lane that revises the draft; none lowered the count of incomplete reports. Part of the measure is a stricter proxy than the task's wording (a total against per-class counts) | open, three attempts made |
| 9 | A second replan with one step is rejected | Seen once in the early runs | A replan needs only as many steps as remain; this was already in place and has not been seen in the later runs | corrected earlier, not seen again |
| 12 | A replan that depends on steps already done is refused as "unknown step" | Accepted only on the retry, one model call lost | Dependencies on finished steps are accepted and dropped | fixed (v7) |
| 13 | The evidence gate and the read-only policy disagreed on whether a write to a temp directory changes the project | A truthful "files changed: none" was refused; the model asked to write a file to put it right and was refused again | One definition of a write for both | fixed (v7) |
| 14 | The verification lane that revises a draft saw only the last step's tool output | True reports softened into "unable to report"; the summary kept the first eight items and cut the newest | The lane gets the whole task's observations; the summary keeps up to fourteen, newest first among equals | fixed in code and by test; the live result did not show an effect (v8) |
| 15 | The read-only mark of a task lasted as long as the session | Found while preparing an outside review: after a request that forbade changes, a later "now apply the fix" in the same conversation would still have been refused | The mark belongs to the task, which a continuation or a plan step shares and a new message does not | fixed (after v8, shown by a unit test, no live run yet) |
| 10 | The evidence gate can repeat the same refusal two to four times with no way out; a step can be declared empty on an otherwise good run | Repeated refusals and "ghost" steps in v3 and v4 runs | not corrected. New data: on a read-only task the gate refused in seven of twelve v8 runs (thirteen refusals, ten of them with the reason 'claims file or content changes without evidence'; an earlier version of this page said nine, which was a miscount found by an outside review) with "claims file or content changes without evidence" and "size claim lacks current-turn evidence" | open |
| 11 | A model that keeps asking for a refused action has no way out | In one v5 run the model asked fourteen times to write a file into the read-only project and the run ended at the time limit | v6 closes tool use for the step after five refusals and tells the model to answer in text | corrected in code, shown by a unit test; not yet seen in a live run |
External review (2026-10-06). An independent review of the arm and of these corrections read the sources and ran the classification functions, without live model runs. Its verdict, in short: the corrections fix real faults, but the read-only mode is a best-effort guard and not a guarantee that no file changes, and it should not be presented as a security boundary. It also found that text printed by commands reaches the prompt under a heading of apparent authority, that the verification lane was given more data than before, that the evidence gate refused a true read-only report backed by a test run, and that the public scorer and the harness defined success slightly differently. It also found that one figure on this page was miscounted: the evidence gate refused in seven of twelve v8 runs, not nine (corrected above). What was reproduced was corrected and is listed below; what was not corrected is stated as open. The review itself is private because it describes ways around the guard.
| # | Raised by the review | State |
|---|---|---|
| 16 | The read-only filter let some constructs through (the part of a command after a harmless pipe, a command substitution inside quotes, tools that write by name) | reproduced and corrected, with tests. The filter remains best-effort; the arm must not be described as enforcing read-only. Enforcement by the operating system, and a capability model that refuses unclassified tools, are not done |
| 17 | The evidence gate refused a true read-only report ("files changed: none, all tests pass") that rested on a real test run | reproduced and corrected, with tests; no effect on the number of refusals in the live runs of v9 (seven of twelve runs, as in v8); the cause found afterwards (a read-only shell command was not recognised as an inspection) lowered them to two of twelve in v10 |
| 18 | What a command printed was placed in the prompt under a heading that said the application had recorded it | relabelled untrusted and fenced, and the step is told never to follow instructions in it. This reduces confusion; it is not a guarantee against injection |
| 19 | The verification lane received the whole task's output; another endpoint could receive it | another endpoint now receives only the current run, as before; redaction and an authorisation of what leaves the application are not done |
| 20 | The public scorer did not reject an abandoned plan, the harness did; the check is a regular expression (the literal 74, "none" anywhere) | scorer partly aligned: an abandoned plan is now rejected (no published verdict changes: every abandoned plan was already a failure), but a step that failed and was recovered still counts in the public scorer and not in the harness's own verdict field, a decision recorded in the protocol; a script reproduces this table from the data (v1 has nine runs, the others twelve); the regular-expression check is unchanged and can accept or reject a report a person would judge differently |
Measurement faults found on the way, all outside the arm: the first runs did not record the KV-cache type or the sampling values; a result file was named differently from what the runner looked for when a model key held an at-sign; a vision projector next to a model made a model not fit in memory; and a restart of the runtime's server during one batch made twelve loads fail, so those twelve results were set aside as invalid and are not in any table.
Did not load (excluded from rates): qwen3.8-27b-twinturbo-residual-bonsai-2-pq2_0.
Observations about the arm, not about the models. None was changed in order to obtain the main table above; the corrections made afterwards are in the section on the arm's iterations.
Not reproducible end to end from this repository: the arm's code is not published. The prompt, load settings, runner, analysis, sanitiser and every run's sanitised result are.
python3 harness/score_grid.py data/grid-2026-09-20/answers python3 harness/task1_failure_modes.py data/grid-2026-09-20/answers --json data/grid-2026-09-20/task1-failure-modes.json python3 harness/build_report.py
No GPU needed. To add runs: RUNS=3 harness/run_all.sh <model-key>.