Introduction#
The last post ended with the feeling that writing a clear system prompt is a lot like writing a spec. The next class was about exactly that. Spec-driven development means letting specifications steer a code agent from requirements to review. The reading pulled in two directions: an article on spec-driven tools from Martin Fowler’s site, and an essay Peter Naur wrote in 1985.
The two classes after that started our project. Engestofte Gods came to present their problems on Thursday, and Monday’s class was the project start.
So this post starts with specs and ends with the company we will work with for the rest of the course.
Spec-First, Spec-Anchored, Spec-as-Source#
In the article, Birgitta Böckeler tries out three spec-driven tools (Kiro, GitHub’s spec-kit and Tessl) and sorts the approaches into levels that build on each other:
- Spec-first: a spec is written before the AI starts coding, and it guides that one task.
- Spec-anchored: the spec is kept after the task is done and used when the feature changes later.
- Spec-as-source: the spec is the main artifact. Humans only edit the spec, and the code is generated from it and never touched by hand.
She also separates a spec from a memory bank. A spec describes one feature or change. A memory bank is the general context an agent always gets, like the AGENTS.md files from the last post.
Then come the criticisms, and they made me more careful about the whole idea. The tools use one workflow for every size of problem, so Kiro turned a small bug into four user stories with 16 acceptance criteria. She calls it a “sledgehammer to crack a nut”. spec-kit produced so many repetitive markdown files that she would rather have reviewed the code. The agents still ignored instructions or duplicated existing code, so all those documents gave a false sense of control. It is not even clear who the tools are for.
Last, she compares it to model-driven development, which never caught on for business software because it was too heavy and too rigid. Spec-as-source could end up with that rigidity and the unpredictability of an LLM on top. She closes with a German word, Verschlimmbesserung: an improvement that makes things worse.
Who Holds the Theory?#
Naur’s essay, “Programming as Theory Building”, says that programming is mostly about building a theory. The theory is the developer’s understanding of how the program fits the real world it serves, and why each part is the way it is. It lives in the developers’ heads. The code and the documentation are what the theory leaves behind, but they don’t contain it. When the team that holds it breaks up, the program is in a sense dead, and Naur argues that the theory can’t be rebuilt from the documentation alone.
Read today, that sounds like a warning about specs, because a spec is documentation. If an AI writes it and I approve it without thinking, the theory ends up nowhere. The model forgets it after the call, and it never got into my head.
My position is that letting the AI draft the spec is fine, but owning the design is not something I can hand over. That is the lesson from the Tetris post again. The agent filled every gap I had not decided on, and I only found out what it chose when the game was in front of me.
What keeps the theory in my head is the grilling before the spec. The agent questions me about the plan and suggests an answer to each question, but every answer I give is a decision I have to make. The spec then records decisions I have already made, and writing it down is the part I am happy to give away.
Böckeler is the counterweight. A spec I haven’t really read gives me exactly the false sense of control she describes, and a stack of markdown is no fun to review. So the specs have to stay short and the tickets small, and the review still has to happen against the code.
The Workflow I Use Now#
Since the Tetris post, I have been working with Matt Pocock’s skills. My workflow uses five of them. The first three run in one context window, so everything said during the grilling is still there when the spec is written:
grill-with-docsinterviews me about the plan and writes the glossary and the decision records as we go.to-specturns the conversation into a spec, without a new interview.to-ticketsbreaks the spec into small tickets that each cut through the whole system, and notes which tickets block which.
Then every ticket goes through a loop. implement builds it, and code-review checks the result against the coding standards and the spec. The review runs in a clean context, ideally with an agent from another provider, so it judges the code without the reasoning that produced it. Any violations get fixed, and the next ticket starts.
flowchart TD
subgraph plan["One context window"]
G["grill-with-docs"] --> S["to-spec"]
S --> T["to-tickets"]
end
subgraph perTicket["Loop per ticket"]
I["implement"] --> R["code-review
clean context, another provider"]
R --> F["fix violations"]
end
T --> I
F -->|"next ticket"| I
The class exercise was a quiz website built from a spec. Our teacher decided to run it live in class, so everyone could see how the skills are set up and run, and we went through part of the workflow together. Our teacher used Codex, and it went straight from the grilling to implementing, without to-spec and to-tickets in between. The reason was a line at the very bottom of its last round of questions, saying that once they were answered, it would implement the feature. With a long round of questions to get through, that line was easy to miss.
It is the same lesson as in my earlier Tetris post: The agent is a tool, and the developer has to stay in control. If I scroll through a grilling without reading it properly, I might as well leave the design to the AI, and then there is no point in grilling at all.
The Books Behind the Skills#
Many of the skills build on well-known books, so I have been reading some of them:
| Book | Status | Where it shows up |
|---|---|---|
| A Philosophy of Software Design (Ousterhout) | Read | Deep modules, with a simple interface over a lot of code |
| The Pragmatic Programmer (Hunt and Thomas) | Reading | Tracer bullets, the slices in to-tickets |
| Domain-Driven Design (Evans) | Researched | Ubiquitous language, the CONTEXT.md glossary |
| Test-Driven Development: By Example (Beck) | Some chapters | Red, green, refactor in the tdd skill |
I like that Pocock doesn’t rely only on his own idea of what good software is. His skills keep referring back to the greats, and many of these books are held in very high regard in the software community. If the skills are built on the principles in those books, they must be off to a good start.
The Engestofte Case#
On Thursday, Engestofte Gods visited with a set of concrete problems for us to work on. It is a country estate on Lolland that lives mostly from weddings, with a Christmas market and holiday-house rentals on the side. The staff are named on the estate’s own website, but just as I only use my first name here, I will refer to them by their roles.
Picture a wedding at the estate. The inquiry comes in by email, the date goes on a card in Trello, the details go into an agreement document and the invoice into e-conomic. Every step is typed by hand, and the overview of how it all fits together lives in the event manager’s head.
The event manager came with a list of smaller things he would like built, and his own priority was to get rid of the human errors from all that manual work and keep everything up to date. The biggest problem was one he didn’t flag himself: the workflow is fragmented, and everything depends on him. Trello is used for everything, and the way it is all organised is built on his ideas. That leads to mistakes, like a summer house booked twice, and it makes him impossible to do without. That is what we want to fix.
At Monday’s project start, my partner and I started on the Engestofte case. The idea is a system that owns an event from the first inquiry to the final invoice, so the information is typed in once. Right now it is only an idea with a lot of open questions.
Specs From Here On#
The class asked how we plan to use specs from now on. Most of my plan revolves around the workflow above, with two additions.
The first is to size the spec to the problem. A small fix only needs a ticket, and a new feature gets the whole workflow.
The second is to read everything the AI drafts. The spec and the tickets are drafts until I have read them and fixed what is wrong. If I skip that, I am back at the false sense of control Böckeler warns about.
In Böckeler’s terms, I would call that spec-anchored, and it is worth explaining why it isn’t one of the other two.
It isn’t spec-first, because the spec doesn’t stop mattering when the last ticket is done. The specs, the tickets, the glossary and the decision records all stay in the repo, and the next grilling starts from them. If something unforeseen comes up during implementation, I expect to update the spec so it still describes what was built. A new feature or a refactor will probably get a spec of its own, so the specs become a record of decisions, one change at a time. Böckeler notes that the tools rarely say how a spec is maintained over time, and I can’t say much more yet. It will depend on the situation.
It isn’t spec-as-source either. Nothing is generated from the spec, and nobody is told to keep their hands off the code. The code is reviewed against the spec, and violations are fixed in the code. Spec-as-source is not for me, because I want to read and own the code.
This is also where Naur comes back in. In his view, the code, the specs and the docs are all things the theory leaves behind, and none of them hold it. Spec-as-source makes the spec the program, and if I never read the code it produces, I can’t explain or justify it the way Naur says the theory lets you. Spec-first lets the spec go once the task is done, and with it the record of why things are the way they are. Spec-anchored keeps that record. Naur argues the theory can’t be rebuilt from documentation alone, so the kept specs are not enough on their own. But when the next change starts with a grilling against the specs and decisions already in the repo, I have to understand them again to answer the questions. The specs are not the theory, but they are the way back to it.
Conclusion#
Engestofte will be the first real test of this, with a customer whose domain we have to learn before we can write a single spec. The next post is about collaborative agentic development, and how my partner and I plan to split the work between us and our agents.
- Daniel