SDS-002: Bounded Context Scaffolder Service

Type

Software Design Specification - Developer Tooling

Status

Proposed

Implements


1. System Overview

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.


2. Purpose

Problem Statement

Manually creating bounded context structures is:

Solution

A single command that scaffolds everything with correct conventions:

1
python tools/sea_new_context.py inventory

3. What Gets Created

Directory Structure

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

Files Created

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

4. Template Content

ADR Template (<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

PRD Template (<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

SDS YAML 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
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: []

SEA-DSL Template

// 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>

Nx Project 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
{
  "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'"
      }
    }
  }
}

5. CLI Interface

Basic Usage

1
python tools/sea_new_context.py <context-name>

Options

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

Example

1
python tools/sea_new_context.py inventory --adr-id ADR-025 --prd-id PRD-012 --sds-id REF-012

6. Naming Conventions

Consistent Patterns

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}

Validation

The scaffolder validates context names:


7. Nx Registration

The scaffolder automatically updates nx.json:

1
2
3
4
5
{
  "projects": {
    "specs-inventory": "tools/nx/specs-inventory"
  }
}

8. Post-Scaffold Workflow

After running the scaffolder:

  1. Fill in ADR — Define architectural constraints
  2. Fill in PRD — Define requirements with REQ-IDs
  3. Fill in SDS — Define entities, commands, queries, policies
  4. Update SEA-DSL — Model the domain in SEA™
  5. Run pipeline:
    1
    
    nx run specs-inventory:all
    

9. Integration with VS Code

The scaffolder integrates with VS Code tasks:

Task Definition

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"
}

Input Prompt

1
2
3
4
5
6
{
  "id": "ctx",
  "type": "promptString",
  "description": "Bounded context name (e.g., orders, inventory, billing)",
  "default": ""
}

10. Success Criteria

Metric Target
All files created 100%
Nx project registered
nx run specs-<context>:all succeeds
No manual file creation required

11. Error Handling

Error Response
Context already exists Fail with “Context ‘' already exists"
Invalid context name Fail with naming rules explanation
Cannot write files Fail with filesystem error details
Nx.json not writable Warn and skip registration

12. Summary

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.