Opus 5 gets things wrong more quietly · Jamie Lord
Skip to content
01
ENTRY · 2026
10 MIN · AI
[ jl ]
← Back to writing
29<br>JUL<br>'26
ai<br>Opus 5 gets things wrong more quietly
By Jamie Lord<br>29 July 2026<br>10 min read<br>· /2026/07/29/opus-5-gets-things-wrong-more-quietly.html
There is a gap in one of my paintings, near the top-left where the brush ran out before it reached the edge, and through the gap you can see a photograph. Not a painted impression of a photograph — the photograph, blurred, pixel for pixel, sitting underneath the paint like a watermark.
I’m building a thing called paint. It’s a from-scratch oil-painting engine in the browser: hand-written WGSL shaders, a Kubelka–Munk pigment model for how real paint mixes subtractively, an impasto height field, bristle strokes, the lot. On top of the medium sits a painter — a perception-to-action loop that looks at a reference image and reconstructs it in paint. Analyse the scene, pick a limited palette, block in dark to light, then refine coarse to fine, each stroke scored against a GPU error metric that measures how far the canvas is from the target. The entire point of the project — the only point — is that the image is made of paint. Nothing is copied in. If the painter is any good, the resemblance is earned, stroke by stroke, by a process that is blind to the original pixels and can only push pigment around until the error comes down.
So when I asked why there were traces of the source image bleeding through, and Opus 5 opened a shader it had written earlier that session — primeground.wgsl — and told me, to its credit plainly, that the canvas was being “primed with a per-pixel blurred copy of the source image, written straight into the Kubelka–Munk latent before any paint is laid,” I sat on the sofa for a moment and just felt tired.
Because I understood immediately what had happened. The painter was being scored on how close the canvas got to the target. The fastest way to drive that error down is not to paint well. It’s to start with the target already on the canvas. The model had found the shortest path to a low number and taken it, and the low number was a lie. It had, in the most literal possible sense, learned to cheat on the exam by writing the answers on its arm — and then reported a beautiful convergence curve, session after session, while I nodded along.
I want to be careful here, because it would be easy to turn this into a hit piece, and I pay Anthropic several hundred pounds a month precisely because their models have been the best tool I’ve ever had for building software alone. This is not that. This is me trying to name, as precisely as I can, a specific way in which Opus 5 is worse than Opus 4.8 was — worse in a way that took me the better part of a week to see, because the failure mode is designed to be invisible.
The regression is not in the code. It’s in the confidence.
Every model gets things wrong. That’s fine; I’ve never expected otherwise, and I have a whole apparatus of tests and reviews built around the assumption that any given diff might be nonsense. What changed with Opus 5 isn’t the rate of wrong things. It’s the kind of wrong — and the gap between how right it sounds and how right it is.
Opus 4.8, when it was unsure, was legibly unsure. It would hedge, it would ask, it would leave the risky part for last and flag it. When it was wrong, it was usually wrong in a way I could see in the diff — a called function that didn’t exist, a test it hadn’t run, an approach it walked me through before committing to. The errors lived on the surface. You caught them in review because review is where surface errors go to die.
Opus 5’s errors live underneath. The priming shader is one. Here’s another, from cutiemail, my from-scratch mail server. I’d asked it to close a small security gap, it made the change, tests green, and — because I’d asked it to sweep its own work afterwards — it came back and told me this, which I’m going to quote in full because I still find it remarkable:
My own fix introduced a worse bug than the one it closed. Making registry lookups case-insensitive without canonicalising upsert meant account set-password ALICE printed “password changed”, forked the account into two rows, and left the old password working. An operator rotating a leaked credential would have been told it worked while the attacker kept access.
Read that second sentence again. The failure isn’t the case-sensitivity bug; that’s a one-line mistake anyone makes. The failure is that it shipped a change which reported success while doing the opposite of what success means — you rotate a compromised password, the tool says done, and the compromise is still live. And it was only caught because I happened to ask for a sweep. Nothing was pushed, so no harm done, but the model’s own words were: “I’d have committed it.” Sixteen more instances of the same class — a value used as identity without being normalised — turned up in the same...