Popular searches
//

Code is the best spec: Reviews in spec-driven development

21.10.2026 | 6 minutes reading time

Anyone working with Spec-driven Development (SDD) spends a lot of time reading specs and code. To achieve the promised efficiency gains, you have to decide where to invest your review time. After working with my team on a greenfield project using the BMad Method for three months, my answer is clear: for well-scoped features, a quick look at the spec's acceptance criteria is enough. Thorough inspection belongs in the code. This is the only way to ensure features are implemented correctly, solutions are not overengineered, and the codebase remains maintainable over the long term.

Two Ways to Live Spec-Driven Development

For three months, our experienced engineering team worked on a greenfield project using an SDD framework, in our case, the BMad Method. First, we developed and documented our architecture and coding conventions. Then, we moved on to implementing the first features. As intended by BMad, we didn't write the spec files ourselves. We gave the AI a high-level description of the feature, and an agent generated a complete spec using the corresponding framework skills. In doing so, we noticed that the AI creates a large volume of documents in a short amount of time. It breaks down a feature into stories, highlights the details of each story, and outlines an implementation plan. From there, working code was produced rapidly. To avoid losing the momentum gained, you have to accept that you cannot review everything in detail. When reviewing, setting priorities is essential. Broadly speaking, there are two distinct approaches.

Spec as a Contract: You thoroughly review the generated spec and refine it until it completely describes the feature. The hope behind this approach is that the AI will implement the feature independently and the code review will hold virtually no surprises.

Spec as a Compass: You only check the generated spec for overall directional alignment, move quickly into implementation, and shift thorough inspection to the code review. If adjustments are needed, you make them directly with the AI in the code.

Spec-Review-vs-Code-Review-english.jpg

What a Spec Review Should Achieve

In the beginning, we examined all feature specs meticulously. Our goal was to ensure functional correctness right at the start of development. In the spec, feature details were formulated in natural language, making them easy to discuss with the AI. Finding a misunderstanding in the spec is also cheaper than discovering it later in the code, as no AI costs for implementation have been incurred up to that point. During the review of the generated code, however, we still noticed several issues that we couldn't catch during the spec review, even though the spec already covered technical implementation details.

Where Spec Reviews Reach Their Limits

BMad often includes phrases that sound like diligence in our generated specs: "should be configurable," "should be extensible." Even when these details were never requested, nobody objects during the spec review because they sound harmless and plausible. But the implementing AI takes them very seriously. As a result, it sometimes gets fixated on these minor details, leading to unnecessarily complex code. Across multiple features, code accumulates this way and then needs to be reviewed, tested, and maintained.

Furthermore, a spec often fails to reveal whether implementing a feature in the proposed way makes technical sense. In some cases, we put a lot of work into developing a spec and reviewed it thoroughly, only to realize during implementation that the feature could only be realized with disproportionately high complexity. Had we transitioned faster from the spec phase to the implementation phase, we could have saved ourselves that work.

Our Approach: Lean Spec Reviews, Thorough Code Reviews

Starting with the greenfield project, there were few existing conventions for the AI to follow. As a baseline, we used the SDD framework to create spec files for architecture and coding conventions. Nevertheless, the issues mentioned above occurred with our initial features. Thus, we invested a lot of time in code reviews right from the start.

Because we were also reviewing the specs thoroughly, we ended up inspecting many things twice: once in the spec, once in the code. The meticulous spec review didn't save us from doing a thorough code review, it simply came on top of it.

Additionally, reviewing specs was quite tedious, as AI-generated specs tend to be long, verbose, and cryptic in places. For some paragraphs, it was unclear what the AI actually meant and whether it was even relevant for the implementation. With engineering experience, on the other hand, reading what actually happens in code is relatively straightforward. Code is ultimately the most precise specification: it unambiguously describes what the system actually does.

So, we reduced the spec review to the acceptance criteria. They show whether the AI understood the feature correctly from a domain perspective, covering the primary goal of the spec review. The actual verification happens in the code. With this shift, we moved from Spec as a Contract to Spec as a Compass. This eliminated duplicate work and reduced the overall effort per feature, even though we continued to look closely at the code.

Another advantage: system understanding is preserved. By consistently reviewing code, we ensured high code quality. Furthermore, we maintained a deep understanding of the codebase, even though we didn't write most of it ourselves. This formed the foundation for well-informed architectural decisions. In parallel, we continuously refined our architecture and convention files. Insights from code reviews were fed back into these files so the AI wouldn't repeat the same mistakes. Together with a growing body of examples in the code, the AI's output improved over time.

Risks of a Lean Spec Review and How We Mitigate Them

The biggest risk: if a spec contains major errors, the AI builds an implementation that we subsequently have to throw away or refactor heavily. That costs time and AI budget, all the more so for larger features. Our SDD framework helped us here: it asks many clarifying questions before creating a spec, ensuring the AI grasps the feature well. Additionally, checking acceptance criteria prior to implementation mitigates this risk. Of course, adjustments were still necessary after completing the implementation phase. In those cases, we went through a few iterations with the AI until the feature was ready. These were often details that a tighter spec review might have caught, but in the code, they required little effort to fix since we rarely had to rewrite large sections.

Another consequence: when we make adjustments directly in the code, the spec no longer matches the implementation. We consciously accept this trade-off because our specs are merely temporary working documents for implementation. After completing a few subsequent features, they become outdated anyway. The most reliable description of the system is the code itself.

Conclusion: Spec for the What, Code for the How

After three months with the BMad Method, a clear way of working emerged for our team. In the spec, we verify the acceptance criteria, checking whether the AI understood the feature correctly from a domain perspective. This is complemented by architecture and convention files as a baseline, which get more detailed with every code review. In the code, we review the implementation: hidden complexity, scope, code quality, and correctness. SDD doesn't replace the craft of software engineering, it shifts its focus. As the engineering team, we inspect and decide, the AI implements and corrects. My advice: use the spec as a compass instead of focusing on every detail. Apply your expertise where the leverage is highest: in the generated code.

//

More articles in this subject area

Discover exciting further topics and let the codecentric world inspire you.