cd /news/ai-agents/specs-guidelines-and-sensors-in-spec… · home › topics › ai-agents › article
[ARTICLE · art-169117] src=martinelli.ch ↗ pub= topic=ai-agents verified=true sentiment=· neutral

Specs, Guidelines, and Sensors in Spec-Driven Development

Writing guidelines for AI coding agents is insufficient without automated "sensors" that fail the build when code violates a rule, according to a Spec-Driven Development article that cites Neal Ford, Rebecca Parsons, and Patrick Kua's concept of fitness functions from their book "Building Evolutionary Architectures." The article argues that specs should state only business behavior, while implementation details belong in guidelines split into company-wide and project-specific levels, and it illustrates the approach with ADR-003, which bans JPA in favor of jOOQ using a Maven Enforcer rule named "adr-003-no-jpa" and an ArchUnit rule named "adr003NoJpa." The author contends that without such checks an AI agent will eventually add spring-boot-starter-data-jpa while the build stays green and nobody notices.

by read6 min views2 publishedNov 13, 2026
Specs, Guidelines, and Sensors in Spec-Driven Development
Image: Martinelli (auto-discovered)

Specs describe the what #

In Spec-Driven Development, the specification says what the system must do, not how it does it. In practice, many specs mix both.

A typical example is a use case step like this: "The user clicks the Save button in the Vaadin Grid, and the service calls the repository." This step mixes business behavior with UI technology and internal design. A business expert cannot review it, and when you change the UI framework or the persistence layer, the spec is wrong although the business behavior is the same.

A good step says only what matters to the business: "The clerk saves the order. The system checks that the delivery date is in the future." It stays valid when the technology changes.

Leaving the how out of the spec does not mean leaving it out of the project. If nobody writes it down, the AI agent decides it, and it may decide differently each time it generates the code.

The how belongs to the guidelines #

The how belongs in the guidelines. You write them once, and every use case uses them.

Guidelines contain three things:

  • Coding and design rules , for example naming, null handling, how to write a Vaadin view, how to structure a jOOQ query.
  • The general architecture , for example layers, modules, Self-Contained Systems, how systems talk to each other.
  • Architecture Decision Records (ADRs) , the concrete decisions with their reasons, for example "we use jOOQ, not JPA".

I split them into two levels. Company-wide guidelines are the same in every project, so a team can reuse its Spring Boot, Vaadin, and jOOQ rules. Project-specific guidelines hold decisions for one project only, for example which payment provider we call.

A guideline without a sensor is only a wish #

Writing guidelines down is not enough. An AI agent follows them most of the time and then drifts away, for example when the context gets long or when its training examples point in another direction. Developers drift too.

So every guideline needs a sensor: an automatic check that fails when the code breaks the rule.

Sensors also give the agent fast feedback. When the build fails with a clear message, the agent fixes the mistake in its next step, before a human reviews the code. So the message should say what is wrong and which rule it breaks.

Neal Ford, Rebecca Parsons, and Patrick Kua call these checks fitness functions in their book "Building Evolutionary Architectures". When AI agents write most of the code, you need them for every guideline.

Example: "We use jOOQ, not JPA" #

In my projects I use jOOQ for database access, not JPA. The ADR looks like this:


Status: Accepted

## Context
The application is database-centric. We need full control over SQL,
vendor features of Oracle and PostgreSQL, and type safety at compile time.

## Decision
All database access uses jOOQ with code generated from the schema.
JPA, Hibernate, and Spring Data JPA are not used.

## Consequences
No lazy  problems and no hidden queries.
Developers must know SQL.

## Verification
- Maven Enforcer rule "adr-003-no-jpa" bans the JPA dependencies.
- ArchUnit rule "adr003NoJpa" bans the JPA packages in the code.

An AI agent that implements a new use case has seen thousands of Spring Boot examples with @Entity and JpaRepository. Without a sensor, it will sooner or later add spring-boot-starter-data-jpa. The build stays green, and nobody notices.

Sensor 1: ban the dependency

The first sensor works on the build level. The Maven Enforcer Plugin fails the build when a banned dependency appears, also as a transitive dependency.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-enforcer-plugin</artifactId>
    <executions>
        <execution>
            <id>adr-003-no-jpa</id>
            <goals>
                <goal>enforce</goal>
            </goals>
            <configuration>
                <rules>
                    <bannedDependencies>
                        <excludes>
                            <exclude>jakarta.persistence:jakarta.persistence-api</exclude>
                            <exclude>org.hibernate.orm:*</exclude>
                            <exclude>org.springframework.boot:spring-boot-starter-data-jpa</exclude>
                        </excludes>
                        <message>ADR-003: We use jOOQ, not JPA. See docs/architecture/decisions/ADR-003.md</message>
                    </bannedDependencies>
                </rules>
            </configuration>
        </execution>
    </executions>
</plugin>

The message names the ADR and its file, so the agent knows which rule it broke and where to read the reason.

Sensor 2: ban the code

The second sensor works on the code level. An ArchUnit test checks that no class uses the JPA packages, even if they come onto the classpath through some other library.

@AnalyzeClasses(packages = "ch.martinelli.demo",
        importOptions = ImportOption.DoNotIncludeTests.class)
class ArchitectureDecisionsTest {

    @ArchTest
    static final ArchRule adr003NoJpa = noClasses()
            .should().dependOnClassesThat()
            .resideInAnyPackage(
                    "jakarta.persistence..",
                    "org.hibernate..",
                    "org.springframework.data.jpa..")
            .because("ADR-003: we use jOOQ, not JPA");
}

The because clause shows up in the failure message.

Now, when the agent adds JPA, the build fails with "ADR-003: We use jOOQ, not JPA". The agent reads the ADR and rewrites the code with jOOQ, without a human reviewer.

Make it a habit #

Every ADR and every guideline should have a sensor. Two rules help.

1. Add a Verification section to the ADR template. It names the sensor, and the sensor carries the ADR id in its name or message. This gives traceability in both directions, the same way the use case id links use cases and tests.

2. Tie the sensor to the ADR lifecycle.

  • When an ADR is accepted , its sensor must exist.
  • When an ADR is superseded , its old sensor is removed or replaced in the same change. Otherwise the old rule blocks the new decision, or the new decision has no protection.
  • When an ADR is deprecated , its sensor goes away.

The same works for the general architecture. Module boundaries can be checked with Spring Modulith or ArchUnit. "No shared database between Self-Contained Systems" can be checked with separate database users and grants. A response time requirement can be checked with a Gatling or k6 test that has a threshold. And coding rules have their usual sensors: Checkstyle, Error Prone, NullAway with JSpecify, OpenRewrite recipes.

If every guideline names its sensor, you can see which rules are checked and which are not. The ones without a sensor are your to-do list.

When no tool can check it #

Not every guideline fits into a compiler or a test. "Use the terms from the glossary" or "keep views simple" are hard to check with a tool.

For these, an AI reviewer can be a softer sensor: a second agent checks the result against one guideline only. It is less reliable than a failing build, but it catches many problems.

Some ADRs have nothing to check, for example "We chose Vaadin because the team knows Java". Then the Verification section says "Documentation only", so readers know the sensor was not forgotten.

Conclusion #

To sum up:

  1. Specs define the what, in business language, so domain experts can review them and they survive technology changes.
  2. Guidelines , including the general architecture and the ADRs, define the how, once for all use cases.
  3. Sensors check that the code follows the guidelines and give the AI agent fast feedback.

The JPA example needs one ADR, one Enforcer rule, and one ArchUnit test, linked by the ADR id. Start with your most important decision and add sensors step by step.

── more in #ai-agents 4 stories · sorted by recency
── more on @neal ford 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/specs-guidelines-and…] indexed:0 read:6min 2026-11-13 · —