Skip to main content

Spec-driven Development

In the era of Artificial Intelligence-assisted software engineering, raw code generation speed is no longer the primary bottleneck. Today, tools like GitHub Copilot, Cursor, Claude Code, and Antigravity can generate hundreds of lines of code in seconds. However, this velocity introduces a critical risk: uncontrolled coding (vibe coding), where language models hallucinate deprecated libraries, violate layered architectures, and accumulate massive technical debt.

To address this challenge, Spec-driven Development (SDD) emerged: an engineering discipline that shifts focus from "generating code quickly" to "defining with architectural rigor exactly what must be built before writing a single line of code".

In this chapter, we explore the contrast between traditional SDLC and SDD, how the 6 foundational phases of GitHub Spec Kit formalize this workflow, and how to apply the handcrafted, universal methodology using an AGENTS.md file and an .agents/ folder structure in Spring Boot projects.


1. Traditional SDLC vs. Spec-driven Development​

In the traditional Software Development Life Cycle (SDLC), documentation is frequently treated as a bureaucratic afterthought that drifts out of sync the moment code is modified. In SDD, the Markdown specification is the executable driver that strictly guides code generation.

Explore the parallel comparison between the 6 foundational phases of SDD and the pitfalls of the traditional development process:

From CLI Tool to Universal Standard​

GitHub Spec Kit initially formalized this workflow through a command-line tool (specify-cli), installable via uv:

Installing and running official GitHub Spec Kit
# 1. Install uv (Rust-based Python package manager)
curl -LsSf https://astral.sh/uv/install.sh | sh

# 2. Install specify-cli
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git

# 3. Initialize a repository
specify init my-backend-project

However, relying on external command-line binaries introduces tooling friction and black-box behaviors across diverse development teams. Modern engineering teams adopt a handcrafted abstraction: structuring context directly within Git-versioned folders and Markdown documents.


2. Handcrafted SDD: Architecture with AGENTS.md and .agents/​

The handcrafted methodology places governance in a root constitution document (AGENTS.md) and a reserved context repository (.agents/).

Interact with the architecture diagram below to inspect how memory, specifications, technical plans, and tasks are organized, and how context travels to the AI agent:


3. Step-by-Step Hands-on Guide: Implementing a Feature with Handcrafted SDD​

Next, we will construct a formal specification from scratch for a new Spring Boot backend feature: User Action Audit Log (AuditLog).

1

Create Root Constitution: AGENTS.md

In your project root directory, create AGENTS.md. This is the first file any AI coding agent reads when initializing a session.

AGENTS.md
# Agent Operating Manual & Constitution

You are a Senior Software Engineer specializing in enterprise backend development with Spring Boot and Java 17.

## Non-Negotiable Golden Rules
1. **Strict Layered Architecture**: Controller -> Service -> Repository. Injecting repositories directly into controllers is strictly prohibited.
2. **Mandatory DTOs**: Never expose JPA entities (@Entity) on REST endpoints. All external communication uses immutable Records or DTO classes with Jakarta validation constraints.
3. **Centralized Exception Handling**: Never suppress errors with empty try-catch blocks. Throw domain exceptions and handle them globally inside @RestControllerAdvice.
4. **Atomic Execution Rule**: Do not implement entire features at once. Consult .agents/tasks/ and execute strictly one task per prompt iteration.

## Context Directory
* [Technical Memory](.agents/memory/tech-stack.md): Official framework and database versions.
* [Architecture Rules](.agents/memory/architecture.md): Naming conventions and layered design patterns.
2

Define Persistent Memory: .agents/memory/

Create .agents/memory/ and record framework constraints in tech-stack.md to prevent agents from hallucinating incompatible libraries:

.agents/memory/tech-stack.md
# Technical Stack Constraints

- **Language**: Java 17 (LTS) - use Records, Text Blocks, and Switch Expressions.
- **Framework**: Spring Boot 3.3.x.
- **Security**: Spring Security 6 with stateless JWT (custom JwtAuthenticationFilter).
- **Database**: PostgreSQL 16 with Spring Data JPA and Hibernate 6.
- **Validation**: Jakarta Validation (@NotNull, @NotBlank, @Positive, @Email).
- **API Documentation**: Springdoc OpenAPI v2 (Swagger UI at /swagger-ui.html).
3

Draft Functional Specification: .agents/specs/

In .agents/specs/feat-audit-spec.md, draft the what. Detail user stories, input/output JSON schemas, and acceptance criteria using Gherkin syntax:

.agents/specs/feat-audit-spec.md
# Specification: User Action Audit Logging (Audit Log)

## 1. User Story
**As a** system administrator,
**I want** critical events (login, course creation, role modifications) logged to a persistent audit trail,
**so that** I can monitor platform security and comply with audit standards.

## 2. Required Endpoints
- `POST /api/v1/audit-logs`: Internal endpoint for recording audit entries.
- `GET /api/v1/audit-logs`: Protected endpoint (ROLE_ADMIN) with pagination (page, size) and descending timestamp ordering.

## 3. Input JSON Schema
```json
{
"action": "COURSE_CREATED",
"userEmail": "profesor@icesi.edu.co",
"details": "Course ID 101 registered with 3 credits",
"ipAddress": "192.168.1.45"
}

4. Acceptance Criteria (Gherkin)​

  • Scenario 1: Successful audit log persistence

    • Given an authenticated user performs a critical action,
    • When the service issues a POST request to /api/v1/audit-logs with valid fields,
    • Then the system responds with HTTP 201 Created and persists the entry with a UTC timestamp.
  • Scenario 2: Validation on mandatory fields

    • Given a payload with an empty action or malformed userEmail,
    • When the request is submitted,
    • Then the system responds with HTTP 400 Bad Request and validation error messages.
</Step>

<Step number="4" title="Clarify Phase: Critical Dialogue with the Agent">
Before generating code, feed `.agents/specs/feat-audit-spec.md` to the agent with this instruction:

```text title="Clarification Prompt (Clarify)"
Review the specification in .agents/specs/feat-audit-spec.md according to AGENTS.md and .agents/memory/.
Ask 3 to 5 questions regarding edge cases, database indexes, or error scenarios that are not explicitly defined.
Do not generate code yet.
Examples of Ambiguities Uncovered in Clarify
  • If the audit database write fails, should it rollback the primary transaction or log asynchronously without blocking user requests?
  • Will filtering by date ranges or user email be required on /api/v1/audit-logs queries?

Clarifying these decisions in Markdown before coding saves hours of refactoring.

5

Design Technical Plan: .agents/plans/

Once the specification is clarified, formulate the technical how in .agents/plans/feat-audit-plan.md:

.agents/plans/feat-audit-plan.md
# Technical Plan: Audit Logging Module

## 1. Component Architecture
1. **JPA Entity**: `AuditLog.java` mapped to `audit_logs`, primary key `UUID`, indexed columns `created_at` and `user_email`.
2. **DTOs**: `CreateAuditLogRequest.java` (Record) and `AuditLogResponse.java` (Record).
3. **Repository**: `AuditLogRepository.java` extending `JpaRepository<AuditLog, UUID>`.
4. **Service**: `AuditLogService.java` interface and `AuditLogServiceImpl.java` using `@Transactional(propagation = Propagation.REQUIRES_NEW)`.
5. **Controller**: `AuditLogController.java` at `/api/v1/audit-logs` with `@PreAuthorize("hasRole('ADMIN')")` on GET queries.

## 2. Key Technical Decisions
- **Isolation**: Use `REQUIRES_NEW` propagation so audit entries remain saved even if downstream user actions throw exceptions.
- **Performance**: Create composite B-Tree index on `(user_email, created_at)` to optimize administrator queries.
6

Deconstruct Atomic Tasks: .agents/tasks/

Break the technical plan into numbered, verifiable tasks in .agents/tasks/feat-audit-tasks.md:

.agents/tasks/feat-audit-tasks.md
# Task Checklist: Audit Logging Feature

- [ ] **Task 1: Persistence Model**
- Create entity `AuditLog.java` with UUID, action, userEmail, details, ipAddress, createdAt.
- Create database migration script with index on `created_at`.
- *Verification Criteria*: Project compiles and table schema is verified in PostgreSQL.

- [ ] **Task 2: DTO Layer and Validation**
- Create `CreateAuditLogRequest` with `@NotBlank` and `@Email`.
- Create `AuditLogResponse` with formatted properties.
- *Verification Criteria*: Validation unit tests pass.

- [ ] **Task 3: Repository and Service Layer**
- Create `AuditLogRepository` with `findAllByOrderByCreatedAtDesc` pagination.
- Implement `AuditLogServiceImpl` with transaction propagation.
- *Verification Criteria*: Integration test persists record.

- [ ] **Task 4: REST Controller and Security**
- Create `AuditLogController` exposing POST and paginated GET.
- Secure GET with ADMIN role and document with OpenAPI `@Operation`.
- *Verification Criteria*: Postman tests pass (201 Created and 400 Bad Request).
7

Guided Execution with AI Agent

With the tasks defined, interact with the agent authorizing strictly one task at a time:

Controlled Execution Prompt
Read AGENTS.md, .agents/plans/feat-audit-plan.md, and Task 1 from .agents/tasks/feat-audit-tasks.md.
Implement ONLY Task 1 (AuditLog entity and repository).
Do not touch controllers or services yet.
When completed, show the code and stop execution.

Once the agent finishes, compile your code, verify tests pass, mark [x] on Task 1, and authorize Task 2.


4. Best Practices for Agent-Assisted Development​

To maximize productivity and software quality when applying SDD:

  1. The Single-Task Rule: Never prompt an agent to build multiple components or architectural layers simultaneously without validation.
  2. Truth Lives in Markdown, Not in the Chat: Every architectural decision made during conversational turns must be committed to .agents/specs/ or .agents/plans/. Chats are volatile; repository Markdown files are versioned in Git and readable by any team member or agent.
  3. Cross-Validation with Postman: Every controller implemented via SDD should be verified immediately against the automated Postman test collection configured in the previous chapter.

Self-Assessment Quiz​

Cargando cuestionario...