Software Engineering Guide for SEA-Forge™

The spec-first, generator-driven workflow for the SEA™ monorepo.

This guide explains the actual development workflow for this repository—every step is grounded in the real tooling and configuration.

SEA-DSL Language Reference:


Prerequisites

Requirement How to Check Install/Fix
Node.js (via mise) node --version mise install
pnpm 10.x pnpm --version corepack enable
Python 3.13+ python3 --version mise install
Docker docker --version Install Docker Desktop
just just --version Install via cargo or mise

Quick setup:

1
2
just setup    # Installs Node + Python deps, creates .venv
just doctor   # Validates environment health

Repository Structure

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
SEA™/
├── apps/                    # Application shells (minimal, mostly placeholder)
├── libs/
│   ├── sea/                 # Core SEA™ bounded context
│   │   ├── domain/          # Domain entities, value objects
│   │   └── ports/           # Port interfaces (hexagonal)
│   └── shared/              # Cross-cutting libraries
│       ├── contracts/       # API/event schemas (Zod)
│       ├── config/          # Configuration validation
│       ├── feature-flags/   # OpenFeature + Flipt integration
│       ├── observability/   # OpenTelemetry instrumentation
│       └── testing/         # Test utilities and fakes
├── docs/
│   ├── specs/               # ⭐ All specifications live here
│   │   ├── shared/          # Shared ADRs, PRDs, SDS templates
│   │   ├── semantic-core/   # SEA™ DSL, Knowledge Graph specs
│   │   ├── cognitive-extension/  # AI agents, CADSL specs
│   │   ├── architectural-governance/  # CALM, compliance specs
│   │   └── developer-tooling/   # Flow linter, scaffolder specs
│   ├── howto/               # This guide and others
│   ├── playbooks/           # SOP documents (ENGINEERING.SOP.md, etc.)
│   └── reference/           # SEA-DSL language references
├── generators/              # Nx generators (sea:bounded-context, etc.)
├── tools/
│   ├── schemas/             # JSON schemas for validation
│   │   ├── ast-v3.schema.json
│   │   ├── sds.schema.json
│   │   ├── sea_ir.schema.json
│   │   └── manifest.schema.json
│   ├── ast_to_ir.py         # AST → IR compiler
│   ├── ir_to_manifest.py    # IR → Manifest compiler
│   ├── validate_sds.py      # SDS schema validation
│   ├── regen_check.py       # Determinism verification
│   ├── flow_lint.py         # Flow annotation linter
│   └── sea_new_context.py   # Context scaffolding script
├── infra/                   # Docker Compose, Flipt config, OTel
├── schemas/                 # Additional JSON schemas for contracts
└── justfile                 # All canonical commands

Core Principles

1. Specs Are Source of Truth

Never handwrite runtime code. Runtime code is generated from specs/SEA™/manifest via generators.

All application logic originates from:

2. Allowed Edits Only

Per AGENTS.md, agents and humans may only modify:

Path Purpose
docs/specs/** ADR, PRD, SDS, SEA™ files
.github/** Copilot customization
tools/** Compilers, linters, generators
.vscode/**, .githooks/** IDE/workflow config
**/src/gen/** Generated output (read-only to humans)

3. Just-First Workflow

All commands go through just. Discover available commands with:

1
2
just          # Shows all available recipes
just --list   # Same as above

4. Agent Workflows

AI agents can use slash commands for common tasks:

Command Purpose
/spec Create new ADR, PRD, SDS, or SEA-DSL spec
/feature Implement feature end-to-end from spec to code
/cycle Execute a TDD cycle using worktrees
/debug Systematic debugging with observability
/review Review PR against spec-first standards
/migrate-plan Migrate old plan to current template

Workflows are defined in .agent/workflows/. Example:

1
2
3
/spec adr 035 event-sourcing-strategy
/feature docs/plans/15_OrderManagement.plan.md
/cycle start 9 1 A order-entity

The Spec-to-Code Pipeline

Step 0: Pre-Flight Checks (Critical)

Lesson Learned: Infrastructure issues commonly derail implementation. Always verify before coding.

1
2
3
4
5
6
7
8
9
# 1. Verify generators compile and list them
just generator-check

# 2. Check for SEA-DSL annotation compliance
just flow-lint

# 3. Ensure dependencies are current
just setup
just doctor

Fallback (if just recipes aren’t available):

1
2
pnpm nx run generators:build
pnpm install

Common Generator Issues:

Step 1: Create a Bounded Context

1
2
3
4
5
6
7
8
# Scaffold a new bounded context (preferred)
just generator-bc orders

# Or with explicit scope and language
just generator-bc orders sea typescript

# Fallback: Direct Nx invocation
pnpm nx g @sea/generators:bounded-context orders --scope=sea

This creates the hexagonal architecture structure in libs/orders/.

Post-Generator Checklist:

Step 2: Write the ADR

The ADR documents decisions, not requirements:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# ADR-XXX: Orders Bounded Context

## Context
What problem this context solves.

## Decision
- Use DDD + Hexagonal Architecture
- Use CQRS with flow annotations
- Use SEA™ pipeline for code generation
- Enforce module boundaries via Nx

## Constraints
- MUST use Nx generators
- MUST generate all runtime code from manifests
- MUST pass determinism checks

## Consequences
Increased file count, requires discipline, but guarantees consistency.

Step 3: Write the PRD

Requirements in EARS notation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# PRD-XXX: Orders Domain

Satisfies: ADR-XXX

## Requirements

### REQ-001 (functional)
When a customer checks out, the system shall create an order.

### REQ-002 (nonfunctional)
The API shall respond within 200ms P95 for GetOrder.

### REQ-003 (constraint)
The system must publish OrderPlaced events at-least-once.

Step 4: Write the SDS (YAML)

The machine-readable design spec:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# orders.sds.yaml
metadata:
  namespace: orders
  satisfies:
    - PRD-XXX

entities:
  Order:
    properties:
      - name: orderId
        type: UUID
        required: true
      - name: status
        type: enum[pending, confirmed, shipped]
        
flows:
  PlaceOrder:
    type: command
    input: PlaceOrderCommand
    output: Order
    emits: [OrderPlaced]

Validate it:

1
just sds-validate docs/specs/orders/orders.sds.yaml

Step 5: Write the SEA-DSL

Create the domain model with flow annotations:

// orders.sea
namespace orders;

entity Order {
  orderId: UUID;
  status: OrderStatus;
}

enum OrderStatus { pending, confirmed, shipped }

resource PlaceOrderCommand {
  customerId: UUID;
  items: List<LineItem>;
}

event OrderPlaced {
  orderId: UUID;
  timestamp: DateTime;
}

/**
 * @cqrs { "kind": "command" }
 * @tx { "transactional": true }
 * @idempotency { "enabled": true, "key": "customerId+items" }
 */
flow PlaceOrder(cmd: PlaceOrderCommand) -> Order {
  // Flow logic here
}

Validate and parse:

1
2
just sea-validate docs/specs/orders/orders.sea
just sea-parse docs/specs/orders/orders.sea

Step 6: Run the Full Pipeline

Individual steps:

1
2
3
4
5
6
7
8
9
10
11
# Compile AST → IR
just ast-ir docs/specs/orders/orders.ast.json

# Compile IR → Manifest
just ir-manifest docs/specs/orders/orders.ir.json

# Generate code
just codegen docs/specs/orders/orders.manifest.json

# Verify determinism
just regen-check docs/specs/orders/orders.manifest.json

Or run the entire pipeline at once:

1
just pipeline orders

Or use Nx targets:

1
just nx-run specs-orders all

Just Commands Reference

The justfile is the canonical command interface. Run just to see all commands.

🚀 Getting Started

1
2
3
just setup          # Install all dependencies
just doctor         # Health check
just env-enter      # Enter Devbox shell

🧪 Testing

1
2
3
4
5
6
7
8
9
just test           # Full test suite (specs + python + typescript)
just test-specs     # Spec validation only
just test-python    # Python tests via pytest
just test-ts        # TypeScript tests via Vitest (affected)
just test-ts-project <name>  # Test specific project
just test-ts-coverage        # Tests with coverage
just test-e2e       # E2E tests via Playwright
just test-e2e-headed         # E2E with visible browser
just playwright-install      # Install browser binaries

📋 Spec Validation & Linting

1
2
3
4
5
just spec-guard       # Full validation suite
just spec-check       # Cross-check specs
just spec-check-strict        # Strict mode
just spec-index       # Generate spec index JSON
just flow-lint        # Lint flow annotations

🔄 CI Mirror (Run CI Locally)

Run the same checks locally that GitHub Actions CI runs. Diagnose issues before pushing.

1
2
3
4
5
6
7
just ci               # Full CI check (lint + specs + tests + determinism)
just ci-quick         # Fast check (lint + specs only)
just ci-lint          # Lint affected projects
just ci-spec          # Spec validation + flow lint
just ci-test          # TypeScript + Python tests
just ci-determinism   # Check repo clean after codegen
just pre-push         # Same as ci-quick (for git hook)

Recommended workflow:

1
2
3
4
5
# Before pushing, run quick check
just ci-quick

# Before opening PR, run full check
just ci

⚙️ SEA™ Compiler Pipeline

1
2
3
4
5
6
7
8
just sds-validate <file>      # Validate SDS YAML
just sea-validate <file>      # Validate SEA-DSL syntax
just sea-parse <file>         # Parse SEA™ → AST JSON
just ast-ir <file>            # Compile AST → IR
just ir-manifest <file>       # Compile IR → Manifest
just codegen <manifest>       # Generate code from manifest
just regen-check <manifest>   # Verify determinism
just pipeline <ctx>           # Run full pipeline for context

🔧 Nx Workspace Utilities

1
2
3
4
5
6
just nx-show <project>        # Show project details
just nx-graph                 # Visualize dependencies
just nx-run <project> <target>    # Run target on project
just nx-affected <target>     # Run on affected projects
just nx-all <target>          # Run on all projects
just nx-list                  # List all projects

🏗️ Generators

1
2
3
4
5
just generator-list                  # List available generators
just generator-bc <name>             # Create bounded context
just generator-bc <name> <scope> <lang>  # With options
just generator-adapter <name> <ctx>  # Create adapter pair
just generator-api <name> <ctx>      # Create API surface

🐳 Development Services

1
2
3
4
5
just dev            # Run spec guard (primary workflow)
just dev-up         # Start PostgreSQL, Redis
just dev-down       # Stop services
just dev-reset      # Destroy volumes and reset
just dev-seed       # Seed initial data

🚩 Feature Flags & Observability

1
2
3
4
just flags-up       # Start Flipt server
just flags-down     # Stop Flipt
just otel-up        # Start OTel Collector
just otel-down      # Stop OTel Collector

� Walking Skeleton Runtime

Local development stack for RAG pipeline: embeddings, vector search, RDF, policy engine.

1
2
3
4
5
just skeleton-up       # Start pgvector + Oxigraph + OPA
just skeleton-down     # Stop all skeleton services
just skeleton-reset    # Destroy volumes and reset
just skeleton-tune     # Auto-tune for your machine resources
just skeleton-status   # Check health of all services

Services started by skeleton-up:

Service Port Purpose
PostgreSQL + pgvector 5432 Vector embeddings storage (384-dim)
Oxigraph 7878 RDF triple store + SPARQL queries
OPA 8181 Policy engine for governance

Testing the skeleton:

1
2
python3 tests/skeleton/test_walking_skeleton_runtime.py  # E2E tests
python3 tests/skeleton/test_llm_integration.py           # LLM tests (requires Ollama)

�🧹 Maintenance

1
2
just clean          # Clean build artifacts
just clean-all      # Deep clean (removes node_modules, .venv)

🔐 Secrets

1
just sops-rotate RECIPIENT='age1...'  # Rotate encryption keys

🔄 TDD & Git Workflow

Full guide: TDD Cycles with Worktrees

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Cycle lifecycle (worktree-first)
just cycle-start <phase> <cycle> <agent> <slug>  # Create branch + worktree
just cycle-complete <phase> <cycle> <agent>      # Push, prepare for PR
just cycle-worktree-remove <phase> <cycle> <agent>  # Remove worktree

# Worktree management
just worktrees           # List active worktrees
just worktrees-status    # Show merge status of each
just worktrees-clean     # Remove merged worktrees
just worktrees-clean-all # Remove ALL worktrees (nuclear)

# Branch promotions
just promote-stage       # Promote dev → stage
just promote-main        # Promote stage → main
just release <ver>       # Create release tag
just hotfix-forward      # Forward-merge hotfix

Flow Annotation Contract

Every Flow in SEA-DSL must include CQRS annotation:

/**
 * @cqrs { "kind": "command" | "query" | "event" }
 */

Recommended additional annotations:

Annotation When to Use Example
@tx Transactional commands @tx { "transactional": true }
@idempotency Idempotent commands @idempotency { "enabled": true, "key": "orderId" }
@outbox Event publishing @outbox { "mode": "required" }
@read_model Query projections @read_model { "name": "OrderSummary" }

Hard rule: Use nested JSON inside annotations (no dotted keys).


CI/CD Gates

Gate A: Allowed File Changes

PRs fail if changes touch files outside allowed paths (see AGENTS.md).

Gate B: Schema Validation

Every artifact must pass schema validation:

Gate C: Determinism

1
2
just regen-check docs/specs/<ctx>/<ctx>.manifest.json
git diff --exit-code  # Must be clean

PR Checklist


Testing Harness

Tool Purpose Command
Vitest Unit/integration tests (TS) just test-ts
pytest Python tests just test-python
Playwright E2E browser tests just test-e2e
Testcontainers Integration tests with real infra Via Vitest/pytest
MSW API mocking Import from @msw/server

Running Tests

1
2
3
4
5
6
7
8
9
10
11
12
# All affected TypeScript tests
just nx-affected test

# Specific project
just test-ts-project shared-contracts

# With coverage
just test-ts-coverage

# E2E (after installing browsers)
just playwright-install
just test-e2e

Where AI Agents Fit

GitHub Copilot and other agents are useful for:

  1. Drafting specs (ADR/PRD/SDS boilerplate)
  2. Writing SEA-DSL from design specs
  3. Updating generators and templates
  4. Writing Nx target configurations

Safety is maintained by:


Quick Reference Cards

New Feature Workflow

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. Create bounded context
just generator-bc orders

# 2. Write specs in docs/specs/orders/
#    - orders.adr.md (decisions)
#    - orders.prd.md (requirements)
#    - orders.sds.yaml (design)
#    - orders.sea (domain model)

# 3. Run the pipeline
just pipeline orders

# 4. Verify
just spec-guard
git diff --exit-code

Debugging Failures

Error Likely Cause Fix
SDS validation fails YAML syntax or missing fields just sds-validate <file> shows errors
SEA™ parse fails Invalid DSL syntax just sea-validate <file> shows line/column
AST→IR fails Missing namespace or invalid refs Ensure metadata.namespace is set
Regen check fails Non-deterministic output Review generator templates
Generator build fails TypeScript type errors Use literal unions not string
Cannot find module Missing path mapping Add to tsconfig.base.json
Flow lint fails Missing @cqrs annotation Add annotations to all flows
Python import error Service not installed Run pip install -e . in service dir

Generator Troubleshooting

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Symptom: "Cannot find generator 'sea:adapter'"
# Fix: Use just recipe (preferred) or correct Nx prefix
just generator-adapter myname myctx http

# Fallback: Direct Nx invocation
pnpm nx g @sea/generators:adapter myname --context=myctx --backend=http

# Symptom: Generator TypeScript errors
# Fix: Build generators first
just generator-build

# Fallback: Direct Nx build
pnpm nx run generators:build

# Symptom: Don't know what generators exist
just generator-list

# Common type fix - use literal unions:
# BAD:  backend: string
# GOOD: backend: 'http' | 'postgres' | 'redis' | 'memory'

Polyglot Development (Python + TypeScript)

For bounded contexts requiring both languages (e.g., LLM providers):

Directory Structure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
libs/<context>/
├── domain/
│   └── src/
│       ├── lib/types.ts       # TypeScript domain types
│       └── gen/types.py       # Python domain types
├── ports/
│   └── src/
│       ├── lib/*.port.ts      # TypeScript port interfaces
│       └── gen/ports.py       # Python port interfaces
└── adapters/
    └── src/
        └── lib/
            ├── fake.adapter.ts    # Fake for testing
            └── http.adapter.ts    # HTTP client to Python service

services/<context>/
├── pyproject.toml             # Python dependencies
├── Dockerfile                 # Container build
├── main.py                    # FastAPI entry point
└── src/
    ├── api/routes.py          # HTTP endpoints
    ├── adapters/<name>.py     # Real Python adapter
    └── config/settings.py     # Pydantic settings

Development Pattern

  1. Define domain types in both languages - keep them synchronized
  2. Python service exposes HTTP API (OpenAI-compatible for LLM)
  3. TypeScript adapter calls Python service via HTTP
  4. Fake adapter enables TS-only testing without Python running

Fake-First Testing

Lesson Learned: Create fakes before real adapters to enable parallel development.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 1. Port interface
export interface LlmProviderPort {
  completeChat(request: ChatRequest): Promise<ChatCompletion>;
}

// 2. Fake adapter (implements port, deterministic responses)
export class FakeLlmAdapter implements LlmProviderPort {
  async completeChat(request: ChatRequest): Promise<ChatCompletion> {
    return { id: `fake-${Date.now()}`, content: 'Echo: ' + request.messages[0]?.content };
  }
}

// 3. Tests use fake (no external deps)
// 4. Real adapter implements same interface, calls Python service

Document Purpose
TDD Cycles with Worktrees Complete TDD cycle + worktree workflow
AGENTS.md Editing rules, sequencing, PR checklist
ARCHITECTURE.md System overview, 5 pillars
ENGINEERING.SOP.md Phase-by-phase implementation guide
SDD.SOP.md Full SDD workflow documentation
SEA-DSL Reference Language grammar and syntax