Skip to main content

Spec-driven development

All Aucert engineering work follows a spec-driven workflow. Every task — whether executed by a human or an AI agent — starts with a specification. The formality scales with task size.

Why spec-first?

Specifications serve three purposes in an agent-driven workflow:

  1. Alignment — Human and agent agree on what "done" looks like before work begins
  2. Context loading — Specs declare which context files the executor needs, reducing wasted tokens
  3. Audit trail — Every task has a written record: what was requested, what was approved, what was delivered

Task sizes

SizeTimePlanning approachExample
Small< 1hPlan in conversation (Plan mode), get approval, executeFix a typo, add a flag
Medium1–4hIntent in .tasks/backlog/ → agent generates spec in .tasks/drafts/ → approve → executeAdd endpoint, write docs page
LargeMulti-dayDetailed backlog file → comprehensive spec → both founders review → executeNew pipeline layer, infra migration

Task file lifecycle

DirectoryPurposeWho writes
.tasks/backlog/Raw intent files awaiting spec generationHuman
.tasks/drafts/Generated specs awaiting reviewAI agent
.tasks/active/Approved specs ready for executionHuman (moves from drafts)
.tasks/archive/Completed tasksAutomated (on merge)

Context loading in specs

Task files declare which context to load, following the cascading context model:

context_load:
l1: [ARCHITECTURE.md, CONVENTIONS.md] # Always loaded
l2: [backend/.context/BACKEND.md] # Platform-specific
l3: [backend/.../domain/generation/spec/GENERATION.md] # Module-specific

This prevents agents from loading irrelevant context (a frontend task doesn't need CLOUD.md), which reduces token usage and improves output quality.

Spec file format

# Task: {title}

## Context
- Module: `backend/platform/src/.../domain/{module}/`
- Spec: `{module}/spec/{MODULE}.md`
- Related proto: `proto/{file}.proto`

## Requirements
1. Specific deliverable
2. Another deliverable

## Acceptance criteria
- [ ] Criterion 1
- [ ] Criterion 2

## Scope boundaries
- NOT in scope: {explicit exclusions}

## Context loading
context_load:
l1: [ARCHITECTURE.md]
l2: [backend/.context/BACKEND.md]

What's next