While going through Matt Pocock’s AI Coding Crash Course, I hit a section on whether you should keep your specs once they’re implemented. Matt’s answer: archive them. He sees the code as the primary source of truth: ”[…] the executable parts of the codebase - the functions themselves - they are unlikely to lie about what the code actually does”. For Matt the real danger is that an agent finds a stale spec in the repo and trusts it over the code, because it’s smaller and easier to read. So instead of keeping specs in the repo, he closes them as issues in the tracker. They’re out of the way, but the agent, or a teammate, can still look up how or why something was built.

Now I want to add another angle I learned from @jimmykoppel that I see missed often. It is about judging whether a piece of code is correct, which is a question about what the code was supposed to do, not what it does. That comes down to knowing the original intent of the code, its design. The problem is that a single implementation is consistent with many possible specs, so once the spec is gone it is hard to judge how the software was supposed to work. Koppel’s example is x >= 65. It is the same line of code whether it checks that a character is an uppercase letter or that a person has reached retirement age. Nothing in that line tells you which, unless the code around it carries the design.

”[…] there are many designs that correspond to the exact same code, and so recovering all the design information is actually impossible.” - The Design of Software is A Thing Apart

Still, Matt’s suggestion doesn’t contradict that. The spec is archived, not deleted, so it can still be read as a historical artifact. It is a weak one, though. The spec was the plan for a piece of work, written before the implementation taught you what the design really was. So it drifts from the intent just as it drifts from the code. Archiving it is necessary but not sufficient. Koppel suggests something better. Make the design apparent in the code itself, which he calls the Embedded Design Principle. Start with precise types, modeled state and tests, because those get checked. Then name things well and write at the right level of abstraction, which don’t get checked. With the design in the code, an agent can judge a change against what the code was supposed to do instead of fixing it toward what it happens to do.