Rip Out the Guts

SubSonic is over twenty years old and last built on .NET 3.5. Jon Skeet and I are upgrading it to .NET 10, live, and the procedure transfers to whatever legacy codebase is haunting your shop.
Round three, and the goal is blunt: rip out the provider model and get one query running against SQLite.
First we build a map of the repo so Claude stops burning context exploring it on every change. I try to save money by having Haiku write the map and Fable check it. That goes badly, and the postmortem is the useful part: draft-cheap-then-verify only wins when verifying is cheaper than doing the work. Here it wasn't. Haiku invented an API and got the license wrong.
Then the real argument. Should we be upgrading this at all, or starting over?
Jon makes the case for greenfield. I push back, badly at first, because what I want to protect isn't the code. It's the reason the code is shaped that way, and none of that is written down anywhere. Jon has a name for it: intent debt, from a paper by Margaret-Anne Storey. Claude has a name for the other half: Chesterton's Fence. Every weird line in the ANSI SQL generator is a bug fix nobody remembers.
So we keep going, and we gut it:
- The Sugar library goes.
- The provider model comes out, replaced with System.Data interfaces, command and query classes.
- SQLite in-memory for tests. No Docker, no server, no config.
- Zero errors, zero warnings, ten green tests, and a query that actually runs.
The API Claude produced is not the one I want. It rebuilt something that looks a lot like ADO.NET. We'll fix that next time.
Also in this one: using plan mode to stop Claude from sprinting ahead, and Jon's question about whether you can put "push back on me if this makes no sense" in your CLAUDE.md. You can.
SubSonic is over twenty years old and last built on .NET 3.5. Jon Skeet and I are upgrading it to .NET 10, live, and the procedure transfers to whatever legacy codebase is haunting your shop.