A generic, domain-agnostic spec-driven runtime for business applications. Domain specifications (.spec files) define entities, workflows, actions, and views — the runtime executes them with full effect tracing and governance. The platform is not tied to any specific industry; it can drive insurance, logistics, HR, finance, or any OLTP domain.
The included insurance claims module (domain/insurance/claims/) is a reference implementation that demonstrates the full vertical slice: Spec DSL → Semantic Model → Runtime Engine → React UI.
This project implements the Spec-Driven Development platform concept along with the derived Runtime architecture specification (both developed in various chat sessions in ChatGPT and Claude). The key idea is to create such a platform from scratch and implement it iteratively with AI coding agents.
┌──────────────────────────────────────────────────────────┐
│ React Frontend (:3000) │
│ Spec-driven renderers: SpecFormView · SpecListView │
│ SpecCreateForm · FieldRenderer · WorkflowStepper · SSE │
└────────────────────────┬─────────────────────────────────┘
│ HTTP / SSE (proxied via Vite)
┌────────────────────────┴─────────────────────────────────┐
│ Domain-Agnostic Fastify Runtime (:3001) │
│ Action Routes · Query Routes · Meta Routes · Auth · SSE │
│ Loads DomainModules → merges graphs, scripts, resolvers │
├──────────────────────────────────────────────────────────┤
│ Action Orchestrator │
│ 12-step cycle: resolve → guards → transaction → │
│ script → collect effects → validate → commit → project │
├──────────────────────────────────────────────────────────┤
│ Workflow Engine · Rule Engine · Effect Validator │
├──────────────────────────────────────────────────────────┤
│ Platform Persistence (AuditLog · Outbox) │
│ Kysely (SQLite dev / PostgreSQL prod) · Migrations │
└──────────────────────────────────────────────────────────┘
↑ DomainModule registry
┌────────┴─────────────────────────────────────────────────┐
│ Domain Module(s) — pluggable per domain │
│ e.g. domain/insurance/claims/module.ts │
│ .spec files · Action Scripts · Capabilities · Hooks │
│ Data Routes · Seed Data │
└──────────────────────────────────────────────────────────┘
The runtime is domain-agnostic. It contains zero references to claims, policies, or any business concept. All domain-specific code lives under domain/ and registers itself via the DomainModule contract. A lint check (pnpm lint:boundaries) enforces this separation.
Delta-Merge enables structured domain evolution: instead of editing .spec files directly, changes are formulated as typed deltas (add/modify/remove) in delta.spec files, validated against the live graph, previewed non-destructively via graph overlay, and atomically merged.
Spec-Driven Navigation: The frontend discovers all views from GET /api/meta/views and builds sidebar navigation + routes automatically. Adding a view spec creates a UI page — no React code changes needed.
Domain specifications are written in a custom DSL that is domain-agnostic. The @platform/spec-dsl parser reads .spec files at startup, resolves cross-references (including entity inheritance, weak entities/aggregates, lookups, invariants, and policies), assigns semantic IDs, and registers everything into the AppGraph. Specs are the live source of truth — edit a .spec file and the runtime picks it up on next start. See SPEC-REF.md for the complete DSL reference.
Example action spec (from the insurance demo):
action ApproveClaim for Claim in claims
input
claimId : UUID required
comment : String optional
guards
actor hasRole "Adjuster"
claim.status == InReview
effects
transitions Claim from InReview to Approved
updates Claim.approvedAt, Claim.approvedBy
emits ClaimApproved
audits "claim-approval"
output
claimId : UUID
newStatus : ClaimStatus
approvalMode : String
script "./scripts/ApproveClaim.ts"
end
Every action declares what effects it will produce. During execution, the scripting host records what actually happened. After execution, the validator compares declared vs. observed:
| Effect | Meaning | Example |
|---|---|---|
updates |
Field changed | updates Claim.status |
creates |
New entity | creates ApprovalTask |
transitions |
Workflow state change | transitions Claim from InReview to Approved |
emits |
Domain event | emits ClaimApproved |
calls |
External capability | calls FraudEngine.ScoreClaim |
audits |
Compliance trail | audits "claim-approval" |
Violations (undeclared effects) block the action. Mismatches (missing declared effects) are logged as warnings. All traces stored in the effect_traces table.
Terminal-based access to the platform API. Same endpoints as the frontend, structured JSON output by default (AI-agent-friendly). Run via pnpm cli <args> from the project root.
pnpm cli login -u <email> -p <password> Authenticate, store JWT
pnpm cli meta <type> [id] Explore metadata (views, entities, actions, ...)
pnpm cli describe <actionId> Show input schema, guards, effects
pnpm cli form <actionId> Show input template (what fields are needed)
pnpm cli execute <actionId> -i <json> Execute a domain action
pnpm cli validate <actionId> -i <json> Validate input without executing
pnpm cli query <viewId> [--filter k=v] [--sort] Query view data (list)
pnpm cli get <viewId> <entityId> Get entity detail
pnpm cli batch <file.json> Execute multiple operations from file
Global options: --server <url> (default http://localhost:3001), --token <jwt>, --format <json|table|raw>.
Meta types: views, entities, actions, workflows, enums, lookups, stats. Pass an ID to get detail: pnpm cli meta actions <actionId>.
POST /api/auth/login Login
POST /api/actions/:actionId/execute Execute a domain action
POST /api/actions/:actionId/validate Validate input without executing
GET /api/views/:viewId/data Query view data (list)
GET /api/views/:viewId/data/:entityId Get entity detail
GET /api/meta/views List all view descriptors (drives navigation)
GET /api/meta/views/:viewId View descriptor (metadata)
GET /api/meta/actions/:actionId Action descriptor
GET /api/meta/workflows/:workflowId Workflow descriptor
GET /api/meta/graph/stats AppGraph statistics
GET /api/meta/lookups Lookup reference data (key/label pairs)
GET /api/meta/enums Enum descriptors with labels
GET /api/data/* Domain-registered data endpoints
GET /api/realtime/subscribe SSE event stream
GET /api/health Health check (modules, graph stats)
- Node.js 22+
- pnpm 9+
# Install dependencies
pnpm install
# Build all packages (required before first run)
pnpm build
# Seed the development database (SQLite)
pnpm dev:seed
# Start the API server (port 3001) — keep this terminal open
pnpm --filter @platform/runtime dev
# In a SECOND terminal — start the React frontend (port 3000)
pnpm --filter @platform/frontend devOpen http://localhost:3000 in your browser. This is the React UI.
Do NOT open port 3001 directly — that is the API server (Fastify) which only serves JSON. The frontend on port 3000 automatically proxies /api requests to port 3001 via Vite.
The platform ships with a complete insurance claims domain as a reference implementation. See FEATURE-DEMOS.md for interactive walkthroughs (browser + CLI) covering the full claim lifecycle, lookup fields, spec-driven navigation, role-based views, child views, and weak entities.
| User | Password | Role | What they can do |
|---|---|---|---|
| anna.clerk@example.com | password123 | Clerk | Create and submit claims |
| bob.adjuster@example.com | password123 | Adjuster | Review, approve, reject, pay claims |
| carol.senior@example.com | password123 | SeniorAdjuster | Approve escalated claims (>25k EUR) |
| dave.fraud@example.com | password123 | FraudReviewer | Review fraud-flagged claims |
platform/
├── packages/ # Domain-agnostic platform infrastructure
│ ├── core/ # Types, semantic IDs, AppGraph, engines, DomainModule contract
│ ├── spec-dsl/ # Spec DSL parser, resolver, graph loader
│ ├── runtime/ # Domain-agnostic Fastify server, persistence, auth, SSE
│ ├── frontend/ # React 19 + Redux Toolkit UI
│ ├── cli/ # pnpm cli: terminal-based platform access
│ └── testing/ # Test harness, effect assertions
├── domain/ # Pluggable domain modules (one per business domain)
│ └── insurance/claims/ # Reference domain: insurance claims processing
│ ├── package.json # Workspace package with @platform/core dependency
│ ├── module.ts # DomainModule entry point (loads .spec files, provides hooks)
│ ├── capabilities/ # FraudEngine + PaymentGateway mocks
│ ├── views/routes.ts # Domain-specific data endpoints (/api/data/policies, etc.)
│ ├── seed.ts # Demo data (users + audit in TS, domain entities from seed.spec)
│ ├── scripts/ # 8 action scripts (TypeScript)
│ └── spec/ # Spec files — the live source of truth
│ ├── current/ # Entity, enum, lookup, rule, workflow, action, view, capability, policy specs
│ ├── data/ # Declarative seed data (claims.seed.spec)
│ ├── changes/ # Pending delta-merge changes
│ └── archive/ # Merged changes
├── scripts/
│ └── check-domain-boundaries.sh # Lint: no insurance terms in runtime
├── migrations/ # Platform infrastructure migrations (audit, outbox, users)
└── data/ # dev.db (gitignored)
Any business domain plugs into the platform by implementing the DomainModule interface (packages/core/src/types/domain-module.ts):
interface DomainModule {
name: string; // e.g., "insurance.claims", "logistics.shipping"
registerGraph(graph: AppGraph): void; // Register entities, actions, workflows, ...
getScripts(): Map<string, ActionScript>;
getCapabilities(): Map<string, CapabilityHandler>;
getHooks?(): Map<string, DomainHook>; // Escape hatches for custom logic
registerRoutes?(app, db, authHelpers): void;
seed?(db): Promise<void>;
// Optional (reflective runtime handles these if not provided):
// buildDomainApi?, getViewResolvers?, getEntityResolvers?
}The runtime discovers modules in packages/runtime/src/bootstrap/load-domain.ts and iterates them at startup to build the AppGraph, collect scripts, wire capabilities, and register routes.
| Layer | Technology |
|---|---|
| Language | TypeScript 5 (strict) |
| Monorepo | pnpm workspaces + Turborepo + tsup |
| Backend | Node.js 22 + Fastify 5 |
| Database (dev) | SQLite via better-sqlite3 |
| Database (prod) | PostgreSQL 16 |
| DB Access | Kysely (type-safe query builder) |
| Frontend | React 19 + Redux Toolkit + Vite |
| CLI | Commander (zero-dep arg parser) |
| Realtime | Server-Sent Events |
| Auth | JWT |
| Validation | Descriptor-driven (from entity specs) |
The chosen technology stack and build system are not the focus of this experiment — they serve the platform concept, not the other way around.
The current approach (after a ramp-up phase) is to derive features from these specification documents, group them in feature sets, and then plan and implement them step by step — while also exploring and experimenting along the way.
Key elements of the workflow:
- Feature sets (
plan/): Features are grouped into coherent sets (e.g., "Localization + Seed Interpreter") and implemented in sessions.plan/backlog.mdholds future sets,plan/next.mdthe active one,plan/done.mdcompleted ones. - Red-Green TDD: Every feature starts with failing tests, then implementation to make them pass.
- Feature Completion Checklist (
PLAN.md): After each feature — write feature doc, update all top-level docs, extend E2E demo tests, commit together. - ADRs (
adrs/): Architectural decisions that deviate from or fill gaps in the original concept and architecture specs are captured as Architecture Decision Records. - Feature docs (
features/): Each completed feature gets a timestamped doc with context, design decisions, and implementation details. - Spec-driven verification:
pnpm build && pnpm test && pnpm dev:reset && pnpm lint:boundariesruns after every change.
There are no formal coding guidelines. Cleanup, refactoring, and documentation sweeps happen ad-hoc as the codebase evolves.
The doc/ directory contains the foundational specification documents that define the platform's vision and architecture. These were developed iteratively in ChatGPT and Claude sessions and serve as the conceptual blueprint from which the implementation is derived. Everything else in this project traces back to these two documents.
| Document | Audience | Content |
|---|---|---|
doc/integrated-spec.md |
Architects, contributors | Origin spec — the consolidated platform vision: Spec-Driven Development concept, semantic core, effect system design, agentic development approach. This is the "why" and "what" of the platform |
doc/platform-runtime-view-v5.md |
Architects, developers | Runtime architecture spec — how the concepts from the integrated spec operationalize at runtime: Semantic Core, Spec-DSL, Delta-Merge, Effect System, Business Scripting, Lenses |
SPEC-REF.md |
Domain modelers | Complete DSL reference — syntax, semantics, runtime behavior for all spec types |
DOMAIN-CHANGES.md |
Domain modelers | Step-by-step tutorials for extending a domain module (add field, add entity, add action, delta-merge) |
FEATURE-DEMOS.md |
Anyone | Interactive walkthroughs of all platform features using the insurance demo |
ANALYSIS.md |
Developers | Deep internals — each package, how they connect, execution traces |
ADRS.md |
Developers | Architecture decision records (adrs/) |
PLAN.md |
Contributors | Roadmap structure — points to plan/ for backlog, current work, done sets |
NOTES.md |
Contributors | Design notes index — topic explorations, rationale, concept comparisons (notes/) |
features/ |
Contributors | Timestamped feature docs — context, design decisions, implementation details per completed feature |