lexler

event-modeling

Designs systems using Event Modeling.

lexler 215 59 Updated 4mo ago

Resources

3
GitHub

Install

npx skillscat add lexler/skill-factory/event-modeling

Install via the SkillsCat registry.

SKILL.md

STARTER_CHARACTER = ๐Ÿ—บ๏ธ

What Event Modeling Produces

A set of vertical slices that fully describe a system's behavior. Each slice is independently implementable and testable. The model uses business language throughout โ€” no infrastructure or technical terms.

                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                    โ”‚          Event Model                โ”‚
                    โ”‚                                     โ”‚
                    โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”       โ”‚
                    โ”‚  โ”‚  Slice 1  โ”‚  โ”‚  Slice 2  โ”‚  ...  โ”‚
                    โ”‚  โ”‚ STATE_    โ”‚  โ”‚ STATE_    โ”‚       โ”‚
                    โ”‚  โ”‚ CHANGE    โ”‚  โ”‚ VIEW      โ”‚       โ”‚
                    โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜       โ”‚
                    โ”‚         โ”‚              โ–ฒ            โ”‚
                    โ”‚         โ”‚  (events)    โ”‚            โ”‚
                    โ”‚         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜            โ”‚
                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Slice Types

Three types. Every behavior in the system fits one:

STATE_CHANGE โ€” user does something

  • Screen โ†’ Command โ†’ Event
  • Command produces one or more events
  • May have error events for failure paths

STATE_VIEW โ€” system shows something

  • Events โ†’ Read Model โ†’ Screen
  • Read model aggregates data from one or more events

AUTOMATION โ€” system reacts to something

  • Event โ†’ Processor โ†’ Command โ†’ Event
  • Background process, no user interaction

See references/slice-types.md for element rules, dependency patterns, and naming conventions.

Conversational Design Process

Work with the user through these phases. Move at the user's pace โ€” they might want to go deep on one slice before seeing the full picture.

Phase 1: Understand the Domain

Identify aggregates (core business entities), actors, and high-level use cases. Ask about the business processes, not technical implementation.

Phase 2: High-Level Model

Draft all slices without field details. Show the flow between them โ€” which events feed which read models, which screens lead to which commands. This is the "map" of the system.

Format as a markdown document with one section per slice. Include slice type, aggregate, elements, and how slices connect.

Phase 3: Slice Detail

Walk through one slice at a time. For each:

  • Define fields with types and example values
  • Identify business rules (not simple validations โ€” real domain rules)
  • Write specifications as Given/When/Then scenarios

Phase 4: Executable Specifications

Turn specifications into approval fixture files using the bdd-with-approvals skill. That skill teaches how to:

  • Design scannable fixture formats adapted to the domain
  • Structure input/output for human validation
  • Build parsers and formatters

Read that skill when it's time to design fixtures. The event model specs (Given events / When command / Then events) map naturally to the approved fixture pattern.

Analyzing Existing Code

When working with an existing codebase instead of greenfield:

  • Read the code to extract domain concepts
  • Map existing operations to slice types (writes โ†’ STATE_CHANGE, reads โ†’ STATE_VIEW, background โ†’ AUTOMATION)
  • Put code references (class names, packages) in element descriptions
  • Extract specs from unit tests and comments

Output Format

Produce markdown, not JSON. Design for human readability โ€” someone should look at the model and understand the system.

Write model artifacts to files. Ask the user where they want them (e.g., docs/event-model.md). Update the files as the model evolves through conversation.

High-Level Model

One document showing all slices and their relationships:

# [System Name] Event Model

## Aggregates
- Owner โ€” pet owners who use the clinic
- Pet โ€” animals registered to owners

## Slices

### Register Owner [STATE_CHANGE]
Aggregate: Owner
Screen: Owner Registration Form
Command: Register Owner โ†’ Event: Owner Registered
Error: โ†’ Owner Registration Failed

### View Owner Profile [STATE_VIEW]
Aggregate: Owner
Events: Owner Registered, Pet Registered โ†’ Read Model: Owner Profile
Screen: Owner Profile

### Notify Vet of New Patient [AUTOMATION]
Trigger: Pet Registered โ†’ Processor: New Patient Notifier
Command: Send Notification โ†’ Event: Vet Notified

Detailed Slice

Per-slice detail includes fields and specifications:

## Register Owner [STATE_CHANGE]
Aggregate: Owner

### Command: Register Owner
  firstName: String โ€” "George"
  lastName: String โ€” "Franklin"
  address: String โ€” "110 W. Liberty St."
  city: String โ€” "Madison"
  telephone: String โ€” "6085551023"

### Event: Owner Registered
  ownerId: UUID โ€” <generated>
  firstName: String โ€” "George"
  lastName: String โ€” "Franklin"
  address: String โ€” "110 W. Liberty St."
  city: String โ€” "Madison"
  telephone: String โ€” "6085551023"

### Event: Owner Registration Failed
  errors: Map โ€” {"lastName": "required"}

### Specifications

#### Successfully register with valid data
Given: (no prior state)
When: Register Owner
  firstName: George, lastName: Franklin
  address: 110 W. Liberty St., city: Madison
  telephone: 6085551023
Then: Owner Registered
  ownerId: <generated>, firstName: George, lastName: Franklin

#### Fail when required fields missing
Given: (no prior state)
When: Register Owner
  firstName: George, city: Madison
Then: Owner Registration Failed
  errors: {address: required, telephone: required}

#### Business rules
- All fields mandatory: firstName, lastName, address, city, telephone
- Telephone must be numeric, max 10 digits

These are defaults. Adapt the format to the domain โ€” what matters is that a person can scan it and quickly validate correctness.

Anti-Patterns

  • Technical language in element names ("insertOwnerRecord" โ†’ "Register Owner")
  • Skipping STATE_VIEW slices โ€” every query/display is a slice
  • Circular dependencies between elements
  • Specs that test simple validation ("must be a number") instead of business rules
  • Jumping to fixture format before the model is understood
  • Combining multiple commands in one slice โ€” one command per STATE_CHANGE

See Also

  • For executable test specifications: invoke the bdd-with-approvals skill
  • For approval testing mechanics: invoke the approval-tests skill