AgentSkillsCN

cqrs-document

以文档为先,通过对话驱动CQRS设计。当设计的系统中,用户所看到的文档(视图)会由命令持续更新时,可采用此方法。该方法可直接输出SQL迁移脚本与TypeScript类型定义——无需中间DSL。适用于围绕文档、命令、实体、CQRS、Seiro协议,以及“用户究竟看到什么”等系统设计相关话题的讨论。

SKILL.md
--- frontmatter
name: cqrs-document
description: Document-first CQRS design through conversation. Use when designing systems where users see documents (views) that are kept up to date by commands. Outputs SQL migrations and TypeScript types directly - no intermediate DSL. Triggers on discussions about documents, commands, entities, CQRS, Seiro protocol, or system design conversations that involve "what does the user see" questions.

Document-First CQRS Design

Design systems by starting with what the user sees (the document), then deriving entities and commands.

Core Principle

A document is a composition of entity views. Commands exist to transition the document from one valid state to another. Entities are derived from what's needed to support the documents.

Conversation Workflow

1. Establish the Document

Ask: "What does the user see?"

Capture the shape:

code
Document Venue {
  id, name, location
  sites: [Site { id, name, position, dimensions, area_id? }]
  areas: [Area { id, name, parent_id? }]
}
  • Nesting implies joins
  • ? means optional/nullable
  • [] means array/list
  • Use entity names, subset fields for views

2. Define Commands

Commands that transition the document:

code
commands {
  save_venue(name, location, id?)
  delete_venue(id)
  save_site(venue_id, name, position, dimensions, area_id?, id?)
  delete_site(id)
}

Conventions:

  • save_* for create/update (id absent = create, id present = update)
  • Required parameters first, optional id? last
  • Commands return { id } on success
  • delete_* with cascade logic documented

3. Derive Entities

Extract the minimal tables:

code
venues (id, name, location)
sites (id, venue_id FK, name, position, dimensions, area_id?)
areas (id, venue_id FK, name, parent_id?)

4. Output Code

Once document is agreed, write directly:

SQL Migration - Tables, constraints, command functions with pg_notify TypeScript Types - Document shapes, command/query types for Seiro

Output Conventions

SQL Command Functions

sql
CREATE FUNCTION cmd_entity_save(
  p_required_field text,
  p_optional_field text DEFAULT NULL,
  p_id int DEFAULT NULL
) RETURNS jsonb AS $$
DECLARE
  v_entity entities%ROWTYPE;
BEGIN
  IF p_id IS NULL THEN
    INSERT INTO entities (...) VALUES (...) RETURNING * INTO v_entity;
  ELSE
    UPDATE entities SET ... WHERE id = p_id RETURNING * INTO v_entity;
  END IF;
  
  PERFORM pg_notify('entity_saved', jsonb_build_object(...));
  RETURN jsonb_build_object('id', v_entity.id);
END;
$$ LANGUAGE plpgsql;

SQL Delete with Cascade

sql
CREATE FUNCTION cmd_entity_delete(p_id int) RETURNS void AS $$
BEGIN
  -- Nullify references before delete
  UPDATE children SET entity_id = NULL WHERE entity_id = p_id;
  DELETE FROM entities WHERE id = p_id;
  PERFORM pg_notify('entity_deleted', jsonb_build_object('id', p_id));
END;
$$ LANGUAGE plpgsql;

TypeScript Document Type

typescript
export type VenueDocument = {
  id: number
  name: string
  location: string
  sites: Site[]
  areas: Area[]
}

export type Site = {
  id: number
  name: string
  position: { x: number, y: number }
  dimensions: { w: number, h: number }
  area_id: number | null
}

What NOT To Do

  • No intermediate DSL or spec files
  • No compiler or code generator to maintain
  • No UML diagrams
  • No abstract entity modelling before documents are clear

Alternative: seiro model

For larger systems where you want to visualise the complete domain (entities, documents, commands, events, sequences), use seiro model:

bash
bunx seiro model add entity Product
bunx seiro model add document Catalogue
bunx seiro model serve  # view diagrams
bunx seiro model export # get JSON for code generation

Then use the model-generate skill to create the application from the export.

Use this skill (cqrs-document) for conversational design. Use seiro model when you need the full picture and consistency checking across a larger domain.

Iteration Pattern

When requirements change:

  1. Update the document shape in conversation
  2. Identify entity/command changes
  3. Write migration SQL
  4. Update TypeScript types

The code is the spec. PostgreSQL enforces it. TypeScript checks it.