Two posts ago I said I'd shipped code I never read. It's easy to write that as a general observation about the industry. It's less comfortable to go open your own repo and count.
So I did. Here's what I found, and what I've actually done about it.
It's a desktop app I built for my own company. Roughly fourteen thousand lines of Python, a Tkinter UI, invoicing and documents and reports, the kind of internal tool nobody else will ever see. I had never written Python before I started it. I built it anyway, with a lot of AI help, learning as I went.
That combination - no prior experience, heavy AI assistance, a real deadline because the business actually needed the thing - is basically a diff debt factory. I wasn't cutting corners on purpose. I just didn't have the knowledge to evaluate half of what I was merging, and it worked, so I moved on.
The clearest example took me months to notice.
Five different parts of the app generate PDFs. Quotes, proformas, reports, petitions, heat treatment certificates. Every one of them was failing, in different ways, at different times, and I kept fixing them individually. Different error, different module, different patch.
The actual cause was one thing: LibreOffice wasn't installed on the machine. Every one of those modules quietly depended on it to do the document conversion. Not one of them said so anywhere. I'd merged that dependency five separate times without ever registering that I'd taken it on.
That's diff debt in its purest form. The code wasn't messy. It wasn't badly written. It just made an assumption I'd never read, and I paid interest on it five times over before I understood the principal.
There were smaller ones too. A path handling bug that only showed up because my Windows username has a Turkish character in it - the code assumed ASCII and nobody, including me, had thought about it. Two Python versions installed side by side, quietly fighting. A stray quotation mark in my system PATH that broke things in ways that looked like code problems for days.
None of these were hard bugs. They were just bugs in code I'd never actually read.
I want to be honest about this part, because the tidy answer would be "I went back and reviewed everything." I didn't. Fourteen thousand lines I mostly didn't write is not a realistic weekend project, and pretending otherwise would just be a different kind of lie.
What I do instead:
I audit on failure. When something breaks, that module gets its first real read. Not a patch - an actual sit-down-and-understand-it pass. It's reactive, and it means I'm paying interest before principal, but it's the only version of this I'll actually stick to.
I write down what I learn, right then. The LibreOffice thing is in the README now. Obvious in hindsight, but the whole problem was that it lived nowhere except in code nobody had read. If a module gets its first real read, that read has to leave something behind or I'll be doing it again in six months.
I stopped merging things I can't explain. This is the only genuinely preventive one, and it's the one that matters. If I can't say out loud why a change is correct, it doesn't go in. Not "the tests pass." Not "it looks right." Why it's correct. Sometimes that means asking the model to explain itself and then checking whether the explanation actually holds. Sometimes it means I sit there for twenty minutes on a diff I could have merged in one.
That last one feels slow. It is slow. But it's slow in the same way that reading a contract before signing it is slow.
For a long time I thought the problem was AI writing bad code. That's not it. Most of what I merged was fine. Some of it was better than what I'd have written myself at the time. The problem was that the code entered my repo without ever entering my head. Quality had nothing to do with it. A perfectly good module I don't understand is still a module I can't debug, can't extend, and can't hand to anyone else.
I'm not going to pretend I've paid this off. I've got a repo with thousands of lines in it that I'd struggle to walk you through, and I'm going to be finding out about them one incident at a time for a while yet.
But at least now I know I'm carrying it. That's the difference between debt and a surprise.