Spec-Driven Development (SDD) SOP

The complete workflow for implementing features in SEA™ using the spec-first pipeline.

This SOP covers Phases 7–9 of the ENGINEERING.SOP:


Prerequisites

Before starting, ensure:

1
2
3
just doctor     # Environment OK
just setup      # Dependencies installed
nx show projects   # Workspace visible

See: Skills — Skill 0


Step 1: Create a TDD Cycle Branch

Every feature begins with a TDD cycle. Use the unified branching workflow.

1
2
# Start a new cycle: phase, cycle-number, agent-id, slug
just cycle-start 1 1 A happy-path-order

This command:

  1. Creates branch cycle/p1-c1A-happy-path-order from dev
  2. Creates a GitHub Issue with labels tdd, phase, cycle, agent
  3. Pushes and tracks the branch

CI Trigger: branch-rules.yml validates branch naming on PR open.

See: Branching Reference


Step 2: Author Specifications (ADR → PRD → SDS)

Specs live in docs/specs/<bounded-context>/.

2.1 ADR (Architecture Decision Record)

1
2
# Create or edit
vim docs/specs/orders/orders.adr.md
Section What to Write
Context Problem domain, why a decision is needed
Decision DDD + CQRS + hexagonal (or chosen approach)
Constraints MUST/MUST NOT rules for generators
Consequences Trade-offs, complexity added

2.2 PRD (Product Requirements)

1
vim docs/specs/orders/orders.prd.md

2.3 SDS (Software Design Spec)

1
vim docs/specs/orders/orders.sds.yaml

Machine-readable YAML with:

Validate:

1
python tools/validate_sds.py docs/specs/orders/orders.sds.yaml

CI Gate: ci.yml runs SDS validation on specs changes.

See: Spec Pipeline — Sections 1-3


Step 3: Translate to SEA-DSL

Create the SEA™ model that expresses the SDS:

1
vim docs/specs/orders/orders.sea

Translation Rules

SDS Concept SEA-DSL Construct
Entity Entity "Order"
Value Object Resource "Money"
Command Flow + @cqrs { "kind": "command" }
Query Flow + @cqrs { "kind": "query" }
Event Flow + @cqrs { "kind": "event" }
Invariant Policy "name" as: expression

Required Flow Annotations

Every Flow must have @cqrs:

Flow "PlaceOrder"
  @cqrs { "kind": "command" }
  @tx { "transactional": true }
  @idempotency { "enabled": true, "key": "header:X-Idempotency-Key" }
  from "Customer" to "Order"

Validate:

1
2
sea validate docs/specs/orders/orders.sea
just flow-lint

See: Flow Annotations, Skills 2-4


Step 4: Run the Compilation Pipeline

Generate code from specs through the deterministic pipeline:

1
2
# Full pipeline via Nx
nx run specs-orders:all

Or run steps individually:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. Parse SEA™ to AST
sea parse --format json docs/specs/orders/orders.sea > orders.ast.json

# 2. AST → IR
python tools/ast_to_ir.py orders.ast.json orders.ir.json

# 3. IR → Manifest
python tools/ir_to_manifest.py orders.ir.json orders.manifest.json

# 4. Manifest → Code
python tools/codegen/gen.py orders.manifest.json

# 5. Determinism gate
python tools/regen_check.py orders.manifest.json

CI Gate: ci.yml runs regen-check on every PR.

See: Spec Pipeline — Section 5, Nx Targets


Step 5: Phase 7 — Generate Scaffolding

With the manifest, scaffold the bounded context structure.

Generated Output Locations

Layer Path
Domain libs/orders/domain/src/gen/
Application libs/orders/application/src/gen/
Ports libs/orders/ports/src/gen/
Adapters libs/orders/adapters/src/gen/
API apps/api/src/gen/

Adding a New Bounded Context

1
python tools/sea_new_context.py orders

This creates:

Rule: Never manually create scaffolding. Use generators.

See: Skills — Skill 1


Step 6: Phase 8 — Build Testing Harness

Tests are generated alongside code. Verify at each layer.

Test Pyramid

Layer Test Type Command
Domain Unit tests nx test orders-domain
Application Use-case tests nx test orders-application
Adapters Integration tests nx test orders-adapters
E2E Minimal smoke tests nx e2e api-e2e

Run All Tests

1
2
just test                    # Baseline suite
nx run-many -t test          # All libs/apps

CI Gate: ci.yml runs tests on every push.

Troubleshooting Test Failures

Symptom Fix
Flow lint fails Add missing @cqrs annotation
AST schema fails DSL syntax error
IR schema fails Check ast_to_ir.py mapping
Manifest schema fails Check ir_to_manifest.py
Regen fails Generator has nondeterminism

See: Skills — Troubleshooting


Step 7: Phase 9 — Implement Vertical Slice

Each slice follows the Required Order (do not skip):

7.1 Domain Model + Invariants

Edit SEA™ to define:

Entity "Order"
Policy "TotalMustBePositive" as: Order.total.amount > 0

7.2 Use Case / Application Logic

Define commands and queries with handlers:

Flow "PlaceOrder"
  @cqrs { "kind": "command" }
  @tx { "transactional": true }
  from "Customer" to "Order"

7.3 Ports (Interfaces)

Generated from flows:

7.4 Adapters (Implementations)

Generated based on runtime choices in SDS:

7.5 Wiring (API/DI)

Generated in apps/api/src/gen/app.py:

7.6 Observability Hooks

Defined in ADR constraints, generated as:

7.7 Feature Flags (Optional)

If rollout risk exists, add feature flags via manifest config.


Step 8: Commit and Push

After passing all local checks:

1
2
3
4
5
6
7
8
# Stage changes
git add docs/specs/ libs/ apps/

# Commit with conventional message
git commit -m "feat(orders): implement PlaceOrder command"

# Push
git push

CI Pipeline:

  1. ci.yml — tests, lint, regen-check
  2. pr-cycle-assist.yml — adds labels, wave warnings
  3. branch-rules.yml — validates PR target

Step 9: Create PR and Merge

1
2
# Open PR to dev
gh pr create --base dev --title "feat(orders): PlaceOrder"

PR Checklist

After approval, merge to dev.


Promotion Flow

1
2
3
4
5
6
7
8
# Promote dev to stage
just promote-stage

# Promote stage to main (release)
just promote-main

# Create release tag
just release v1.2.0

See: Branching SOP


Quick Reference

Task Command
Start cycle just cycle-start <phase> <cycle> <agent> <slug>
Validate SDS python tools/validate_sds.py <sds.yaml>
Validate SEA™ sea validate <file.sea>
Full codegen nx run specs-<ctx>:all
Regen check python tools/regen_check.py <manifest.json>
Run tests nx run-many -t test
Promote just promote-stage / just promote-main