Forty days of local models: what we kept and what we set aside

Eduardo Verboonen Khoury · November 3, 2026

On 2026-09-26 I turned on a Mac Studio with 256 GB of memory to run open-weight models next to the cloud. A second Mac served as backup, and later as a helper. The question was simple: which parts of the work can move off the cloud without getting worse, and how would I know? This is the notebook of the first 38 days, through 2026-11-03. It covers what we tried, what we kept, what we set aside and why. Every number comes from a dated log, and every verdict was measured against a criterion written down before the result existed.

A companion note, The dangerous failure is the one that reports success, covers the exam built from real work and the sandbox around the agent. This one is the wider record.

The rules of the lab

Three rules held for the whole period.

Things that failed quietly

The most useful findings were not about which model is smarter. They were about tools that looked like they worked.

A “local” coding agent that called home. I set up Codex CLI with a profile pointing at the local model, over loopback only. On 2026-10-02 I measured 15 runs and caught a connection to chatgpt.com in 3 of them. The cause was in the client’s source code, not in the model: a “memories” feature checks the account’s usage limit on every run, whatever model the run uses, and a profile is layered on top of the base configuration instead of replacing it. So the account feature stayed on. The fix was a separate home folder for the tool, with no login file and features.memories = false. After the fix: 0 connections in 15 runs, and 0 in 3 more with the installed version. One caveat: the detector could miss connections shorter than about a quarter of a second, so 3 in 15 is a floor, not an exact rate. The lesson: a profile is not isolation. A separate home is.

Prompts cut in half without a word. The version of Ollama we run, 0.34.4, handles a prompt longer than the context window by cutting it to about half the window, dropping the beginning, and the client is not told. We found it twice. First, the coding agent believed it had 64k tokens of context and was seeing 16k. Then, on 2026-10-06, an audit of my own context measurements showed that their recall, incremental and 90% fill results were invalid: my prompts had been cut before the model saw them. From then on every measurement sends truncate: false, so an oversized prompt fails loudly with an error instead of shrinking. In daily use a lock reads the server log and records every cut. A real control on 2026-10-18, a prompt of 44,785 tokens sent to a small window, was recorded and alerted exactly once.

Thinking budgets that return nothing. Several models think before they answer, and the thinking counts against the token limit. Gemma 4 thinks by default; with a short limit it spent the budget thinking and returned empty content, and in two cases it ran on until it filled the context. gpt-oss 20B did something similar even with thinking turned off: thousands of characters of reasoning and no answer. Both looked like model failures. Both were configuration. Every call now states its thinking mode explicitly.

The reasoning mode is a variable

A public comment said that a 27B Qwen model needs its reasoning mode on to program well. We tested it on 2026-10-04 with the official release, on the first 80 HumanEval problems: reasoning off, 75 of 80; reasoning on, 59 of 80, with a 6,000 token limit that may have cut some long reasoning. In our harness, the comment did not hold. An earlier run of the same model had scored 49 of 80, but that harness cut answers at 768 tokens. The earlier number was ours to fix, not the model’s.

Benchmarks stop discriminating

By early October, HumanEval no longer separated the candidates: the strongest local models all scored between 71 and 76 of 80. So between 2026-10-02 and 2026-10-04 I wrote a 41 task exam in three families (programming as an agent, reasoning, and following instructions in Spanish), graded by code, and used Opus 4.7 as the reference. Opus passed 41 of 41 for US$7.91. Gemma 4 31B passed 85% of the agent family and 100% of the other two. Gemma 4 26B: 77, 100, 100. Qwen3-Coder-Next, then in use for code: 69, 82, 73. In reasoning and Spanish instructions, three local models matched the reference. In programming as an agent, none did; the best was 15 points behind.

A reference that scores 100% everywhere means the exam is too easy to rank the top. That pushed me to build the exam from real commits in client repositories, described in the companion note. On the fair bank of 28 tasks, over three repetitions, Gemma 26B solved 21, 19 and 20, and Qwen solved 14, 15 and 13. On 9 tasks with rewritten statements, one repetition each, Opus 5.5 solved 9, Gemma 26B 8 and Qwen 7.

Candidates, with the verdict and the reason

Alternatives set aside

How a model changes jobs

No tool names a model. Each job (text, code agent, and so on) is an alias with a contract test, and one command moves a job to another model, runs the contract and keeps the way back.

On 2026-10-15 the text job moved from gpt-oss 20B to Gemma 26B. On a golden set of 30 synthetic cases, Gemma passed 30 and gpt-oss 25; the five misses were empty answers from the thinking budget problem above. Gemma also passed the manipulation bank, and gpt-oss did not.

On 2026-10-18 the code agent job moved from Qwen to Gemma 26B. The evidence was thin and I wrote that down: 4 of 13 against 2 of 12 on a small screen, not conclusive. The change was justified because it was reversible and watched, not because the evidence was strong. The way back was rehearsed before the change and took 6 seconds. The watch is written as code: if the error rate reaches 5%, the 95th percentile passes 90 seconds, three turns time out, two prompts get cut or memory leaves its limit, the job returns to Qwen on its own and I get one line. It passes after 7 days and 30 real turns with no incident. As I write this, that watch and the one on the text job are still open, so I am not calling either change confirmed.

The same pattern runs everything that spends time in shadow: numeric criteria with a minimum of days and cases, a daily evaluator that activates the change only when they are met, and an automatic return to shadow after a critical incident.

Next

NVIDIA’s newer Nemotron models (document parsing, embeddings, reranking and speech recognition) are prepared, not measured. Six official repositories are downloaded and checked by hash, the criteria are written, and NeMo Evaluator is installed. The one test so far: converting the 1B embedding model to the format our engine uses was not faithful (cosine 0.983 to 0.995 against the reference, where a faithful copy gives 1.000), so it will be measured in its original form. One model was set aside before measuring: Nemotron Content Safety. Its license adds the Gemma 3 terms of use and prohibited use policy on top of NVIDIA’s open license, and that was a layer of obligations we chose not to carry. Two Apache licensed safety models will be measured in its place.

What this adds up to

The models improved quickly over these weeks. What moved my results most, though, was the plumbing: a profile that did not isolate, a prompt cut in silence, a thinking budget that returned nothing, an engine that renamed a tool. Each looked like a model failure until I read the log. The best local models now do real programming work in my harness, and a frontier model still sets the line they are measured against.