Chapter 4: The Artifact Triad: Structuring `.spec.md` , `.plan.md` , and `.tasks.md`
By Muhammad Riaz
The Separation of Concerns in AI Engineering
In classical software design, the principle of Separation of Concerns dictates that a system should be divided into distinct sections, where each section addresses a separate, specific aspect of functionality. You would never mix database queries, routing logic, and frontend DOM manipulation inside a single file; doing so creates brittle, unmaintainable code.
Yet, when interacting with AI coding models, developers commit this exact error every day.
When you type a single prompt asking an AI assistant to "Design, plan, and write code for an authentication system," you force the model to perform three distinct cognitive tasks simultaneously:
-
Product Requirements: Figuring out what needs to be built and what business rules apply.
-
System Architecture: Deciding how files, schemas, and dependencies should be structured.
-
Line-by-Line Execution: Writing the syntax, handling errors, and creating tests.
Confronted with all three tasks at once, the LLM inevitably takes shortcuts. It skips subtle architectural considerations, forgets business constraints mid-generation, and produces code that requires extensive refactoring.
To achieve deterministic, production-grade output from AI agents, we must enforce a strict Separation of Concerns before a single line of code is written. We do this through The Artifact Triad.
The Artifact Triad Architecture
The Artifact Triad is the core structural framework of Spec-Driven Development. It divides every feature or system build into three distinct, version-controlled markdown documents:
.specs/001-payment-gateway/
βββ 01-spec.md <-- WHAT & WHY (Intent, Boundaries, Contracts)
βββ 02-plan.md <-- HOW (Architecture, File Impact Map, Schemas)
βββ 03-tasks.md <-- EXECUTION (Atomic, Step-by-Step Implementation Checklist)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β THE ARTIFACT TRIAD β
β β
β [ 01-spec.md ] ββ> Defines Intent & Business Rules (No Tech Specs) β
β β β
β βΌ β
β [ 02-plan.md ] ββ> Translates Spec into Tech Architecture & File Impacts β
β β β
β βΌ β
β [ 03-tasks.md ] ββ> Converts Architecture into Single-Responsibility Steps β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Each artifact serves a specific purpose, targets a clear audience, and answers one foundational question.
Artifact 1: The Specification Document ( 01-spec.md )
Purpose
The Specification file answers the question: WHAT are we building, WHY are we building it, and WHAT are the hard boundaries?
It is entirely technology-agnostic. It does not dictate variable names, framework choices, or database column types. Instead, it captures business logic, user journeys, system invariants, and explicit exclusions.
Core Structure
A production-grade 01-spec.md contains five mandatory sections:
# Spec: [Feature Name]
## 1. User Story & Core Objective
- **As a** [user role],
- **I want to** [perform action],
- **So that** [achieve business outcome].
## 2. Functional Requirements
- Requirement 1: [Unambiguous requirement]
- Requirement 2: [Unambiguous requirement]
## 3. System Invariants & Business Rules
- Rule 1: [Condition that MUST ALWAYS hold true]
- Rule 2: [Condition that MUST NEVER occur]
## 4. Explicit Scope Exclusions (What NOT to Build)
- Exclusion 1: [Feature or behavior explicitly forbidden in this iteration]
- Exclusion 2: [Unneeded abstraction layer to avoid]
## 5. Acceptance Criteria
- [ ] Criterion 1 (Verifiable via test or manual inspection)
- [ ] Criterion 2
Real-World Practical Example
Imagine you are building a rate-limiting feature for an API gateway.
# Spec: User Rate Limiting
## 1. User Story & Core Objective
- **As an** API Administrator,
- **I want to** limit the frequency of incoming user requests,
- **So that** our downstream microservices remain protected against denial-of-service spikes.
## 2. Functional Requirements
- Authenticated tier: Maximum 100 requests per minute per User ID.
- Unauthenticated tier: Maximum 10 requests per minute per client IP address.
- When a client exceeds their limit, the API must respond with HTTP Status `429 Too Many Requests`.
## 3. System Invariants & Business Rules
- Rate limits MUST be calculated across distributed server nodes; local in-memory counters are forbidden.
- Internal health check routes (`/healthz`, `/metrics`) MUST NEVER be throttled under any circumstance.
## 4. Explicit Scope Exclusions
- DO NOT implement dynamic rate-limit tier purchasing or UI admin dashboards in this spec.
- DO NOT modify existing JWT validation logic.
## 5. Acceptance Criteria
- [ ] Exceeding 100 requests within 60 seconds returns HTTP 429 with `Retry-After` header set.
- [ ] Health check endpoint succeeds even when client address is actively throttled.
Artifact 2: The Architecture Plan ( 02-plan.md )
Purpose
The Plan file answers the question: HOW will the existing codebase be modified to safely fulfill the specification?
Written after the specification is approved, the plan bridges product requirements and physical code changes. Its primary component is the File Impact Map βa strict boundary mechanism that tells AI agents exactly which files they are permitted to create, modify, or inspect.
Core Structure
# Architecture Plan: [Feature Name]
## 1. Technical Strategy
High-level description of frameworks, design patterns, and internal utilities to be used.
## 2. File Impact Map
### Files to Create:
- `path/to/new_file.ts` (Purpose)
### Files to Modify:
- `path/to/existing_file.ts` (Specific lines or functions to update)
### Read-Only Context Files (For AI Reference):
- `path/to/schema.ts` (To read existing types)
## 3. Data Models & Interface Contracts
Exact TypeScript interfaces, database schemas, or API payload definitions.
## 4. Security & Risk Analysis
Potential edge cases, performance bottlenecks, or security considerations.
Real-World Practical Example (Continuing Rate Limiting)
# Architecture Plan: User Rate Limiting
## 1. Technical Strategy
Implement a sliding-window rate-limiter middleware leveraging our existing Redis cluster connection via `ioredis`.
## 2. File Impact Map
### Files to Create:
- `src/middleware/rateLimiter.ts` (Core middleware logic)
- `tests/unit/rateLimiter.test.ts` (Unit test coverage)
### Files to Modify:
- `src/app.ts` (Attach middleware to main Express routing stack)
### Read-Only Context Files:
- `src/config/redis.ts` (To reuse existing Redis client instance)
- `src/middleware/auth.ts` (To read attached `req.user.id` property)
## 3. Interface Contract
```typescript
export interface RateLimitConfig {
windowMs: number;
maxRequests: number;
keyPrefix: string;
}
---
### Artifact 3: The Execution Breakdown (`03-tasks.md`)
#### Purpose
The Tasks file answers the question: **IN WHAT EXACT ORDER will the changes be implemented and verified?**
AI agents struggle when given huge, multi-faceted execution plans. The `03-tasks.md` file breaks the plan down into **atomic, single-responsibility steps**. Each task represents a unit of work small enough for an AI agent to execute and verify without running out of context tokens or introducing subtle bugs.
#### Core Structure
```markdown
# Task Execution List: [Feature Name]
## Phase 1: Environment & Contract Setup
- [ ] Task 1.1: Define TypeScript interfaces in `src/types/rateLimit.ts`.
- [ ] Task 1.2: Write failing unit test skeleton for rate-limiter logic in `tests/unit/rateLimiter.test.ts`.
## Phase 2: Core Implementation
- [ ] Task 2.1: Implement Redis sliding-window logic inside `src/middleware/rateLimiter.ts`.
- [ ] Task 2.2: Implement response header formatting (`X-RateLimit-Limit`, `Retry-After`).
## Phase 3: System Integration & Review Gate
- [ ] Task 3.1: Mount middleware in `src/app.ts` ensuring health check routes precede rate-limiting middleware.
- [ ] Task 3.2: **[HUMAN CHECKPOINT]** Run full test suite (`npm test`) and inspect Redis key expiration metrics.
The Workflow: How the Triad Eliminates AI Drift
When an AI agent is executed using the Artifact Triad, the prompt pattern changes completely:
-
Phase 1 (Spec Review): You ask the AI to read
01-spec.mdand critique it for missing edge cases or logical gaps. -
Phase 2 (Plan Generation): You instruct the AI to read
01-spec.mdand draft02-plan.md. You review the File Impact Map to ensure the AI isn't touching unnecessary files. -
Phase 3 (Task Execution): You feed the AI
02-plan.mdand03-tasks.md, instructing it: "Execute Task 1.1 in03-tasks.md. Modify
ONLY the files listed in the File Impact Map for Task 1.1. Do not proceed to Task 1.2 until Task 1.1 passes its tests."
NO AGENT DRIFT MINIMAL CONTEXT ROT
βββββββββββββββββββββββββ ββββββββββββββββββββββββββββββ
AI is locked into specific AI works on single atomic
files via File Impact Map tasks rather than big-bang
monolithic feature prompts
By decoupling Intent (spec.md), Architecture (plan.md), and Execution (tasks.md), you transform the AI from an unpredictable generator into an execution pipeline with total traceability.
Practical Exercises: Creating Your First Triad
-
Set Up the Directory Structure: In your current repository, create a directory called
.specs/001-test-feature/. -
Draft a
01-spec.mdFile: Pick a small feature you plan to build this week. Write its user story, explicit scope exclusions, and business rules without writing any code or referencing file paths. -
Generate the File Impact Map (
02-plan.md): Open your AI coding assistant and prompt:
"Read
.specs/001-test-feature/01-spec.mdand inspect our codebase repository. Generate a02-plan.mdfile listing ONLY the files that need to be created or modified to satisfy this spec. Do not write any implementation code yet."
- Evaluate the Output: Notice how forcing the AI to output a File Impact Map before writing code immediately surfaces misunderstandings about your codebase structure.
Module 1 Summary & Looking Ahead
Congratulations! You have completed Module 1: The Foundations of SDD & Eliminating "Ambiguity Tax".
Across these first four chapters, you have learned:
-
Why conversational prompting collapses under the weight of real-world scale (Chapter 1).
-
How to calculate and prevent the financial cost of the Ambiguity Tax (Chapter 2).
-
How to move up the SDD Maturity Spectrum from disposable scratchpads to executable pipelines (Chapter 3).
-
How to structure the foundational backbone of SDD using The Artifact Triad (Chapter 4).
In Module 2, we will focus on authoring deep, machine-readable specifications: learning how to write structured markdown contracts, define airtight scope boundaries, and use interactive AI loops to critique your specs before writing code.
How would you like to proceed?
We can now begin Module 2: Authoring Machine-Readable Specifications with Chapter 5: The Anatomy of a Production-Grade .spec.md. Let me know when you are ready!