For most of software's history the specification was a means and the code was the asset — specs were written, partially followed, and abandoned. Cheap generation inverts the economics. When a competent implementation can be produced in minutes from a sufficiently precise description, the description is the expensive part and the code is closer to a build artefact.
What actually changed
- Ambiguity now costs more. A vague requirement used to produce a clarifying question from an engineer. It now produces a confident, plausible, wrong implementation that must be read and unpicked.
- Regeneration became viable. Where a spec is precise and tests exist, replacing an implementation is a realistic option rather than a rewrite project.
- Review moved upstream. Reviewing a diff catches problems late; reviewing the spec catches the same problems before anything is built.
What a spec has to contain to be buildable
Prose intent is not enough. The parts that determine whether an implementation is right are the ones usually left implicit:
- Behaviour, including failures. What happens on missing input, duplicate submission, upstream timeout, partial success.
- Invariants. What must be true before and after, regardless of path.
- Boundaries. What this component does not do, and what it may not touch.
- Observable outcomes. How you would verify it from outside, which is what makes acceptance a check rather than a debate.
- Non-goals. The section that prevents the most rework and is skipped the most often.
The test for a sufficient spec
Could two competent implementers, working independently and without talking to you, produce systems that pass the same tests? If not, the gap between them is exactly the ambiguity a generator will fill on its own — silently, plausibly, and differently each time.
Specs as the durable artefact
This is the practical shift: version the specification with the same discipline previously reserved for code. It gets reviewed, it gets diffed, and when behaviour changes the spec changes first. Where a spec, its acceptance criteria and its tests are all current, the implementation becomes replaceable — which is the closest thing to a defence against inheriting code nobody understands.
Where this fails
- Over-specification. Prescribing implementation in the spec removes the freedom that made regeneration valuable and produces a document nobody maintains.
- Specs that drift. A spec contradicting the running system is worse than none, because people trust it. Whatever is not verified by tests will drift.
- Ceremony without benefit. Not everything needs a formal spec. A one-line change does not, and insisting otherwise discredits the practice for the cases that do.
A workable middle
Write the spec at the level of the interface and the behaviour, not the implementation. Keep acceptance criteria executable so drift is caught mechanically. Treat the ADR as the record of *why* and the spec as the record of *what* — and accept that for small changes the whole thing collapses into a well-written ticket, which is fine.
Frequently Asked Questions
Is this waterfall by another name?
No. Waterfall specified everything up front and then built for months. This specifies one increment precisely, builds it quickly, and iterates - the cycle stays short, the precision moves earlier within it.
Who writes the spec - product or engineering?
Whoever owns the outcome drafts it; engineering reviews it before work starts. The review is the part that cannot be skipped, because that is where the unstated assumptions surface.
Do we still review the code?
Yes. Spec review catches wrong intent; code review catches wrong implementation and poor fit with the system. Neither substitutes for the other.
References
- The Agentic Engineering Trends Report 2026 — SaaSRise
- Documenting Architecture Decisions — Michael Nygard / Cognitect
About Jishu Labs
Jishu Labs is a software development company founded in 2016. We build custom software, AI/ML systems, and full-stack web and mobile applications for clients, and we make eight AI tools for software teams.