Software Design Specification - Developer Tooling
Proposed
The Bounded Context Scaffolder is a developer tooling service that generates complete, spec-compliant project structures for new DDD bounded contexts. It creates all required files with proper templating and registers the context in Nx, enabling developers to immediately run the full delivery pipeline.
Manually creating bounded context structures is:
A single command that scaffolds everything with correct conventions:
1
python tools/sea_new_context.py inventory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
specs/inventory/
├── inventory.adr.md # Architectural Decision Record stub
├── inventory.prd.md # Product Requirements Document stub
├── inventory.sds.yaml # Software Design Specification (YAML)
└── inventory.sea # SEA-DSL file with starter flows
tools/nx/specs-inventory/
└── project.json # Nx project with full pipeline targets
libs/inventory/
├── domain/src/gen/ # Empty generated domain directory
├── application/src/gen/ # Empty generated application directory
├── ports/src/gen/ # Empty generated ports directory
└── adapters/src/gen/ # Empty generated adapters directory
| File | Purpose |
|---|---|
specs/<ctx>/<ctx>.adr.md |
ADR stub with ID placeholder and constraints section |
specs/<ctx>/<ctx>.prd.md |
PRD stub with EARS format and REQ-ID template |
specs/<ctx>/<ctx>.sds.yaml |
Full SDS YAML with all sections pre-filled |
specs/<ctx>/<ctx>.sea |
SEA-DSL with example Entity/Resource/Flow/Policy |
tools/nx/specs-<ctx>/project.json |
Nx project with all pipeline targets |
<ctx>.adr.md)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
# ADR-XXX: <Context> Context Architecture
## Status
**Draft**
## Context
[Describe the domain problem this context addresses]
## Decision
This bounded context follows DDD + Hexagonal Architecture with CQRS.
## Constraints
- MUST use SEA-DSL for domain modeling
- MUST use Nx for project structure
- MUST generate all runtime code from manifests
- MUST pin SEA™ CLI version in CI
## Consequences
[Describe complexity tradeoffs]
## Related
- ADR-012: Delivery Pipeline
<ctx>.prd.md)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# PRD-XXX: <Context> Requirements
## Satisfies
- ADR-XXX: <Context> Context Architecture
## Requirements
### REQ-001: [Requirement Title]
**Type:** functional
**EARS:** When [trigger], the system shall [action].
**Acceptance:** Given/When/Then criteria
### REQ-002: [Requirement Title]
**Type:** nonfunctional
**EARS:** The system shall [quality attribute].
**Acceptance:** Measurable criteria
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
sds:
id: SDS-XXX
title: <Context> Context SDS
bounded_context: <context>
satisfies_prds: [PRD-XXX]
satisfies_adrs: [ADR-XXX]
version: 0.1.0
status: draft
glossary:
- term: Example
type: entity
description: Example entity description
types:
value_objects:
- name: ExampleId
underlying: uuid
enums:
- name: ExampleStatus
values: [PENDING, ACTIVE, COMPLETED]
domain:
aggregates:
- name: Example
root: true
identity: ExampleId
fields:
id: ExampleId
status: ExampleStatus
invariants: []
policies: []
cqrs:
commands: []
queries: []
events: []
ports: []
runtime:
api:
framework: fastapi
persistence:
kind: postgres
orm: sqlalchemy
migrations: alembic
messaging:
kind: kafka
outbox:
enabled: true
table: outbox_events
di:
bindings: []
// Bounded Context: <context>
// Generated by: sea_new_context.py
Entity "Example" v1.0.0
in <context>
Resource "ExampleId" units in <context>
Resource "CreateExample" units in <context>
Flow "CreateExample"
@cqrs { "kind": "command" }
@tx { "transactional": true }
from "User" to "Example"
Policy "ExampleMustExist" v1.0.0
as: Example != null
in <context>
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
{
"name": "specs-<context>",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"targets": {
"sea:ast": {
"executor": "nx:run-commands",
"options": {
"cwd": ".",
"command": "sea parse --format json specs/<context>/<context>.sea > specs/<context>/<context>.ast.json"
}
},
"sea:lint": {
"executor": "nx:run-commands",
"dependsOn": ["sea:ast"],
"options": {
"cwd": ".",
"command": "python tools/flow_lint.py specs/<context>/<context>.ast.json --config tools/flow_lint.config.json"
}
},
"sea:ir": {
"executor": "nx:run-commands",
"dependsOn": ["sea:lint"],
"options": {
"cwd": ".",
"command": "python tools/ast_to_ir.py specs/<context>/<context>.ast.json specs/<context>/<context>.ir.json"
}
},
"sea:manifest": {
"executor": "nx:run-commands",
"dependsOn": ["sea:ir"],
"options": {
"cwd": ".",
"command": "python tools/ir_to_manifest.py specs/<context>/<context>.ir.json specs/<context>/<context>.manifest.json"
}
},
"codegen": {
"executor": "nx:run-commands",
"dependsOn": ["sea:manifest"],
"options": {
"cwd": ".",
"command": "python tools/codegen/gen.py specs/<context>/<context>.manifest.json"
}
},
"determinism": {
"executor": "nx:run-commands",
"dependsOn": ["codegen"],
"options": {
"cwd": ".",
"command": "python tools/regen_check.py specs/<context>/<context>.manifest.json"
}
},
"all": {
"executor": "nx:run-commands",
"dependsOn": ["determinism"],
"options": {
"cwd": ".",
"command": "echo 'specs-<context>: all stages complete'"
}
}
}
}
1
python tools/sea_new_context.py <context-name>
| Flag | Description |
|---|---|
--dry-run |
Show what would be created without writing files |
--skip-nx |
Skip Nx project registration |
--adr-id ADR-NNN |
Pre-fill ADR ID |
--prd-id PRD-NNN |
Pre-fill PRD ID |
--sds-id SDS-NNN |
Pre-fill SDS ID |
1
python tools/sea_new_context.py inventory --adr-id ADR-025 --prd-id PRD-012 --sds-id REF-012
| Thing | Convention |
|---|---|
| Context folder | specs/<context>/ |
| SEA™ file | <context>.sea |
| Nx project | specs-<context> |
| Namespace | <context> (must match metadata.namespace in SEA™) |
| Generated libs | libs/<context>/{domain,application,ports,adapters} |
The scaffolder validates context names:
shared, platform)The scaffolder automatically updates nx.json:
1
2
3
4
5
{
"projects": {
"specs-inventory": "tools/nx/specs-inventory"
}
}
After running the scaffolder:
1
nx run specs-inventory:all
The scaffolder integrates with VS Code tasks:
1
2
3
4
5
6
7
{
"label": "SEA™: New Context Scaffold",
"type": "shell",
"command": "python tools/sea_new_context.py ${input:ctx}",
"problemMatcher": [],
"group": "build"
}
1
2
3
4
5
6
{
"id": "ctx",
"type": "promptString",
"description": "Bounded context name (e.g., orders, inventory, billing)",
"default": ""
}
| Metric | Target |
|---|---|
| All files created | 100% |
| Nx project registered | ✅ |
nx run specs-<context>:all succeeds |
✅ |
| No manual file creation required | ✅ |
| Error | Response |
|---|---|
| Context already exists | Fail with “Context ‘ |
| Invalid context name | Fail with naming rules explanation |
| Cannot write files | Fail with filesystem error details |
| Nx.json not writable | Warn and skip registration |
The Bounded Context Scaffolder eliminates manual project setup by generating spec-compliant structures. Combined with the delivery pipeline, it enables a true “bounded context in 5 minutes” developer experience.