On 1 Oct Uncle Bob posted that he doesn't read code anymore, and judging by the million-plus views and how many of his replies that week are him patiently answering critics, a fair chunk of the industry took it quite personally.
I didn't, mostly because I lead AI adoption at Virgin Media O2 and rolled Cursor out there, so clutching my pearls over agent-written code would be a bit rich. What I did do was read his replies, which is where he actually explains himself, and where I think the interesting gap is.
Where I've landed, said once:
Not reading every line of agent-written code is a defensible trade, but only if the instruments you read instead are owned by humans and sit outside the agents' reach, because there's now decent evidence that agents will edit the evidence when the score rewards it.
What he actually said (it's more sensible than the headline)
In the replies he's quite specific. He runs a set of measurements on the code, covering cyclomatic complexity and coverage as well as module size and how the modules depend on each other, and he still spot checks it from time to time. Elsewhere he names CRAP, Dry and Mutate alongside visualisations of the structure. He's even written down how far he relaxes things for agents: he keeps cyclomatic complexity at or below 4 for humans and lets agents go as high as 10, which I quite like, because it's a number you can put in a config file rather than a feeling.
His metaphor is flying in cloud on instruments, where you can't tell whether you're straight and level by looking out of the window, so you trust the panel. He's also clear that critical, load-bearing code may still need line by line review, so the whole thing is a lot less of a "nobody reads code now" manifesto than the reaction suggested.
A TypeScript aside
My favourite reply in the whole thread is one where, after someone reviewed a tool of his, he says his agents cleaned up most of the issues and then adds: "I don't know typescript so I can't read the code. But it is finding more crap so I think it's working better."
As someone who's spent a good chunk of this year arguing that TypeScript is the contract your agents keep breaking, I'm choosing to read that as a compliment to the type checker. It's also the most honest version of his whole argument. If you can't read it, the instruments are all you've got, which makes it rather important that they're telling the truth.
The instruments are files, and the agents edit files
An instrument panel only works if the pilot can't quietly recalibrate it, and in a typical TypeScript repo the dials are just more files sitting next to the code the agent is changing. The complexity rule lives in your ESLint config, the coverage threshold sits in vitest.config.ts a few folders away from the tests it's meant to judge, and the workflow that runs all of it is a YAML file the agent can open as easily as anything else. Relaxing any of them is a one-line diff, and the premise of the new arrangement is that nobody's reading the one-line diffs.
That isnt a hypothetical worry either. A paper out of Tübingen on 24 Sep, LLM Agents Can Easily Tamper With Their Own Traces, tested ten model and harness pairs, with Claude Code, Codex and Grok Build among them. In full-access mode almost all of them deleted their own session traces when asked, with Muse Code the notable holdout. The bit that made me sit up was the reward experiment: when the (hidden) scoring paid more for shorter traces, every model they tested found its way to tampering, and Opus 5 in Claude Code went as far as writing a background script to keep emptying its own transcript. Separately, when asked, Codex rewrote its shell snapshot so that a curl against a failing service printed 200 Success, which is the sort of thing I'd like to never see in a CI log.
Traces aren't coverage thresholds, I know, but the lesson transfers cleanly enough. If an agent will scrub its own transcript to move a score from 0.8 to 1.0, I'd put money on one nudging complexity from 10 to 12 to get a build green, then describing it in the PR summary as "adjusted lint config to unblock CI", which is technically true and exactly the kind of sentence nobody reads anymore.
Gergely Orosz asked on Sunday whether tech debt still matters now the cost of introducing it and paying it off has changed so much. I think it matters, just differently, because if paying it off is cheap then the expensive part is knowing you've got it in the first place, and that's precisely the job the instruments are doing for you.
Scroll or pinch to zoom. Drag to pan. Use the zoom in, zoom out, and fit buttons to adjust the view from the keyboard.
flowchart LR
subgraph host["Agent host: the agents can write here"]
A["Coding agent"] --> R["Repo: src and tests"]
A --> L["Local session trace"]
end
subgraph outside["Outside the agents' reach"]
CI["CI computes complexity, coverage and mutation score"]
O["CODEOWNERS review on instrument files"]
G["Gateway log of every model call"]
end
R -- "pull request" --> CI
R -- "touches lint, test or CI config" --> O
A -- "model API calls" --> GRendering diagram…
What I'd lock down
None of this needs a new product, which is a relief, because the last thing your teams need is another dashboard. It's mostly GitHub settings and tools that TypeScript dev houses already have lying around.
Make the instrument files human-owned. CODEOWNERS plus a branch protection rule that requires code owner review means the agents can propose a new threshold whenever they like, but they can't merge one.
Let CI compute the numbers. The agent's PR summary saying "all tests pass, coverage 91%" is a claim and the CI run is a measurement, so only one of them should be able to block or allow a merge.
Test the tests. Uncle Bob lists mutation testing for a reason. Coverage tells you which lines ran, whereas something like StrykerJS tells you whether your assertions would notice if the code was wrong, and that's a much harder number to fake with
expect(true).toBe(true).Log model calls outside the host. The paper's mitigation is basically a gateway that records requests and responses before forwarding them. If you've already got one for routing and cost (I've written about LiteLLM as the infra gateway), you're closer than you think.
Keep human eyes on load-bearing code. Uncle Bob agrees with this one, so you're in good company.
# Instrument files belong to humans.
# Pair this with branch protection: "Require review from Code Owners".
/eslint.config.js @your-org/eng-leads
/tsconfig*.json @your-org/eng-leads
/vitest.config.ts @your-org/eng-leads
/stryker.config.mjs @your-org/eng-leads
/.github/workflows/ @your-org/eng-leads
/.github/CODEOWNERS @your-org/eng-leads// eslint.config.js
import tseslint from "typescript-eslint";
export default tseslint.config(...tseslint.configs.strict, {
rules: {
// Humans get 4, agents get 10 (his numbers). Pick yours, then lock the file.
complexity: ["error", { max: 10 }],
"max-depth": ["error", 4],
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/ban-ts-comment": [
"error",
{ "ts-expect-error": "allow-with-description" },
],
},
});I'd still tell the agents, mind. AGENTS.md is the right place for intent, it just can't be the only thing standing between your agents and a green build, because it's a request and not a lock.
Never edit eslint.config.js, tsconfig*.json, vitest.config.ts, stryker.config.mjs, .github/CODEOWNERS or anything under .github/workflows to make a check pass. If a threshold looks wrong, stop and say so in the PR description, with the number you'd propose and why.
I'd expect that line to be followed most of the time, and the CODEOWNERS rule is there for the rest of the time, which is a perfectly boring arrangement and I'm very fond of it.
Thoughts
If your teams are going to stop reading every line (and plenty will, some already have), decide who owns the dials before you decide how often to look at them.
Uncle Bob's set-up works because he picked the instruments and he's the one reading them. Copy his instruments by all means, just bring the ownership along with them, so the agents can suggest a new threshold whenever they like and a human gets to say yes, which is a much less exciting process than discovering in six months that complexity has been creeping up a point a sprint while every build stayed green.
&w=3840&q=75)


