The AI makes the experiments cheap.
The engineering makes the experiments mean something. I don't use AI to decide what I should build. I use it to make building what I want to test ridiculously cheap, and then I make it prove what it wrote.
What it bought.
From question to running experiment.
A couple of hours. The generic memory server already existed, and there was no chat server to write.
Redis's own suite as the oracle.
From a standing start.
End to end, or five from when I took over the implementation work.
Those numbers aren't interesting because typing fast is impressive. They're interesting because I could move from question to running experiment fast enough to ask the next question while I still cared about the answer. The conversions.
Using AI for maximum code velocity.
AI changes the economics of the experiment.
It doesn't change what I need to know. I still need the oracle from Part IV to tell me whether the behavior is right. I still need the instrumentation to tell me what the implementation actually did. I still need the measurements and the runnable system from Part V.
What AI changes is how cheaply I can ask the next question.
I don't use AI to decide what I should build. I use it to make building what I want to test ridiculously cheap.
That distinction matters. Claude can write a ton of code very quickly. So can the other current coding models. But if I'm not also writing and running tests, measuring the result and documenting what I actually built, it's probably all crap.
AI is a tool, just like any other. You wouldn't use a hammer to cut a board, so why use AI for the parts it sucks at? I don't want it supplying the imagination or understanding the bigger picture. Those are the parts I need to own. What I want from the AI is the ability to turn a sufficiently precise engineering idea into working code at a rate I couldn't begin to approach by hand.
That changes what I'm willing to try.
In the past, rewriting a subsystem was expensive. If I already had 30,000 lines of working code wrapped around an architectural decision, those 30,000 lines became an unstated argument for keeping the decision. I might know there was another way to do it. I might even think the other way was better. But somebody had to write it, compile it, debug it, integrate it and test it before I could find out.
That tax was high enough that we normally paid it only when something was badly broken.
AI changes the economics.
If I have a good behavioral oracle, I can hand an AI the existing implementation, the contract it has to preserve, the tests that establish that contract and the architecture I want to try. It can build the alternative. Then I run the oracle.
If it passes, I have learned something.
If it fails, I find out why.
If I get it running and discover that the whole idea was stupid, I throw it away.
That last one is more important than it sounds.
I've done it repeatedly while building Ribbit. I've dropped entire architectures and replaced them wholesale because the cost of trying the replacement was low enough that I didn't have to argue about whether it might work. I could run it and find out.
Sometimes the replacement was better. Sometimes it exposed another problem. Sometimes, once I could see what it was actually doing, I realized that I had asked it to do the wrong thing and threw that one away too.
That's not thrashing. Thrashing is changing things without knowing whether the change helped. If I have an oracle that tells me whether I preserved the required behavior, instrumentation that tells me what the implementation is actually doing, and measurements that tell me whether I improved the thing I was trying to improve, then rewriting an architecture is an experiment.
That is where the code velocity comes from.
Maximum code velocity comes from reducing the cost of asking the machine another well-formed engineering question.
The important word there is well-formed.
"Make this faster" is not a particularly useful engineering question. Faster how? Throughput? Latency? CPU? Wall-clock time? Under what workload? Compared with what? What behavior am I not allowed to change?
"Preserve these 42 externally observable behaviors, remove this synchronization mechanism, and tell me whether throughput and latency improve under this workload" is something I can test.
Now the AI has boundaries. More importantly, so do I.
I can build the red test first. I can run it against the incumbent and establish what the incumbent actually does. I can make the new implementation pass the same oracle. Then I can measure the result.
This is exactly why the debugging and instrumentation in Part IV matter. AI code generation without fast feedback isn't maximum velocity. It is just maximum code generation.
Those aren't the same thing.
The faster I can generate code, the less willing I should be to accept code merely because it looks right. Compile it. Run it. Test it. Measure it. If I'm replacing something, run the incumbent too. If I claim compatibility, prove compatibility. If I claim performance, measure the thing I actually claim improved.
I also document while I'm doing it.
That is partly because AI needs the documentation. A coding assistant coming into a system without a clear statement of what the system is supposed to do will happily infer one. Sometimes it will infer the right one. Sometimes it will build an extremely competent implementation of something I never wanted.
The documentation is part of the engineering contract. It says what the architecture is, who owns what, what behavior must be preserved, what the tests mean, what has already been tried and why something was discarded. If the implementation and the documentation disagree, that's something I want to discover, not quietly paper over.
The checkpoints matter for the same reason. When I get something green, I keep it. Now I have a known point I can return to. The next experiment starts from something that worked instead of from whatever happens to be in the directory after three unsuccessful ideas.
That makes aggressive experimentation safe enough to be useful.
Ribbit-LISP is a good example. I didn't just tell an AI to "rewrite lispers.net using Ribbit." The incumbent implementation was the behavioral oracle. Changes were made in pieces. A failing test established the next behavior before the implementation changed. When a new architecture didn't survive the tests, it didn't survive. When something went green, it became a checkpoint.
That process let me make changes that I would have considered absurdly expensive a few years ago. Locks disappeared from the participant side. The RAM host's single global mutex was replaced by per-row locks and a pool of Engines. Once that was running I could see what I had actually built: a pool of Engines that were clients of their own server, complete with loopback sessions, copied views and their own mutexes. I threw the pool out. The operations now run in the memory itself, under the row locks. Registration ownership changed. Liveness changed. Multi-record registration became an all-or-nothing operation. Whole pieces of architecture were replaced while the externally required behavior stayed pinned down by the oracle.
The AI made writing those alternatives cheap. The oracle made throwing them away cheap.
Those are two different things, and I need both.
The same pattern shows up in the other Ribbit experiments. The chat client took a couple of hours because the generic memory server already existed and there was no chat server to write. Redis took four days. The PyTorch work took five days from a standing start. The lispers.net conversion took about six days end to end, or five from when I took over the implementation work.
Those numbers aren't interesting because typing fast is impressive. Typing isn't the bottleneck anymore.
They're interesting because I could move from question to running experiment fast enough to ask the next question while I still cared about the answer.
That changes architecture.
Before AI, I had to spend a lot more time deciding whether an idea was worth implementing. There was no choice. Implementation was expensive. I had to reject most alternatives before I had evidence because I couldn't afford to build every plausible one.
Now I can be much less conservative.
What happens if I remove this layer?
Try it.
What happens if I replace the global lock?
Try it.
What happens if I stop reproducing the existing PyTorch choreography and model the operation directly as shared state?
Try it.
What happens if the application doesn't have a server at all?
Try it.
The important part comes immediately afterward:
Run it.
That is the difference between using AI as an engineering accelerator and using it as a code generator.
The design still matters enormously. In fact, I think it matters more. If I can generate 10,000 lines of implementation before lunch, a bad architectural decision can now become 10,000 lines of bad implementation before lunch.
The AI doesn't fix that.
A flawless implementation of the wrong design is still wrong.
So I want to spend my time where I have the most leverage: deciding what the system should do, figuring out who owns each truth, defining the interfaces and invariants, designing the experiment, deciding what constitutes success, and looking at the results. I let the machine pay as much of the mechanical implementation tax as I can safely hand it.
Then I make it prove what it wrote.
This is also why I don't particularly care about arguments over whether AI-generated code is "real programming." I care whether the system works. I care whether the implementation satisfies its contract. I care whether I can reproduce the result. I care whether the measurements are honest. I care whether somebody else can open the tree, run the tests and see the same thing.
The source doesn't get extra credit because I suffered while typing it.
The real opportunity is that architectures have become disposable in a way they never were before.
That's a very big deal.
Software engineering has always accumulated sunk cost. Once enough code depends on a decision, changing the decision becomes progressively harder, even when everybody knows it wasn't a particularly good decision to begin with. Eventually the cost of changing the architecture can be larger than the cost of living with it.
AI attacks that cost directly.
But it only works if the rest of the engineering process gets more rigorous at the same time. The faster I can rewrite something, the more important the oracle becomes. The faster I can generate alternatives, the more important measurement becomes. The easier it is to change the architecture, the more important it is to know exactly what contract I'm preserving.
Maximum code velocity isn't how many lines an AI can spit out in an hour.
Maximum code velocity comes from designing and instrumenting the system so it's easy and fast to see if an algorithm is or is not working, combined with a rigor that cuts off unproductive architectures as soon as they can be identified, while simultaneously opening the door for new, previously unknown or untried architectures.
The AI makes the experiments cheap.
The engineering makes the experiments mean something.
How I run the AIs.
The essay says what the AI is for. This is how the work is actually organised.
Several AIs are a design review.
Playing one AI against another is just design review. Two, and sometimes three or four, validate something while I stay at the architectural level. It is diversity of perspective with actual code influence.
A disagreement is an investigation.
If two of them see something differently, either one of them made it up or there is a genuine ambiguity. Either way I want to know which.
One AI writes all the code.
The entire system. The others only review. Parallel coding sessions of the same AI may be the same coder when they start, but not for long.
One thread integrates.
I share statuses between the threads by hand, and only when it is necessary: this is a complex system and an AI's context is limited. One thread does integration and reconciliation.
The tests decide, not the AI.
That is what the acceptance tests are for. I'm not stupid enough to take its word. That's why I prefer existing tests: an AI is a very poor QA.
Let it run.
A junior developer doesn't learn if you don't let him run. Good practice, the full development lifecycle, makes those excursions affordable, even if still annoying, and more than once one has turned up an alternative that was worth having.
The tree is written to be read by an AI.
AI_READ_FIRST.md at the root, an AI_README.md in the major directories, and hand-off documents that list the corrections already made so the next session doesn't need them made again.
Maximum code velocity isn't how many lines an AI can spit out in an hour.