Making Sense of Specification-Driven Development
To know whether specification-driven development works, I first had to ask what a specification is supposed to do.
AI changed everything. Again. Now the specification comes before the software. Why didn’t anyone think of this sooner? … Oh, wait.
The reason nobody thought of it sooner is that everybody did — it was called waterfall. Write the whole specification up front, then build. It failed, and not because the idea was foolish: the first real feedback arrived only when the software did, months later, and it usually said the specification had described the wrong system.
Agile fixed the feedback loop by shrinking the work into small slices. That made separately maintained prose specifications feel optional, and many teams relied on a story, a conversation, tests, and the code instead. So for most of my career, when I encountered a specification as a distinct document, it had been written after the software: usually for newcomers, so that nobody had to explain the system in person for the tenth time. A summary of code that already existed, not a guide to what should exist.
Writing specifications beforehand is not what killed waterfall — steering too rarely did. But once separately maintained prose specifications felt optional, the economics made sure they stayed optional.
The code is the specification
Code was usually the expensive part. When a requirement changed, you had to understand the existing system, change the implementation, repair whatever broke, and verify that the result still worked.
Updating the specification on top of that was a cost nobody was willing to pay. And the code already specified how the application actually behaved. So the code became the source of truth and the specification slowly became a historical record.
Cheaper code changes the economics
AI makes producing and changing code cheaper, which means implementations can change faster and grow unsupervised.
At some point, treating the code itself as the specification stops working. The behavior is still all there — but so is every accident that shipped. The code tells you what the system does; it has stopped telling you which parts it does on purpose.
Now that code is the cheap, replaceable artifact, the roles flip: the specification becomes the thing worth keeping. That shift is what makes specification-driven development interesting, and perhaps necessary for teams that want to use AI effectively on large projects.
A specification has to earn its keep
Cheaper code does not make a specification good. Its existence is not the goal. Neither are its length, level of detail, or approval status.
A good end-to-end test suite aims at much the same result. It records observable behavior in a form the machine can check, giving me enough confidence to change the implementation without accidentally changing the behavior.
In many applications I have worked on, neither artifact achieved that. Specifications drifted away from the code. Tests mirrored implementation details, broke during harmless changes, and became another system developers were afraid to touch.
Their existence was treated as success. Test coverage was measured. Documents were approved. The more important question was rarely asked: Did any of this make the application easier to change?
If the answer is no, the next question should be simple: why? Perhaps the specification described the wrong things. Perhaps the tests protected implementation rather than behavior. Perhaps useful rules existed but were not found when the developer or agent needed them.
Cheap code is a reason, not a method
This change in the economics of code gives me a reason to revisit an old idea, but it does not answer those questions. What I expect a specification to accomplish is settled; the structure that delivers it is not.
The open questions all start from that goal. What belongs in a specification, and which parts does an agent actually need for the task in front of it? How do I separate what the software does from how it got built — and how would I even know if any of this is working?
Those questions deserve more than one article. For now, the first principle is enough:
A specification earns its keep only when it makes software easier to change.
Making Sense of Specification-Driven Development
// To know whether specification-driven development works, I first had to ask what a specification is supposed to do.
AI changed everything. Again. Now the specification comes before the software. Why didn’t anyone think of this sooner? … Oh, wait.
The reason nobody thought of it sooner is that everybody did — it was called waterfall. Write the whole specification up front, then build. It failed, and not because the idea was foolish: the first real feedback arrived only when the software did, months later, and it usually said the specification had described the wrong system.
Agile fixed the feedback loop by shrinking the work into small slices. That made separately maintained prose specifications feel optional, and many teams relied on a story, a conversation, tests, and the code instead. So for most of my career, when I encountered a specification as a distinct document, it had been written after the software: usually for newcomers, so that nobody had to explain the system in person for the tenth time. A summary of code that already existed, not a guide to what should exist.
Writing specifications beforehand is not what killed waterfall — steering too rarely did. But once separately maintained prose specifications felt optional, the economics made sure they stayed optional.
The code is the specification
Code was usually the expensive part. When a requirement changed, you had to understand the existing system, change the implementation, repair whatever broke, and verify that the result still worked.
Updating the specification on top of that was a cost nobody was willing to pay. And the code already specified how the application actually behaved. So the code became the source of truth and the specification slowly became a historical record.
Cheaper code changes the economics
AI makes producing and changing code cheaper, which means implementations can change faster and grow unsupervised.
At some point, treating the code itself as the specification stops working. The behavior is still all there — but so is every accident that shipped. The code tells you what the system does; it has stopped telling you which parts it does on purpose.
Now that code is the cheap, replaceable artifact, the roles flip: the specification becomes the thing worth keeping. That shift is what makes specification-driven development interesting, and perhaps necessary for teams that want to use AI effectively on large projects.
A specification has to earn its keep
Cheaper code does not make a specification good. Its existence is not the goal. Neither are its length, level of detail, or approval status.
A good end-to-end test suite aims at much the same result. It records observable behavior in a form the machine can check, giving me enough confidence to change the implementation without accidentally changing the behavior.
In many applications I have worked on, neither artifact achieved that. Specifications drifted away from the code. Tests mirrored implementation details, broke during harmless changes, and became another system developers were afraid to touch.
Their existence was treated as success. Test coverage was measured. Documents were approved. The more important question was rarely asked: Did any of this make the application easier to change?
If the answer is no, the next question should be simple: why? Perhaps the specification described the wrong things. Perhaps the tests protected implementation rather than behavior. Perhaps useful rules existed but were not found when the developer or agent needed them.
Cheap code is a reason, not a method
This change in the economics of code gives me a reason to revisit an old idea, but it does not answer those questions. What I expect a specification to accomplish is settled; the structure that delivers it is not.
The open questions all start from that goal. What belongs in a specification, and which parts does an agent actually need for the task in front of it? How do I separate what the software does from how it got built — and how would I even know if any of this is working?
Those questions deserve more than one article. For now, the first principle is enough:
A specification earns its keep only when it makes software easier to change.
Making Sense of Specification-Driven Development
To know whether specification-driven development works, I first had to ask what a specification is supposed to do.
AI changed everything. Again. Now the specification comes before the software. Why didn’t anyone think of this sooner? … Oh, wait.
The reason nobody thought of it sooner is that everybody did — it was called waterfall. Write the whole specification up front, then build. It failed, and not because the idea was foolish: the first real feedback arrived only when the software did, months later, and it usually said the specification had described the wrong system.
Agile fixed the feedback loop by shrinking the work into small slices. That made separately maintained prose specifications feel optional, and many teams relied on a story, a conversation, tests, and the code instead. So for most of my career, when I encountered a specification as a distinct document, it had been written after the software: usually for newcomers, so that nobody had to explain the system in person for the tenth time. A summary of code that already existed, not a guide to what should exist.
Writing specifications beforehand is not what killed waterfall — steering too rarely did. But once separately maintained prose specifications felt optional, the economics made sure they stayed optional.
The code is the specification
Code was usually the expensive part. When a requirement changed, you had to understand the existing system, change the implementation, repair whatever broke, and verify that the result still worked.
Updating the specification on top of that was a cost nobody was willing to pay. And the code already specified how the application actually behaved. So the code became the source of truth and the specification slowly became a historical record.
Cheaper code changes the economics
AI makes producing and changing code cheaper, which means implementations can change faster and grow unsupervised.
At some point, treating the code itself as the specification stops working. The behavior is still all there — but so is every accident that shipped. The code tells you what the system does; it has stopped telling you which parts it does on purpose.
Now that code is the cheap, replaceable artifact, the roles flip: the specification becomes the thing worth keeping. That shift is what makes specification-driven development interesting, and perhaps necessary for teams that want to use AI effectively on large projects.
A specification has to earn its keep
Cheaper code does not make a specification good. Its existence is not the goal. Neither are its length, level of detail, or approval status.
A good end-to-end test suite aims at much the same result. It records observable behavior in a form the machine can check, giving me enough confidence to change the implementation without accidentally changing the behavior.
In many applications I have worked on, neither artifact achieved that. Specifications drifted away from the code. Tests mirrored implementation details, broke during harmless changes, and became another system developers were afraid to touch.
Their existence was treated as success. Test coverage was measured. Documents were approved. The more important question was rarely asked: Did any of this make the application easier to change?
If the answer is no, the next question should be simple: why? Perhaps the specification described the wrong things. Perhaps the tests protected implementation rather than behavior. Perhaps useful rules existed but were not found when the developer or agent needed them.
Cheap code is a reason, not a method
This change in the economics of code gives me a reason to revisit an old idea, but it does not answer those questions. What I expect a specification to accomplish is settled; the structure that delivers it is not.
The open questions all start from that goal. What belongs in a specification, and which parts does an agent actually need for the task in front of it? How do I separate what the software does from how it got built — and how would I even know if any of this is working?
Those questions deserve more than one article. For now, the first principle is enough:
A specification earns its keep only when it makes software easier to change.
AI changed everything. Again. Now the specification comes before the software. Why didn’t anyone think of this sooner? … Oh, wait.
The reason nobody thought of it sooner is that everybody did — it was called waterfall. Write the whole specification up front, then build. It failed, and not because the idea was foolish: the first real feedback arrived only when the software did, months later, and it usually said the specification had described the wrong system.
Agile fixed the feedback loop by shrinking the work into small slices. That made separately maintained prose specifications feel optional, and many teams relied on a story, a conversation, tests, and the code instead. So for most of my career, when I encountered a specification as a distinct document, it had been written after the software: usually for newcomers, so that nobody had to explain the system in person for the tenth time. A summary of code that already existed, not a guide to what should exist.
Writing specifications beforehand is not what killed waterfall — steering too rarely did. But once separately maintained prose specifications felt optional, the economics made sure they stayed optional.
The code is the specification
Code was usually the expensive part. When a requirement changed, you had to understand the existing system, change the implementation, repair whatever broke, and verify that the result still worked.
Updating the specification on top of that was a cost nobody was willing to pay. And the code already specified how the application actually behaved. So the code became the source of truth and the specification slowly became a historical record.
Cheaper code changes the economics
AI makes producing and changing code cheaper, which means implementations can change faster and grow unsupervised.
At some point, treating the code itself as the specification stops working. The behavior is still all there — but so is every accident that shipped. The code tells you what the system does; it has stopped telling you which parts it does on purpose.
Now that code is the cheap, replaceable artifact, the roles flip: the specification becomes the thing worth keeping. That shift is what makes specification-driven development interesting, and perhaps necessary for teams that want to use AI effectively on large projects.
A specification has to earn its keep
Cheaper code does not make a specification good. Its existence is not the goal. Neither are its length, level of detail, or approval status.
A good end-to-end test suite aims at much the same result. It records observable behavior in a form the machine can check, giving me enough confidence to change the implementation without accidentally changing the behavior.
In many applications I have worked on, neither artifact achieved that. Specifications drifted away from the code. Tests mirrored implementation details, broke during harmless changes, and became another system developers were afraid to touch.
Their existence was treated as success. Test coverage was measured. Documents were approved. The more important question was rarely asked: Did any of this make the application easier to change?
If the answer is no, the next question should be simple: why? Perhaps the specification described the wrong things. Perhaps the tests protected implementation rather than behavior. Perhaps useful rules existed but were not found when the developer or agent needed them.
Cheap code is a reason, not a method
This change in the economics of code gives me a reason to revisit an old idea, but it does not answer those questions. What I expect a specification to accomplish is settled; the structure that delivers it is not.
The open questions all start from that goal. What belongs in a specification, and which parts does an agent actually need for the task in front of it? How do I separate what the software does from how it got built — and how would I even know if any of this is working?
Those questions deserve more than one article. For now, the first principle is enough:
A specification earns its keep only when it makes software easier to change.
Making Sense of Specification-Driven Development
To know whether specification-driven development works, I first had to ask what a specification is supposed to do.
AI changed everything. Again. Now the specification comes before the software. Why didn’t anyone think of this sooner? … Oh, wait.
The reason nobody thought of it sooner is that everybody did — it was called waterfall. Write the whole specification up front, then build. It failed, and not because the idea was foolish: the first real feedback arrived only when the software did, months later, and it usually said the specification had described the wrong system.
Agile fixed the feedback loop by shrinking the work into small slices. That made separately maintained prose specifications feel optional, and many teams relied on a story, a conversation, tests, and the code instead. So for most of my career, when I encountered a specification as a distinct document, it had been written after the software: usually for newcomers, so that nobody had to explain the system in person for the tenth time. A summary of code that already existed, not a guide to what should exist.
Writing specifications beforehand is not what killed waterfall — steering too rarely did. But once separately maintained prose specifications felt optional, the economics made sure they stayed optional.
The code is the specification
Code was usually the expensive part. When a requirement changed, you had to understand the existing system, change the implementation, repair whatever broke, and verify that the result still worked.
Updating the specification on top of that was a cost nobody was willing to pay. And the code already specified how the application actually behaved. So the code became the source of truth and the specification slowly became a historical record.
Cheaper code changes the economics
AI makes producing and changing code cheaper, which means implementations can change faster and grow unsupervised.
At some point, treating the code itself as the specification stops working. The behavior is still all there — but so is every accident that shipped. The code tells you what the system does; it has stopped telling you which parts it does on purpose.
Now that code is the cheap, replaceable artifact, the roles flip: the specification becomes the thing worth keeping. That shift is what makes specification-driven development interesting, and perhaps necessary for teams that want to use AI effectively on large projects.
A specification has to earn its keep
Cheaper code does not make a specification good. Its existence is not the goal. Neither are its length, level of detail, or approval status.
A good end-to-end test suite aims at much the same result. It records observable behavior in a form the machine can check, giving me enough confidence to change the implementation without accidentally changing the behavior.
In many applications I have worked on, neither artifact achieved that. Specifications drifted away from the code. Tests mirrored implementation details, broke during harmless changes, and became another system developers were afraid to touch.
Their existence was treated as success. Test coverage was measured. Documents were approved. The more important question was rarely asked: Did any of this make the application easier to change?
If the answer is no, the next question should be simple: why? Perhaps the specification described the wrong things. Perhaps the tests protected implementation rather than behavior. Perhaps useful rules existed but were not found when the developer or agent needed them.
Cheap code is a reason, not a method
This change in the economics of code gives me a reason to revisit an old idea, but it does not answer those questions. What I expect a specification to accomplish is settled; the structure that delivers it is not.
The open questions all start from that goal. What belongs in a specification, and which parts does an agent actually need for the task in front of it? How do I separate what the software does from how it got built — and how would I even know if any of this is working?
Those questions deserve more than one article. For now, the first principle is enough:
A specification earns its keep only when it makes software easier to change.