← Blog
SDDAI agentsbusiness rulesDDD

The Anemic Spec: Spec-Driven Development, AI Agents and Business Rules

A specification can be detailed and still leave business rules implicit.

A “Cancel” button measured with calipers on a paper mockup: the button is described precisely, while the cancellation conditions remain undefined

The “Cancel” button is 120 pixels wide.

Take a meeting room booking service. The spec sets the button color, the confirmation message, the API to call and the response format. The agent even has an implementation plan.

An organizer wants to cancel ten minutes before their booking starts. The spec doesn’t say whether they’re allowed to. The cancellation deadline appears neither in the acceptance criteria nor in the generated tasks.

A business decision is missing. A few lines would be enough to describe it, but someone has to make it first.

With Spec-Driven Development (SDD), agents rely more heavily on specifications to produce code. So we need to be able to find in them the rules to apply, the examples that let us check those rules, and the points that still need clarifying.

The spec as a reference

SDD covers several practices. Birgitta Böckeler distinguishes three approaches: spec-first, where the spec comes before the implementation; spec-anchored, where it is kept for later changes; and spec-as-source, where humans edit the spec and the code is generated from it.

When the spec serves as a reference, a missing rule can have consequences for the software. A developer may recover it through their knowledge of the product, an existing test or a conversation. An agent can explore the repository and ask questions. Both can also move forward on an assumption without getting it validated.

If the tests carry the same assumption, they will confirm that the code respects it. The whole thing can then serve as a reference for further changes. A decision made for lack of information becomes hard to tell apart from a rule the product team actually wanted.

Rules that stay implicit

I call an anemic spec a specification that gathers information but leaves implicit the decisions the expected behavior depends on, and the means to check them.

The term echoes the Anemic Domain Model described by Martin Fowler: objects carry the data, while behavior is organized elsewhere. I’m borrowing that idea of responsibilities placed elsewhere. The analogy has its limits: with an Anemic Domain Model, the rules may be known and correctly applied. In an anemic spec, some of them have sometimes never been defined.

Here’s what I expect from a specification:

ResponsibilityWhat we need to be able to find
Describe the intentThe problem to solve, the desired outcome and the scope.
Spell out the decisionsThe rules, when they apply, the exceptions and the trade-offs.
Enable verificationExamples and expected results able to expose a misinterpretation.
Flag uncertaintyValidated decisions, assumptions, open questions and what’s out of scope.
Explain where rules come fromTheir source and the people who can clarify their meaning or change them.
Track changesWhat changed, why, and which situations the change applies to.

Not everything has to fit in a single file. A rule can be referenced in domain documentation, a contract or an acceptance scenario. What matters is being able to find it and knowing which version applies.

The trouble starts when this information stays in an expert’s head or in a conversation nobody can find. Adding pages to the spec doesn’t necessarily solve that.

Conceptual grid with two dimensions, amount of text and explicitness of decisions: concise and useful, detailed and useful, short and anemic, long and anemic. Anemia shows in the missing decisions, not in the length of the text
Amount of text and precision of decisions are two separate dimensions. This chart is conceptual. Open the diagram at full resolution ↗

Two possible implementations

Back to the booking. The functional part fits in a few lines:

Function: handle a cancellation request.
Input: booking identifier.
Output: request status.
Interface: Cancel button and confirmation dialog.

The organizer asks to cancel a confirmed booking, ten minutes before it starts. Two implementations can fill in this spec with different rules:

Interpretation AInterpretation B
Rule addedCancellation allowed until the start.Cancellation allowed until 24 hours before the start.
ResultAccepted.Rejected.
Tests written for this interpretationGreen.Green.

The spec can’t settle it. Each version added a rule that had never been decided.

Another LLM might suggest a third deadline or ask for clarification. It’s up to the product team to choose the rule that fits the need.

When reviewing a spec, looking for two incompatible business behaviors that the text both allows helps spot this kind of gap. Several architectures can satisfy the same requirement. In this example, the disagreement is directly about the user’s right to cancel.

Keeping uncertainty visible

Demanding every rule before starting assumes you know the need down to the last detail. What we mostly need are the decisions required for the scope at hand, and a clear view of what remains to be clarified.

Example Mapping separates rules, examples and unanswered questions. That separation helps avoid mistaking a well-written assumption for a validated requirement.

Suppose the product team settles on the 24-hour deadline. The spec could contain this:

R-12 - Cancellation by the organizer

Status: decision validated by the product team.
Origin: trade-off on the minimum cancellation notice.

Rule: the organizer can cancel a confirmed booking if it starts at least 24 hours after the time of the request. The notice is an elapsed duration, independent of local time.

Examples:
- Exactly 24 hours before: cancellation accepted.
- 23 hours and 59 minutes before: cancellation rejected.
- When rejected, the booking stays confirmed.

Out of scope: exceptions granted by an administrator.
Open question: what if the notification cannot be delivered?

The examples pin down the boundary and make it testable. They don’t cover the feature’s whole test strategy.

The notification problem stays open. You can experiment with the cancellation rule without having solved it, as long as you know what you’ll be able to evaluate and what will remain incomplete.

Distinguishing between a validated decision, an assumption to test, an open question and a superseded decision lets you work without giving every line of the document the same status.

Versioning keeps track of changes. Their business scope needs stating too. If the cancellation deadline changes, the new rule can apply to future bookings while leaving existing ones under the previous terms. The commit date isn’t enough to define that policy.

Feedback loops

Feedback starts during implementation. Writing the code can reveal a contradiction, an edge case, a technical constraint or a distinction missing from the model. The spec has to be able to evolve from these discoveries.

Kent Beck criticizes approaches that assume implementation will teach us nothing that could change the spec. Work on behavior continues during development, then with feedback from use.

We have two things to check:

  • Conformance: the software respects the decisions as stated.
  • Relevance: those decisions produce the intended outcome.

Tests can check the 24-hour rule. User feedback may teach us that this rule stops them from releasing rooms that would otherwise sit empty. The software then respects the spec, but that feedback may lead us to revisit the rule.

Feedback loops between four stages: the specification (rules, examples, open questions) is implemented as code and tests, which check conformance; observing experience and usage lets you assess relevance; the decision step chooses to fix the code, revise the rule or keep exploring, then revises the specification if needed. Learning while coding also leads straight to that decision
Discoveries made during development and use can lead to changing the spec. Open the diagram at full resolution ↗

When a gap appears, the team has to decide whether to fix the code, revisit the rule or keep exploring. Automatically updating the spec to match the code could cement a mistake.

Organizing spec reviews

Having another LLM review a spec can help find contradictions and counterexamples. Agreement between several models doesn’t tell you whether a rule fits the business.

I prefer to ask for specific objections:

Rule in question: ...
Two possible interpretations: ...
Situation that tells them apart: ...
Consequence for the user: ...
Information or decision needed: ...

The team can then fix, experiment with or postpone the point raised. A string of rephrasings and hypothetical cases can also drag the review out without helping anyone decide. The review can stop when the team has the decisions needed for the next increment and knows how to evaluate the result.

The amount of text matters too. In her SDD trials, Böckeler describes a reading load that is sometimes out of proportion for small tasks. If the generated volume exceeds what the team can examine, some parts risk being approved without a real review.

Domain experts and the product team review the rules and expected outcomes described in the spec. Developers review the model, the constraints and their technical consequences. Testing work brings counterexamples and sharpens the observable results. The same person can contribute to several of these activities.

To make this review easier, a rule should be easy to find, along with its rationale and examples. Copying it into five files multiplies the places to fix at the next change.

What DDD brings

Domain-Driven Design (DDD) helps pin down the vocabulary shared with the business (Ubiquitous Language), the boundaries of the model and the invariants to protect. A “cancellation requested”, a “cancellation accepted” and a “booking cancelled” can refer to different facts. Lumping them into a status field without spelling out how they relate leaves part of the behavior undefined.

Bounded Contexts define where that vocabulary applies. Work on Aggregates helps define the boundaries within which invariants must hold. Behavior-Driven Development (BDD) and examples provide concrete situations to discuss these rules and check them.

This work is done with the people who know the domain. Sections titled “DDD”, “Aggregates” or “invariants” in a document don’t guarantee that the corresponding decisions have been made.

Before handing a spec to an agent, I want to be able to check its rules, understand the trade-offs and spot the uncertainties. Spec review relies on examples to check that the described behavior meets the need. It starts again every time feedback leads to changing a rule.


References

Spec-Driven Development

  • Birgitta Böckeler, Understanding Spec-Driven-Development: Kiro, spec-kit, and Tessl, martinfowler.com, October 2025: the three approaches, spec-first, spec-anchored and spec-as-source, and the reading load observed on small tasks. martinfowler.com
  • Kent Beck, LinkedIn post on descriptions of Spec-Driven Development: the critique of approaches that assume implementation will teach us nothing that could change the spec. linkedin.com

Domain modeling

  • Martin Fowler, AnemicDomainModel, martinfowler.com: objects carry the data, behavior is organized elsewhere. martinfowler.com
  • Martin Fowler, BoundedContext, martinfowler.com: where a vocabulary applies. martinfowler.com
  • Vaughn Vernon, Aggregates, excerpt from Implementing Domain-Driven Design (Addison-Wesley, 2013), InformIT: the boundaries within which invariants must hold. informit.com

Examples

  • Matt Wynne, Introducing Example Mapping, Cucumber, December 2015: separating rules, examples and unanswered questions. cucumber.io

The booking scenarios are fictional. The charts are conceptual; they do not represent measured results. Cover illustration generated with AI.