Skip to content

/edikt:sdlc:artifacts

Generate implementable design artifacts from an accepted technical specification. Each artifact is treated as a design blueprint — it defines intent and structure, not implementation. Your code, migrations, and schema files are the implementation.

Usage

bash
/edikt:sdlc:artifacts SPEC-005
/edikt:sdlc:artifacts path/to/spec-folder/

Pass a SPEC identifier (e.g., SPEC-005) or the path to the spec folder.

Gate

The spec must have status: accepted before artifacts can be generated:

text
⛔ SPEC-005 status is "draft".
   Specs must be accepted before generating artifacts.
   Review the spec and change status to "accepted" first.

How context is resolved

Before generating anything, the command works through a checklist and records its state explicitly:

Database type — resolved in priority order (first match wins):

  1. Spec frontmatter database_type: — per-spec override, useful in monorepos
  2. Config artifacts.database.default_type — set by /edikt:init from code signals
  3. Keyword scan of spec content — last resort; warns you when used
  4. Still unresolved — asks you directly

Storage strategy — resolved when DB type is sql or mixed:

The command scans spec content and any existing migrations for JSONB signals (jsonb, json column, aggregate storage, embedded entity, nested entity, etc.). If detected, the storage strategy is set to jsonb-aggregate — this changes how the ERD renders entities. If no signals are found, the strategy defaults to normalized.

This matters for projects using the DDD pattern of storing nested entities as JSONB columns inside aggregate root tables. Without detection, the ERD would show a 2-entity diagram that hides structure in comments.

Active invariants — loaded from your governance chain. For each status: Active invariant, the body is stripped of frontmatter and injected as a structured constraint into every artifact agent prompt. If an invariant body is empty, you get a warning:

text
⚠ INV-003 body is empty — constraint not injected. Review docs/architecture/invariants/INV-003-*.md

Artifact versions — resolved from artifacts.versions in config with sensible defaults:

Config keyDefaultUsed in
artifacts.versions.openapi3.1.0contracts/api.yaml
artifacts.versions.asyncapi3.0.0contracts/events.yaml
artifacts.versions.json_schemahttps://json-schema.org/draft/2020-12/schemadata-model.schema.yaml

Teams pinning older versions (e.g., openapi: "3.0.0" for tooling compatibility) set these in .edikt/config.yaml and every generated artifact respects the pin.

The command outputs a state checkpoint before proceeding so you can verify DB type, storage strategy, constraint count, and versions before generation begins.

What gets generated

The command scans the spec and shows what it will generate:

text
Based on SPEC-005, these artifacts are relevant:
  ✓ data-model.mmd        — sql detected via config (Mermaid ERD)
  ✓ model.mmd             — domain class diagram (auto, alongside data-model)
  ✓ contracts/api.yaml    — API endpoint references
  ✓ test-strategy.md      — testing strategy section
  ✗ migrations/           — no schema changes
  ✗ contracts/events.yaml — no messaging patterns
  ✗ config-spec.md        — no config changes

Generate 4 artifacts? (y/n)

Detection is automatic. Confirm or adjust before generation begins. Migrations are only generated for SQL and mixed database types — document and key-value stores never produce migration files.

Database-aware data model

The data model artifact format depends on your resolved database type:

DB typeFileFormat
SQL (Postgres, MySQL, SQLite)data-model.mmdMermaid ERD — entities, fields, relationships, index comments
MongoDB, Firestore, CouchDBdata-model.schema.yamlJSON Schema in YAML — collection, properties, required, indexes
DynamoDB, Cassandra, HBasedata-model.mdAccess patterns table → entity prefixes → PK/SK/GSI design
Redis, Memcached, ElastiCachedata-model.mdKey schema table — key pattern, value type, TTL, purpose

For projects using multiple database types (e.g., Postgres + Redis), both artifacts are generated with suffixes to avoid collision:

Sub-typeFile
SQLdata-model-sql.mmd
MongoDBdata-model-mongo.schema.yaml
DynamoDBdata-model-dynamo.md
Redis / KVdata-model-kv.md

JSONB aggregate storage

When the storage strategy is jsonb-aggregate (detected from spec or migrations), the ERD uses three entity modes:

ModeWhenHow it renders
Physical tableEntity has its own tableNormal entity block
JSONB-embeddedEntity stored as JSONB inside another tableEntity block with relationship label containing jsonb
Reference-onlyEntity from an external bounded contextEntity block with only PK, relationship label containing ref

This makes the structure visible in the diagram instead of hiding nested entities in JSONB column comments.

Domain class diagram

A domain class diagram (model.mmd) is always generated alongside the data model, regardless of database type. It shows the domain model independent of storage:

  • Aggregate roots marked with <<aggregate root>> stereotype
  • Value objects marked with <<value object>> stereotype
  • Composition, aggregation, inheritance, and cross-aggregate references
  • Key domain methods (commands, queries) — not getters/setters

The data model shows how data is stored. The domain class diagram shows what the domain means. Both are generated so teams can reason about storage and semantics separately.

All artifact types

ArtifactTriggered byReviewed by
(see above)database, model, schema, entity, table, column, field, relationshipdba
model.mmd(auto-triggers with data model)architect
contracts/api.yamlAPI, endpoint, route, REST, GraphQL, request, response, contractapi
contracts/proto/gRPC, protobuf, service definitionapi
migrations/ (SQL and mixed only)migration, schema change, ALTER, CREATE TABLEdba
contracts/events.yamlevent, queue, Kafka, RabbitMQ, pub/sub, webhook deliveryarchitect
test-strategy.mdtest, testing strategy, coverage, unit test, integration testqa
config-spec.mdconfig, environment variable, feature flag, configurationsre
fixtures.yamlseed, fixture, test data, sample data (also auto-triggers with data model)qa

API contracts use OpenAPI 3.1.0 YAML (configurable). Event contracts use AsyncAPI 3.0.0 YAML (configurable). JSON Schema for MongoDB models uses the 2020-12 draft (configurable). Fixtures are portable YAML — transform to your stack (SQL seeds, Prisma seed.ts, factory definitions) at implementation time.

Invariant injection

When active invariants exist, every agent prompt includes a structured constraint block:

text
🔀 edikt: routing to dba (2 active constraints applied) — data-model.mmd [jsonb-aggregate]
🔀 edikt: routing to architect — model.mmd

The constraints are pulled verbatim from your invariant bodies and injected before the artifact instruction. Superseded invariants are excluded automatically. When storage strategy is jsonb-aggregate, the tag appears in the routing line for data-model.mmd.

Output location

All artifacts live in the spec's folder:

text
docs/product/specs/SPEC-005-webhook-delivery/
├── spec.md
├── data-model.mmd           ← or .schema.yaml / .md depending on DB type
├── model.mmd                ← domain class diagram
├── contracts/
│   ├── api.yaml
│   └── events.yaml
├── migrations/
│   └── 001_create_webhooks.sql
├── fixtures.yaml
└── test-strategy.md

Each artifact includes a design blueprint header comment in format-appropriate syntax (%% for .mmd, # for .yaml, -- for .sql, HTML comment for .md):

text
Design blueprint — implement in your stack's native format.
This artifact defines intent, not implementation.

Config reference

Database type is detected and written by /edikt:init from code signals. You can also set it manually in .edikt/config.yaml:

yaml
artifacts:
  database:
    default_type: sql   # sql | document | key-value | mixed | auto
  sql:
    migrations:
      tool: golang-migrate  # golang-migrate | prisma | alembic | django | rails | etc.
  fixtures:
    format: yaml
  versions:
    openapi: "3.1.0"                                          # default
    asyncapi: "3.0.0"                                         # default
    json_schema: "https://json-schema.org/draft/2020-12/schema"  # default

auto means the command detects from spec content each time. Use it for greenfield projects or monorepos where each spec sets its own database_type: in frontmatter.

Override versions to pin older spec versions when your toolchain requires it (e.g., openapi: "3.0.0" if your code generator doesn't support 3.1 yet).

After generating

Review each artifact. Accept them individually by changing status: draft to status: accepted in the frontmatter. All artifacts must be accepted before running /edikt:sdlc:plan.

These are design blueprints — implement them in your stack's native format.
The data model defines what exists and why. The API contract defines the interface.
The migration defines intent. Your code is the implementation.

What's next

Released under the Elastic License 2.0. Free to use, not for resale.