.codex/skills/design-doc/SKILL.md
Generate a detailed design document via `tx doc add design`. Covers architecture, interfaces, data model, invariants, failure modes, verification, and testing strategy. References plan via file path instead of embedding. Plan lives in ~/.codex/plans/<name>.md. Reads companion PRD automatically to map EARS requirements to invariants. Output lands in specs/design/<name>.md.
npx skillsauth add jamesaphoenix/tx design-docInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Create a comprehensive technical design document using the tx doc primitive. Design docs specify HOW the system implements requirements, with traceable invariants and a concrete testing strategy.
Design Doc + PRD are companions. A PRD defines WHAT and WHY. A design doc defines HOW. If a PRD exists for this feature, the design doc reads it automatically and maps every must-priority EARS requirement to an invariant + verification entry.
doc_id. Human name slugs only need to be unique within their doc kind.<feature>-prd and <feature>-design.START
│
▼
┌─────────────────────────────────────────────────────┐
│ Step 0: PLAN GATE │
│ │
│ Is there an active plan in this conversation? │
│ │
│ ├─ YES → Save plan to `~/.codex/plans/<name>.md` if not │
│ │ already saved. Set `plan: ~/.codex/plans/<name>.md` │
│ │ in frontmatter. │
│ │ → Continue to Step 0.5 │
│ │ │
│ └─ NO → Tell the user to run `plan` first. │
│ If enough detail provided, generate plan, │
│ save to `~/.codex/plans/<name>.md`. │
│ → Continue to Step 0.5 │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Step 0.5: CHECK FOR COMPANION PRD │
│ │
│ Run: tx doc list --kind prd │
│ │
│ ├─ PRD exists for this feature? │
│ │ → tx doc show <prd-name> --md │
│ │ → Extract ALL EARS requirements │
│ │ → Each `must` EARS req MUST get an invariant │
│ │ and a verification entry in this design doc │
│ │ → Set `implements: <prd-name>` in frontmatter │
│ │ → Continue to Step 1 │
│ │ │
│ └─ No companion PRD? │
│ → Continue to Step 1 (design doc stands alone) │
│ → Suggest creating PRD after: `prd` <name> │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Step 1: SCAFFOLD via tx │
│ │
│ tx doc add design <name> --title "<title>" │
│ ├─ SUCCESS → Continue to Step 2 │
│ └─ FAIL (exists) → Edit existing doc │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Step 2: DEEP CONTEXT GATHERING │
│ │
│ Read: ARCHITECTURE.md, QUALITY.md, project instructions (for example `AGENTS.md`, if present), │
│ domain code, schema.ts, effect-schemas, │
│ API routes, workflows, activities, │
│ existing designs (tx doc list --kind design) │
│ → Continue to Step 3 │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Step 3: FILL DOCUMENT │
│ │
│ Write `# Plan` first (reference to plan file from │
│ Step 0). │
│ Then fill all sections from plan + PRD + codebase. │
│ │
│ MINIMUM THRESHOLDS: │
│ - Invariants: ≥ 5 │
│ - Failure modes: ≥ 3 │
│ - Verification entries: ≥ 5 │
│ - Integration test files: ≥ 2 (HARD REQUIREMENT) │
│ - Unit test files: ≥ 1 (recommended, not hard) │
│ - Sequence diagrams: ≥ 2 (happy + error) │
│ - Design decisions: ≥ 1 │
│ │
│ Integration tests are the primary verification │
│ mechanism. Unit tests complement but do not replace │
│ integration tests. │
│ │
│ RULE: No section may be left as a template/stub. │
│ │
│ COMPREHENSIVENESS: The design doc must cover EVERY │
│ item from the plan. Every implementation step, │
│ constraint, risk, and decision in the plan must │
│ appear in the design doc with full technical detail. │
│ The design doc is the single source of truth for HOW │
│ the feature is built — it should be detailed enough │
│ that an engineer can implement from it alone. │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Step 4: SELF-AUDIT │
│ │
│ Check: │
│ ├─ Every plan item captured in a section? │
│ ├─ Every PRD `must` EARS req has an invariant? │
│ ├─ Every invariant has a verification entry? │
│ ├─ Minimums met? │
│ ├─ No stubs/placeholders? │
│ ├─ All diagrams complete? │
│ └─ Plan file exists at frontmatter path and is │
│ consistent with doc sections? │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Step 5: VALIDATE │
│ │
│ tx spec lint │
│ ├─ PASS → Continue to Step 6 │
│ └─ WARN/FAIL → Fix, re-validate │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Step 5.5: SYNC PLAN FILE │
│ │
│ Read the plan file from frontmatter `plan:` path. │
│ Compare with what the doc now contains. │
│ UPDATE the plan file to incorporate: │
│ - Architecture decisions, component inventory │
│ - Interface contracts, data model details │
│ - Invariants, failure modes, error handling │
│ - Implementation sequence, testing strategy │
│ The plan file must reflect the FULL current state │
│ of the feature — not just the initial draft. │
│ This is a MANDATORY step, not optional. │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Step 6: DISCOVER + LINK + REPORT │
│ │
│ tx spec discover --doc <name> │
│ tx doc link <prd> <design> (if PRD exists) │
│ tx doc show <name> │
│ tx spec gaps --doc <name> │
│ Print summary │
└─────────────────────────────────────────────────────┘
│
▼
DONE
The plan is the primary input. Check for plan content in the conversation:
~/.codex/plans/<name>.md (relative to repo root).plan first.The doc's frontmatter gets plan: ~/.codex/plans/<name>.md and the # Plan section contains a reference link + brief summary, not the full verbatim content.
tx doc list --kind prd
If a PRD exists for this feature:
tx doc show <prd-name> --mdmust-priority EARS requirement MUST become:
invariants: YAML blockverification: YAML blockimplements: <prd-name> in frontmatterIf no PRD exists, the design doc stands alone. Suggest creating one after.
tx doc add design $ARGUMENTS --title "<Human-Readable Title>"
Creates specs/design/<name>.md. If exists, edit instead.
Read these files:
docs/ARCHITECTURE.md — architecture + DDD structuredocs/QUALITY.md — all invariants, governance rulesproject instructions (for example AGENTS.md, if present) — stack, conventionspackages/core/src/domains/packages/infra/db/src/schema.tspackages/infra/db/src/effect-schemas/apps/api/src/apps/worker/src/workflows.tsapps/worker/src/activities.tstx doc list --kind design---
kind: spec
spec_type: design
name: <name>
title: "<title>"
status: draft
version: 1
owners:
- <team-or-person>
summary: Technical approach for <title>
domain: <product-area>
tags:
- design
depends_on: []
supersedes: []
implements: <prd-name-or-null>
last_reviewed_at: <YYYY-MM-DD>
plan: ~/.codex/plans/<name>.md
---
Update owners, summary, domain, tags, depends_on, implements.
# Plan comes first (as a reference to the plan file). Then all technical sections. No section may be a stub.
If a companion PRD exists, every must EARS requirement maps to an invariant + verification entry.
# Plan
> Full plan: [~/.codex/plans/<name>.md](../~/.codex/plans/<name>.md)
<2-3 sentence summary of what the plan covers. The full plan lives in the file referenced above.>
# Summary
2-3 sentences on design approach and key technical decisions.
# Architecture
## System Context
Where this feature sits in the existing system. Reference `docs/ARCHITECTURE.md`.
## Component Diagram
┌──────────────────────────────────────────────────────┐ │ API Layer │ │ ┌──────────────────────────────────────────┐ │ │ │ apps/api [MOD] │ │ │ │ ├── routes/<domain>.ts [NEW] │ │ │ └──────────────────┬───────────────────────┘ │ └─────────────────────┼────────────────────────────────┘ ▼ ┌──────────────────────────────────────────────────────┐ │ Domain Layer │ │ ┌──────────────────────────────────────────┐ │ │ │ packages/core/src/domains/<domain>/ [NEW]│ │ │ │ ├── domain/ [NEW] │ │ │ │ ├── ports/ [NEW] │ │ │ │ ├── application/ [NEW] │ │ │ │ └── adapters/ [NEW] │ │ │ └──────────────────┬───────────────────────┘ │ └─────────────────────┼────────────────────────────────┘ ▼ ┌──────────────────────────────────────────────────────┐ │ Infrastructure Layer │ │ ┌─────────────┐ │ │ │ infra/db │ │ │ │ [MOD] │ │ │ └─────────────┘ │ └──────────────────────────────────────────────────────┘
Mark: `[NEW]`, `[MOD]`, or unmarked.
## Component Inventory
| Component | Package/App | Responsibility | New/Modified |
|-----------|-------------|---------------|--------------|
## Design Decisions
**MINIMUM: ≥ 1 decision with ADR-lite format.**
### Decision 1: <Title>
**Context:** Why needed.
**Options:**
| Option | Pros | Cons |
|--------|------|------|
**Decision:** Option X because <reasoning>.
**Consequences:** What follows.
# Interfaces
```yaml
interfaces:
- name: <InterfaceName>
type: http | queue | event | rpc | cron
definition: |
// TypeScript/Effect Schema definition
interfaces: is for runtime contracts and boundaries, not entities. Use:
http for routes and API endpointsqueue for async workflow, worker, or queue boundariesevent for published or consumed event contractsrpc for Effect services, internal service boundaries, adapters, and request/response style contracts that are not public HTTPcron for scheduled jobsEntities, value objects, and aggregate state belong in # Data Model or domain sections, not interfaces:.
| Method | Path | Request Schema | Response Schema | Auth | Permission | |--------|------|---------------|----------------|------|-----------|
import { Schema } from 'effect'
export const Create<X>Request = Schema.Struct({ /* fields */ })
export const Create<X>Response = Schema.Struct({ /* fields */ })
| Status | Error Code | Condition | Response Body |
|--------|-----------|-----------|--------------|
| 400 | VALIDATION_ERROR | Invalid request body | { error, details } |
| 401 | UNAUTHORIZED | Missing/expired token | { error } |
| 403 | FORBIDDEN | Insufficient permissions | { error } |
| 404 | NOT_FOUND | Resource doesn't exist | { error } |
| 409 | CONFLICT | Duplicate / state conflict | { error, details } |
export interface <Domain>Repository {
create(input: Create<X>Input): Effect.Effect<X, <Error>>
findById(id: string): Effect.Effect<X | null, <Error>>
findMany(filter: <Filter>): Effect.Effect<readonly X[], <Error>>
update(id: string, input: Update<X>Input): Effect.Effect<X, <Error>>
remove(id: string): Effect.Effect<void, <Error>>
}
export interface <Domain><Verb>EventPayload { /* fields */ }
export const <Domain><Verb>EventPayloadSchema = Schema.Struct({ /* fields */ })
CREATE TABLE <table_name> (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_<table>_<column> ON <table_name>(<column>);
ALTER TABLE <existing_table> ADD COLUMN <column> <type>;
export const <Table>Schema = Schema.Struct({ /* columns */ })
export const create<Table>Factory = (overrides?: Partial<Table>): Table => ({ /* defaults */ })
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ organizations │────<│ teams │────<│ <entity> │
│ │ 1:N │ │ 1:N │ │
└──────────────┘ └──────────────┘ └──────────────┘
MINIMUM: ≥ 5 invariants. If companion PRD exists, every must EARS req MUST map to an invariant.
invariants:
- id: INV-<SCOPE>-001
statement: <what must be true>
enforcement: <lint script | test | pgTAP>
traces_to: REQ-<SCOPE>-001 # link to PRD requirement if applicable
MINIMUM: ≥ 3 failure modes.
failure_modes:
- id: FM-<SCOPE>-001
trigger: <what causes failure>
impact: <user/system effect>
detection: <logs, metrics, alerts>
mitigation: <automatic response>
recovery: <human intervention>
MINIMUM: ≥ 5 entries. Every invariant MUST have a verification entry.
verification:
- invariant: INV-<SCOPE>-001
test_file: <path>
test_name: "description [INV-<SCOPE>-001]"
type: unit | integration | lint | pgtap
MINIMUM: ≥ 2 (happy path + at least one error path).
Client API Core DB Worker
│ │ │ │ │
│ POST /api/<x> │ │ │ │
│─────────────────▶│ │ │ │
│ │ validate + auth │ │ │
│ │ create<X>(input) │ │ │
│ │────────────────────▶│ │ │
│ │ │ BEGIN TXN │ │
│ │ │───────────────────▶│ │
│ │ │ INSERT + event │ │
│ │ │───────────────────▶│ │
│ │ │ COMMIT │ │
│ │ │───────────────────▶│ │
│ │◀────────────────────│ │ │
│ 201 Created │ │ │ │
│◀─────────────────│ │ │ poll + dispatch │
│ │ │ │◀────────────────────│
Client API
│ POST /api/<x> │
│─────────────────▶│
│ │ <failure point>
│ <status code> │
│◀─────────────────│
Integration tests are the primary verification mechanism and a HARD REQUIREMENT. Unit tests are recommended but secondary.
The testing strategy must be comprehensive. Cover:
HARD REQUIREMENT: ≥ 2 integration test files listed. Design docs MUST NOT be considered complete without integration tests.
| Test File | What It Covers | Invariants | |-----------|---------------|------------|
describe('<Domain> API', () => {
it('returns 401 for unauthenticated [INV-<SCOPE>-003]', async () => { /* ... */ })
it('creates resource with valid input', async () => { /* ... */ })
})
| Test File | What It Covers | Invariants | |-----------|---------------|------------|
describe('<Entity>', () => {
it('creates valid entity [INV-<SCOPE>-001]', () => { /* ... */ })
// @spec REQ-<SCOPE>-001
it('rejects invalid input', () => { /* ... */ })
})
| Test File | What It Covers | |-----------|---------------|
it('description [INV-<SCOPE>-001]', () => { ... }) // preferred
// @spec INV-<SCOPE>-001 // alternative
File: packages/infra/db/migrations/NNNN_<description>.sql
| Step | Action | Verification | |------|--------|-------------|
| Concern | Mitigation | Enforcement | |---------|-----------|-------------|
Phase 1: Domain Foundation
├── <specific file paths>
Phase 2: Infrastructure
├── <specific file paths>
Phase 3: Application Layer
├── <specific file paths>
Phase 4: API Layer
├── <specific file paths>
Phase 5: Worker (if domain events)
├── <specific file paths>
Phase 6: Quality Gates
├── pnpm lint && pnpm type-check && pnpm test && pnpm test:integration
├── tx spec discover --doc <name>
└── tx spec fci --doc <name>
## Step 4 — Self-Audit
Re-read the plan file and verify:
1. **Comprehensiveness check**: Read the plan file. For EVERY item (implementation steps, constraints, risks, decisions), confirm it has full technical detail in the design doc. The design doc must be detailed enough to implement from alone.
2. If PRD exists: every `must` EARS req has an invariant. Every invariant has a verification entry.
3. HARD: ≥2 integration test files (blocking requirement). SOFT: ≥1 unit test file (recommended).
4. Minimums met: ≥5 invariants, ≥3 failure modes, ≥5 verifications, ≥2 sequence diagrams, ≥1 decision.
5. Testing strategy is comprehensive: traceability, happy path, failure path, validation/auth, dependency failures, and data integrity are all covered where relevant.
5. No stubs, no empty tables, no "..." placeholders.
6. All diagrams complete.
7. Implementation sequence lists real file paths.
8. Verify plan file exists at the path in frontmatter and its content is consistent with the doc sections.
## Step 5 — Validate
```bash
tx spec lint
Treat schema and parser errors as blocking. Coverage-oriented warnings after generation, such as unlinked tasks or invariants without tests yet, should be surfaced separately from structural doc errors.
After filling and validating the doc, update the plan file at the plan: frontmatter path to reflect everything the design doc surfaced. The plan file must be the living source of truth — not a stale initial draft.
What to add to the plan file:
Read the current plan file, merge in the new information, and write it back. Preserve the plan's structure but ensure it now covers the full technical design.
tx spec discover --doc <name>
tx doc link <prd> <design> # if PRD exists
tx doc show <name>
tx spec gaps --doc <name>
specs/design/<name>.md).tx spec lint.# Plan summary and derived sections in this doc. If this doc's scope changes, update the plan file to stay consistent.development
Implement and verify design doc invariants by annotating tests and source code with [INV-*] / @spec tags, then driving tx spec coverage from BUILD toward HARDEN (100% FCI). Works with any design doc that has an invariants block.
data-ai
Link tasks to paired PRD/design specs, export all open work to markdown, and keep Ralph-style loops moving by creating tasks, subtasks, and dependency updates through tx primitives.
development
Refresh bundled tx Claude Code and Codex skills in a project from the canonical tx source without manual copy and paste.
development
Run Ralph against either the full repo queue or tasks linked to one design doc, with injected task/spec/queue context for Codex or Claude runtimes.