The fourth time is too late
In the previous episode ([CANONICAL URL #52: to complete after push of over-engineering-3-recadrages]), I described three reframings in the same session — no simpler, no simpler, no simpler — before Claude finally proposed the eight-line version of a function instead of the one with interface, registry and three files. The next morning I reopen the project, ask for a minor fix in the same module, and the answer arrives architected exactly like the day before. Strategy pattern, registry, three integration tests. The reframing did not survive /clear. It had no reason to. No file carried it, no mechanism triggered when the reflex returned.
The fourth time is too late. You write the line on the third.
The line
I added this to CLAUDE.md, in the Conventions section, one block above the Server Component rule:
Default to the smallest change that fits. Add abstractions only after the second occurrence, never the first.
Four choices in two sentences. Each cost several drafts before it held.
Why these four
Default to, not avoid. The first version I tried said Avoid premature abstraction and changed nothing in practice. The negative activates the object it names. The agent reads premature abstraction and surfaces the abstraction category, against which it has a trained default that pushes it to produce one. The positive sets a direction without naming the reverse reflex. This is the least obvious detail of the exercise and the one that tipped the test.
That fits, not just smallest. The smallest change alone pushes toward a hack. The simplest solution opens a debate on what simple means. That fits states the measure: covering the need, not elegance.
Second occurrence, not third. Martin Fowler's rule of three from Refactoring says "the third time you do something similar, refactor". I lowered it to two for a reason that probably only holds for solo Claude Code dev: there is no PR review, so the second occurrence is the last moment where I am still lucid about the abstraction I am about to commit to. By the third, Claude proposes the abstraction spontaneously and I sign without looking, because session pressure has worn me down.
Never the first. The never is deliberate and probably excessive. But a default formulated with an exception becomes an exception searched for. Never shuts down the internal negotiation. When the genuinely exceptional case arrives — and it does — I must argue against the rule explicitly, which is exactly the friction I want.
What I have seen so far
Three sessions, three subjects, three modules. Claude proposed one premature abstraction that I caught and that he retracted in one exchange, against three or four per session the week before. Not a study. One observer, confirmation bias, sample ridiculous. But the line loads with CLAUDE.md on every start, and the baseline pressure now points against the trained default. A proper A/B test is the subject of a later post.
Coda
The doctrine in CLAUDE.md is not a list of best practices. It is the material accumulation of lessons I refused to repeat a fourth time. The rule of three (Fowler, abstractions) applied to the rule of three (mine, oral reframings in session). The third time I find myself saying the same thing to Claude, it goes into CLAUDE.md as a line. Otherwise I will say it again in the next session, and the lesson will leave with the context.
Sequel to [CANONICAL URL #52: to complete after push of over-engineering-3-recadrages]. A/B test of the CLAUDE.md effect on Claude Code output: subject of a later post in this series.
Top comments (0)