Ref-002: Machine-Readable SDS Format (YAML)

Document Type

Reference / Schema Specification

Purpose

Defines the structured YAML format for Software Design Specifications (SDS) that enables deterministic translation to SEA-DSL while maintaining human readability. This format eliminates prose ambiguity and enables agents to author specifications that can be mechanically compiled into semantic models.


Design Principles

  1. Machine-extractable — Every design element has a fixed location in the YAML structure
  2. Human-readable — YAML is easier to read than JSON for documentation purposes
  3. Schema-gated — Validated via sds.schema.json before any downstream processing
  4. Traceable — Every element references requirement IDs from the PRD

SDS YAML Template

File Location

1
specs/<context>/<context>.sds.yaml

Complete Template

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
sds:
  id: SDS-001
  title: Orders Context SDS
  bounded_context: orders
  satisfies_prds: [PRD-010]
  satisfies_adrs: [ADR-001]
  version: 1.0.0
  status: draft # draft|review|approved
  owners: ["team@example.com"]
  created: 2025-12-23

glossary:
  - term: Order
    type: entity
    description: Customer purchase request tracked through fulfillment.
  - term: PlaceOrder
    type: command
    description: Request to create an order.
  - term: OrderPlaced
    type: event
    description: Emitted when an order is successfully placed.

types:
  value_objects:
    - name: OrderId
      underlying: uuid
    - name: Money
      fields:
        amount: decimal
        currency: string # ISO-4217
  enums:
    - name: OrderStatus
      values: [PENDING, CONFIRMED, CANCELLED]

domain:
  aggregates:
    - name: Order
      root: true
      identity: OrderId
      fields:
        id: OrderId
        status: OrderStatus
        total: Money
        customer_id: uuid
      invariants: [POL-001]

policies:
  - id: POL-001
    name: TotalMustBePositive
    applies_to: Order
    satisfies_reqs: [REQ-001]
    rule:
      op: ">"
      left: { ref: "Order.total.amount" }
      right: { const: 0 }
    error:
      code: ORDER_TOTAL_INVALID
      message: "Order total must be > 0"

cqrs:
  commands:
    - id: CMD-001
      name: PlaceOrder
      satisfies_reqs: [REQ-001]
      input:
        customer_id: uuid
        total: Money
      transactional: true
      idempotency:
        enabled: true
        key: header:X-Idempotency-Key
      touches:
        aggregates: [Order]
      preconditions: [POL-001]
      emits: [EVT-001]

  queries:
    - id: QRY-001
      name: GetOrder
      satisfies_reqs: [REQ-002]
      input:
        order_id: OrderId
      output:
        order_id: OrderId
        status: OrderStatus
        total: Money
      consistency: strong # strong|eventual
      read_model:
        source: primary_db # primary_db|read_replica|projection
        table: orders

events:
  - id: EVT-001
    name: OrderPlaced
    satisfies_reqs: [REQ-001]
    payload:
      order_id: OrderId
      customer_id: uuid
      total: Money
    publish:
      topic: orders.order_placed.v1
      delivery: at_least_once # at_least_once|exactly_once
      outbox: required # required|optional

ports:
  - id: PORT-001
    name: OrderRepository
    direction: outbound
    used_by: [CMD-001, CMD-002]
    methods:
      - name: get
        args: [order_id: OrderId]
        returns: Order
      - name: save
        args: [order: Order]
        returns: void

  - id: PORT-002
    name: UnitOfWork
    direction: outbound
    used_by: [CMD-001, CMD-002]
    semantics:
      transaction_per_handler: true

  - id: PORT-003
    name: MessageBus
    direction: outbound
    used_by: [EVT-001, EVT-002]
    methods:
      - name: publish
        args: [event: Event]
        returns: void

runtime:
  api:
    framework: fastapi
  persistence:
    kind: postgres
    orm: sqlalchemy
    migrations: alembic
  messaging:
    kind: kafka # kafka|nats|inmemory
    outbox:
      enabled: true
      table: outbox_events

di:
  bindings:
    - port: OrderRepository
      adapter: SqlAlchemyOrderRepository
      lifetime: request
    - port: UnitOfWork
      adapter: SqlAlchemyUnitOfWork
      lifetime: request
    - port: MessageBus
      adapter: KafkaMessageBus
      lifetime: singleton

Section Reference

sds (Metadata)

Field Type Required Description
id string Unique SDS identifier (pattern: ^SDS-\d{3,}$)
title string Human-readable title
bounded_context string DDD bounded context name
satisfies_prds array PRD IDs this SDS implements
satisfies_adrs array ADR IDs this SDS follows
version string SDS version (semver)
status enum draft, review, approved

glossary

Prevents naming drift (a common source of agent hallucination):

Field Type Required Description
term string Domain term
type enum entity, vo, command, query, event, service
description string Definition

types

Section Description
value_objects Immutable objects with underlying type or fields
enums Enumeration types with allowed values

domain

Field Type Description
aggregates[].name string Aggregate root name
aggregates[].root boolean Is aggregate root?
aggregates[].identity string Identity type
aggregates[].fields object Field name → type mappings
aggregates[].invariants array Policy IDs enforced on this aggregate

policies

Field Type Description
id string Policy ID (pattern: ^POL-\d{3,}$)
name string Policy name
applies_to string Target entity/aggregate
satisfies_reqs array REQ-IDs from PRD
rule object Expression tree (structured, not prose)
error.code string Error code for violations
error.message string Human-readable error message

cqrs.commands

Field Type Description
id string Command ID (pattern: ^CMD-\d{3,}$)
name string Command name
satisfies_reqs array REQ-IDs
input object Input field → type mappings
transactional boolean Requires transaction?
idempotency.enabled boolean Idempotency support
idempotency.key string Idempotency key source
touches.aggregates array Aggregates modified
preconditions array Policy IDs checked before execution
emits array Event IDs published on success

cqrs.queries

Field Type Description
id string Query ID (pattern: ^QRY-\d{3,}$)
name string Query name
input object Input field → type mappings
output object Output field → type mappings
consistency enum strong or eventual
read_model.source enum primary_db, read_replica, projection
read_model.table string Table/view name

events

Field Type Description
id string Event ID (pattern: ^EVT-\d{3,}$)
name string Event name
payload object Payload field → type mappings
publish.topic string Topic/stream name
publish.delivery enum at_least_once, exactly_once
publish.outbox enum required or optional

ports

Field Type Description
id string Port ID (pattern: ^PORT-\d{3,}$)
name string Port interface name
direction enum inbound or outbound
used_by array CMD/QRY/EVT IDs using this port
methods array Method signatures
semantics object Additional semantics (e.g., transaction behavior)

runtime

Implementation/technology selections:

Section Purpose
api.framework API framework (fastapi, express, etc.)
persistence.kind Database type
persistence.orm ORM/query builder
messaging.kind Message broker
messaging.outbox Outbox configuration

di (Dependency Injection)

Field Type Description
bindings[].port string Port name
bindings[].adapter string Concrete adapter class
bindings[].lifetime enum singleton, request, transient

SDS → SEA-DSL Translation Rules

The agent generates SEA-DSL strictly from SDS blocks:

SDS Section SEA-DSL Construct
domain.aggregates Entity declaration
types.value_objects Resource declaration
policies Policy with expression tree
cqrs.commands Resource (payload) + Flow with @cqrs { "kind": "command" }
cqrs.queries Resource (payload) + Flow with @cqrs { "kind": "query" }
events Resource (payload) + Flow with @cqrs { "kind": "event" }

Validation Pipeline

1
2
3
4
SDS YAML
    ↓ YAML → JSON conversion
    ↓ JSON Schema validation (sds.schema.json)
    ↓ [PASS/FAIL]

Command

1
python tools/validate_sds.py specs/orders/orders.sds.yaml tools/schemas/sds.schema.json

Why YAML (Not JSON or TOML)

Format Readability Nesting Comments Verdict
YAML ✅ Excellent ✅ Native ✅ Supported Best for SDS
JSON ❌ Verbose ✅ Native ❌ No comments Best for manifest
TOML ✅ Good ❌ Awkward ✅ Supported Best for flat config