@eventmodelers/cli 1.0.36 → 1.0.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/package.json +1 -1
  2. package/shared/skills/learn-eventmodelers-api/SKILL.md +22 -13
  3. package/stacks/modeling-kit/templates/.claude/skills/add-next-slice/SKILL.md +2 -23
  4. package/stacks/modeling-kit/templates/.claude/skills/add-next-slice/references/api-fallback.md +11 -0
  5. package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/SKILL.md +6 -57
  6. package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/references/api-fallback.md +68 -0
  7. package/stacks/modeling-kit/templates/.claude/skills/attributes/SKILL.md +4 -61
  8. package/stacks/modeling-kit/templates/.claude/skills/attributes/references/api-fallback.md +39 -0
  9. package/stacks/modeling-kit/templates/.claude/skills/discover-storyboard/SKILL.md +9 -53
  10. package/stacks/modeling-kit/templates/.claude/skills/discover-storyboard/references/api-fallback.md +63 -0
  11. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-applying-conways-law/SKILL.md +12 -380
  12. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-applying-conways-law/references/examples.md +329 -0
  13. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/SKILL.md +45 -290
  14. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/references/api-fallback.md +97 -0
  15. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/references/examples.md +35 -0
  16. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/SKILL.md +15 -410
  17. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/references/api-fallback.md +22 -0
  18. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/references/examples.md +397 -0
  19. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-core-rules/SKILL.md +182 -0
  20. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-automation-chains/SKILL.md +148 -0
  21. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-automation-chains/references/api-fallback.md +21 -0
  22. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/SKILL.md +48 -448
  23. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/references/examples.md +167 -0
  24. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +31 -380
  25. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/references/api-fallback.md +31 -0
  26. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/references/examples.md +216 -0
  27. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/SKILL.md +33 -393
  28. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/references/api-fallback.md +79 -0
  29. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/references/examples.md +282 -0
  30. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md +54 -454
  31. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/references/api-fallback.md +67 -0
  32. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/references/examples.md +273 -0
  33. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-interview-protocol/SKILL.md +31 -0
  34. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/SKILL.md +37 -184
  35. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/domain-patterns.md +58 -99
  36. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/patterns.md +82 -163
  37. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/SKILL.md +86 -78
  38. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/references/api-fallback.md +51 -0
  39. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-plotting-events/SKILL.md +5 -5
  40. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-plotting-events/references/api-fallback.md +10 -0
  41. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/SKILL.md +22 -51
  42. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/api-fallback.md +41 -0
  43. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/examples.md +12 -9
  44. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/patterns.md +1 -10
  45. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/SKILL.md +29 -382
  46. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/references/api-fallback.md +77 -0
  47. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/references/examples.md +271 -0
  48. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-translating-external-events/SKILL.md +12 -349
  49. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-translating-external-events/references/examples.md +306 -0
  50. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/SKILL.md +69 -107
  51. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/references/api-fallback.md +14 -0
  52. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models-checklist/SKILL.md +75 -160
  53. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models-checklist/references/api-fallback.md +14 -0
  54. package/stacks/modeling-kit/templates/.claude/skills/examples/SKILL.md +3 -110
  55. package/stacks/modeling-kit/templates/.claude/skills/examples/references/api-fallback.md +118 -0
  56. package/stacks/modeling-kit/templates/.claude/skills/handle-comment/SKILL.md +5 -25
  57. package/stacks/modeling-kit/templates/.claude/skills/handle-comment/references/api-fallback.md +35 -0
  58. package/stacks/modeling-kit/templates/.claude/skills/html-screen/SKILL.md +9 -44
  59. package/stacks/modeling-kit/templates/.claude/skills/html-screen/references/api-fallback.md +51 -0
  60. package/stacks/modeling-kit/templates/.claude/skills/place-element/SKILL.md +34 -180
  61. package/stacks/modeling-kit/templates/.claude/skills/place-element/references/api-fallback.md +203 -0
  62. package/stacks/modeling-kit/templates/.claude/skills/storyboard/SKILL.md +14 -81
  63. package/stacks/modeling-kit/templates/.claude/skills/storyboard/references/api-fallback.md +74 -0
  64. package/stacks/modeling-kit/templates/.claude/skills/storyboard-screen/SKILL.md +4 -45
  65. package/stacks/modeling-kit/templates/.claude/skills/storyboard-screen/references/api-fallback.md +44 -0
  66. package/stacks/modeling-kit/templates/.claude/skills/timeline/SKILL.md +19 -88
  67. package/stacks/modeling-kit/templates/.claude/skills/timeline/references/api-fallback.md +91 -0
  68. package/stacks/modeling-kit/templates/.claude/skills/update-prompt-status/SKILL.md +1 -9
  69. package/stacks/modeling-kit/templates/.claude/skills/update-prompt-status/references/api-fallback.md +14 -0
  70. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-integrating-legacy-systems/SKILL.md +0 -674
  71. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/snapshotting.md +0 -204
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: eventmodeling-designing-event-models
3
- description: "Designs event-sourced domain models. Maps business processes to immutable events and state projections. Events are the source of truth; state is derived from events for command validation. Use when designing event streaming architectures from domain analysis. Do not use for: brainstorming events from scratch (use eventmodeling-brainstorming-events), optimizing stream sizing or snapshotting (use eventmodeling-optimizing-stream-design), or translating external system events (use eventmodeling-translating-external-events)."
3
+ description: "Designs the event model for a business process maps Commands, Events, and Read Models with clear causality. Events are business facts; Read Models are projections built from them. Use when designing the Command/Event/Read-Model structure from domain analysis. Do not use for: brainstorming events from scratch (use eventmodeling-brainstorming-events), or checking whether an event belongs to the right entity/timeline (use eventmodeling-optimizing-stream-design)."
4
4
  allowed-tools:
5
5
  - AskUserQuestion
6
6
  - Write
@@ -11,487 +11,87 @@ allowed-tools:
11
11
 
12
12
  > **Before doing anything else**, invoke the `connect` skill — if not already connected — to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Do not proceed until it has completed. Consult `learn-eventmodelers-api` only if you need to look up a specific endpoint or field this file doesn't cover — don't load it eagerly.
13
13
 
14
- ## Interview Phase (Optional)
15
-
16
- **When to Interview**: Skip if the user has specified: stream identity strategy, command-specific state needs, and read model requirements. Interview when stream boundaries or state design are unclear.
17
-
18
- **Interview Strategy**: Establish stream identity and per-command state boundaries before designing. Ambiguous boundaries are the primary cause of the DDD aggregate anti-pattern appearing in event-sourced models.
19
-
20
- ### Critical Questions
21
-
22
- 1. **Stream Identity** (Impact: Determines how events are grouped into streams)
23
- - Question: "What's the entity that owns events? (e.g., orderId, reviewId, customerId) What's the lifetime? Single transaction or years?"
24
- - Why it matters: Wrong stream identity causes design problems; correct identity keeps streams appropriately scoped
25
- - Follow-up triggers: If multiple candidates → ask "Which entity's identity would you use to load events for a single command decision?"
26
-
27
- 2. **Minimal State vs Bundled State** (Impact: Prevents DDD aggregate anti-pattern)
28
- - Question: "Will different commands need different state? Or does every command need the same full state?"
29
- - Why it matters: Each command should have minimal, command-specific state—not bundled DDD aggregates
30
- - Follow-up triggers: If "same full state" → walk through two commands and ask what each actually reads during validation
31
-
32
- ### Interview Flow
33
-
34
- **Conditional Entry**:
35
- ```text
36
- If user has provided:
37
- - Stream identity (which entity ID anchors the stream)
38
- - AND at least two commands with explicitly different state needs documented
39
- - AND read model requirements (what queries the UI or processors make)
40
-
41
- Then: Skip interview, proceed directly to design
42
-
43
- Else: Conduct interview
44
- ```
45
-
46
- **Phase 1: Stream Boundaries** (Question 1)
47
- - Confirm which entity anchors the stream
48
- - Establish stream lifetime expectations
49
- - Identify whether multiple candidate roots exist and resolve them
50
-
51
- **Phase 2: State Design** (Question 2)
52
- - Confirm per-command state isolation
53
- - Identify whether DDD aggregate thinking is present upfront
54
- - Establish minimal state shapes for at least two commands
55
-
56
- ### Capturing Interview Findings
57
-
58
- Append findings to the project's event modeling file:
59
-
60
- **File**: `.trogonai/interviews/[project-name]/EVENTMODELING.md`
61
-
62
- Use Write tool to add/update this section:
63
-
64
- ```markdown
65
- ## Designing Event Models (eventmodeling-designing-event-models)
66
-
67
- ### Stream Identity
68
- [From Q1: Which entity? What identity key? Lifetime?]
69
-
70
- ### Per-Command State Decisions
71
- [From Q2: Which commands need different state? Initial minimal state shapes?]
72
-
73
- ### Design Decisions
74
- - Stream root: [entity name] identified by [id field]
75
- - State isolation: [confirmed / DDD pattern caught and corrected]
76
- ```
77
-
78
- Update Interview Trail:
79
- ```markdown
80
- | Design | eventmodeling-designing-event-models | Done | Stream identity, per-command state shapes |
81
- ```
82
-
83
- ---
84
-
85
- ## Core Architectural Rule
86
-
87
- **NEVER use a "DDD Aggregate Root" (bundled state) for command validation** Every command handler has its own minimal state projection. What DDD calls an "aggregate root" is actually a **read model**, not command-validation state.
88
-
89
- ```text
90
- WRONG: Using DDD Aggregate as command state
91
- OrderAggregate { orderId, customerId, items[], total, status, paymentId, address, shippedAt, cancelledAt, ... }
92
- ↑ This is a READ MODEL, not command state
93
- ↓ NEVER use for command validation
94
- handleConfirmOrder(OrderAggregate)
95
- handleShipOrder(OrderAggregate)
96
- handleCancelOrder(OrderAggregate)
97
-
98
- CORRECT: Minimal state per command
99
- ConfirmOrderState { status, orderId }
100
-
101
- handleConfirmOrder(ConfirmOrderState)
102
-
103
- ShipOrderState { status, orderId, paymentId }
104
-
105
- handleShipOrder(ShipOrderState)
106
-
107
- CancelOrderState { status, orderId, createdAt }
108
-
109
- handleCancelOrder(CancelOrderState)
110
-
111
- OrderSummaryView { orderId, customerId, items[], total, status, paymentId, ... }
112
- ↑ This is for UI queries, NOT command validation
113
- ```
14
+ This step applies the shared element rules in **`eventmodeling-core-rules`** — read it once per session if you haven't already; it defines what a COMMAND/EVENT/READMODEL/SCREEN/AUTOMATION is, how each is named, and the anti-patterns to reject, so this step doesn't restate them.
114
15
 
115
16
  ## Purpose
116
- Converts domain analysis into the event sourcing architecture pattern:
117
17
 
118
- **UI/Processor** **Command** [Command State Read Model] → **Event** → **Query Read Models** - **UI/Processor**: Entry points that trigger intent
119
- - **Command**: Intent data (can be rejected)
120
- - **Stream Root**: Logical grouping of immutable events (NOT a DDD aggregate bundle)
121
- - **Command State Read Model**: Minimal projection derived from events, optimized for this specific command's validation. Each command gets its own read model interface. Different commands = different shapes. (Categorized as "Command State" for semantic clarity)
122
- - **Event**: Result of successful command (immutable fact: command data + implicit context)
123
- - **Query Read Models**: Rich projections of events optimized for UI/Processor queries. Separate from command state. (Categorized as "Query Models" for semantic clarity)
18
+ Converts domain analysis into the event modeling structure:
124
19
 
125
- ## Workflow
20
+ **UI/Processor** → **Command** → **Event** → **Read Model** → **UI/Processor**
126
21
 
127
- Given a domain analysis, design a complete event-sourced model:
22
+ - **UI/Processor**: entry points that trigger intent
23
+ - **Command**: business intent, expressed in business language, can be rejected
24
+ - **Event**: a business fact — the result of a successful command
25
+ - **Read Model**: a projection of events, shaped for a specific query need
128
26
 
129
- ### 1. Design Event Streams
130
- Events are the immutable source of truth. Each stream holds facts about one entity:
131
- - **Stream Name**: Entity type + identity (Order:order-123)
132
- - **Event Type**: What changed? (past tense: Created, Confirmed, Shipped)
133
- - **Event Data**: Combines command input + implicit stream state facts
134
- - **Causality**: Triggered by which command?
27
+ ## Workflow
135
28
 
136
- Format:
137
- ```text
138
- Stream: Order:order-123
29
+ Given a domain analysis, design the event model:
139
30
 
140
- Events (chronological):
141
- 1. OrderCreated
142
- Triggered by: CreateOrder command
143
- Data: customerId, items[], total, shippingAddress, createdAt
144
- (from command: customerId, items[], shippingAddress)
145
- (implicit: total calculated from items)
31
+ ### 1. Design Events
146
32
 
147
- 2. OrderConfirmed
148
- Triggered by: ConfirmOrder command
149
- Data: paymentId, confirmedAt
150
- (from command: paymentId)
151
- (implicit: orderId from stream, previous status verified)
33
+ Events are business facts, not technical occurrences:
34
+ - **Event Type**: what changed, in past tense business language (Created, Confirmed, Shipped)
35
+ - **Event Data**: the business fields, noting which came directly from the triggering command versus which are implicit context (e.g. a calculated total, or the entity's identity)
36
+ - **Causality**: which command triggered it
152
37
 
153
- 3. OrderShipped
154
- Triggered by: ShipOrder command
155
- Data: shipmentId, shippedAt
156
- (from command: shipmentId)
157
- (implicit: orderId, confirmed status verified)
158
- ```
38
+ Document each entity's events as a chronological list, giving each event's triggering command and its data. A full worked example (an Order) is in `references/examples.md`.
159
39
 
160
40
  **Key Rules**:
161
- - Events are **immutable facts** from successful commands
162
- - Event data = command input + implicit stream state context
163
- - Stream identity is explicit (Order:order-123)
164
- - Event order matters for state reconstruction
165
- - Never modify or delete events
166
- - Events only exist if command succeeded
167
-
168
- ### 2. Design Command State Read Models (Minimal Per-Command)
169
-
170
- **Critical Rule: Each command must have its own read model (command state). NEVER share read models between commands.** **Naming Convention (for Automation)**:
171
- - `[CommandName]State` = Implemented command state read model
172
- - `[CommandName]StateToDo` = Planned command state read model (marked for implementation)
173
-
174
- Examples:
175
- - `PublishReviewState` = implemented
176
- - `EditReviewStateToDo` = planned, needs implementation
177
- - `SellerRespondState` = implemented
178
-
179
- **Semantic Categorization**: These are read models, but categorized as "Command State" based on their purpose (command validation, not UI queries).
180
-
181
- Command state read models are **derived** from events and **minimal**:
182
- - Read only events needed for a specific command's decision
183
- - Build state by replaying only relevant events
184
- - **ENFORCEMENT**: Different commands = different read model interfaces. Period.
185
- - Each command handler defines what state projection it needs (and ONLY what it needs)
186
- - Projection can be regenerated from events at any time
187
-
188
- Example for Order stream with separate command state read model for EACH command:
189
-
190
- ```text
191
- ## ConfirmOrder Command (IMPLEMENTED)
192
- State interface: ConfirmOrderState { status, orderId }
193
- Builder: buildConfirmOrderState(events)
194
- Naming: [CommandName]State = implemented
195
- - OrderCreated event → Set status='Draft'
196
- - OrderConfirmed event → Set status='Confirmed'
197
- (SKIP: items, total, shipping - not needed for this command)
198
-
199
- ## ShipOrder Command (IMPLEMENTED)
200
- State interface: ShipOrderState { status, orderId, paymentId }
201
- Builder: buildShipOrderState(events)
202
- Naming: [CommandName]State = implemented
203
- (DIFFERENT from ConfirmOrderState)
204
- - OrderCreated event → (skip)
205
- - OrderConfirmed event → Set status='Confirmed', set paymentId
206
- - OrderShipped event → Set status='Shipped'
207
-
208
- ## CancelOrder Command (PLANNED - NOT IMPLEMENTED)
209
- State interface: CancelOrderStateToDo { status, orderId, createdAt }
210
- Builder: buildCancelOrderStateToDo(events) [STUB - TODO]
211
- Naming: [CommandName]StateToDo = planned, needs implementation
212
- (DIFFERENT from both above)
213
- - OrderCreated event → Set status='Draft', createdAt
214
- - OrderCancelled event → Set status='Cancelled'
215
- ```
216
-
217
- **Enforcement Rule**:
218
- - ConfirmOrderState used ONLY by handleConfirmOrder
219
- - ShipOrderState used ONLY by handleShipOrder
220
- - NEVER share state between commands
221
- - NEVER create a single "OrderState" for all Order commands
41
+ - Events are immutable business facts
42
+ - Events use past tense, business language
43
+ - Event order matters it tells the story
44
+ - Never modify or delete an event once it exists
45
+ - Events only exist if the triggering command succeeded
222
46
 
223
- This is **NOT** a full aggregate state bundle—it's minimal, command-specific state access.
47
+ ### 2. Design Commands
224
48
 
225
- ### 3. Design Commands
226
- Commands are **intent data from UI or Processor**:
227
- - Represent what user/system wants to do
49
+ Commands are business intent from a UI or Processor:
50
+ - Represent what a user or system wants to do
228
51
  - Can be rejected (validation failure)
229
- - Only UI or Processor can issue commands
230
- - Load current stream state for validation
52
+ - Only a UI or Processor can issue a command
231
53
  - Produce events if valid, or reject if invalid
232
54
 
233
- Format:
234
- ```text
235
- Command: ConfirmOrder
236
- Source: UI or Processor (only these can issue)
237
- Input: orderId, paymentId
238
-
239
- Processing:
240
- 1. Load current state from Order:orderId stream
241
- 2. Validate preconditions:
242
- - state.status === 'Draft' (reject: already confirmed)
243
- - paymentId is valid (reject: invalid payment)
244
- 3. If all valid:
245
- - Produce: OrderConfirmed event
246
- - Data: paymentId, confirmedAt
247
- - Implicit: orderId (from stream), previous status (from state)
248
- 4. If any validation fails:
249
- - Reject: return error (no event created)
250
-
251
- Outcomes:
252
- Success: OrderConfirmed event appended to stream
253
- Rejection: Error returned, no event created
254
- ```
55
+ Document each command's source, its input fields, the preconditions it's checked against, the event(s) it produces on success (noting which data comes from the command versus implicit context), and its rejection outcomes. A full worked example (ConfirmOrder) is in `references/examples.md`.
255
56
 
256
57
  **Key Rules**:
257
- - Only UI or Processor can issue commands (entry points)
58
+ - Only a UI or Processor can issue commands (entry points)
258
59
  - One command per UI/Processor action
259
- - Commands validate against stream state
260
60
  - Successful command → Event(s) created
261
61
  - Failed validation → Command rejected, no event
262
- - Commands are synchronous decision logic (pure)
263
-
264
- ### 4. Design Read Models
265
- Read models are **projections of events for UI/Processor queries**:
266
- - Built from events (only source is events)
267
- - Optimized for specific query patterns
268
- - Consumed by UI or Processor (for display/decision)
269
- - Can be regenerated from events anytime
270
-
271
- Format:
272
- ```text
273
- ReadModel: OrderSummaryView
274
- Purpose: UI displays customer order list, Processor checks order status
275
-
276
- Subscribed to events:
277
- - OrderCreated
278
- - OrderConfirmed
279
- - OrderShipped
280
- - OrderCancelled
281
-
282
- Data (optimized for queries):
283
- {
284
- orderId: string
285
- customerId: string
286
- total: number
287
- status: string
288
- createdAt: Date
289
- confirmedAt?: Date
290
- shippedAt?: Date
291
- }
292
62
 
293
- Update from events:
294
- - OrderCreated → Insert row (id, customer, total, status='Draft')
295
- - OrderConfirmed → Update status='Confirmed', set confirmedAt
296
- - OrderShipped → Update status='Shipped', set shippedAt
297
- - OrderCancelled → Update status='Cancelled'
63
+ ### 3. Design Read Models
298
64
 
299
- Consumed by:
300
- - UI: displays list of orders
301
- - Processor: checks if order can be shipped
302
- ```
65
+ Read models are projections of events, built for UI/Processor queries:
66
+ - Built from events (their only source)
67
+ - Optimized for a specific query pattern
68
+ - Consumed by UI (for display) or Processor (for a decision)
69
+ - Can be regenerated from events at any time
303
70
 
304
- ### 5. Document Event Causality
305
- Show how events relate to each other:
71
+ Document each read model's purpose, which events it subscribes to, its query-shaped data, how each subscribed event updates that data, and who consumes it. A full worked example (OrderSummaryView) is in `references/examples.md`.
306
72
 
307
- ```text
308
- Command Flow:
309
- CreateOrder command
310
- → OrderCreated event
311
- ↓ (may trigger external process)
312
- ConfirmOrder command (reads OrderCreated state)
313
- → OrderConfirmed event
314
- ↓ (may trigger)
315
- ShipOrder command (reads OrderCreated + OrderConfirmed state)
316
- → OrderShipped event
317
- ```
73
+ ### 4. Document Event Causality
318
74
 
319
- ### 6. Document State Transitions
320
- Show valid state transitions:
75
+ Trace the causal chain from the first command through the events and downstream commands it can trigger, showing how a later command's decision depends on events produced earlier. A full worked example (an Order create→confirm→ship chain) is in `references/examples.md`.
321
76
 
322
- ```text
323
- Order Stream State Transitions:
77
+ ### 5. Document State Transitions
324
78
 
325
- Initial state: (empty stream)
326
-
327
- CreateOrder → OrderCreated
328
-
329
- State: Draft
330
-
331
- Draft state:
332
- → ConfirmOrder → OrderConfirmed → State: Confirmed
333
- → CancelOrder → OrderCancelled → State: Cancelled
334
-
335
- Confirmed state:
336
- → ShipOrder → OrderShipped → State: Shipped
337
- → CancelOrder (rejected - already confirmed)
338
-
339
- Shipped state:
340
- → No more transitions allowed
341
- ```
79
+ Map the valid states a process can be in, which command causes which transition, and which transitions are invalid from a given state (e.g. cancelling an already-shipped order), ending at any terminal states. A full worked example (Order transitions) is in `references/examples.md`.
342
80
 
343
81
  ### Output Format
344
82
 
345
- Present complete model as:
346
-
347
- ```markdown
348
- # Event Model: [Domain]
349
-
350
- ## Event Streams
351
-
352
- ### Stream: Order
353
-
354
- **Identity**: orderId
355
-
356
- **Events**:
357
- - OrderCreated: Initial event creating the order
358
- Data: customerId, items[], total, shippingAddress
359
-
360
- - OrderConfirmed: Payment confirmed
361
- Data: paymentId, confirmedAt
362
-
363
- - OrderShipped: Order shipped
364
- Data: shipmentId, shippedAt
365
-
366
- - OrderCancelled: Order cancelled
367
- Data: cancelledAt, reason
368
-
369
- **State Projection (Human Example)**:
370
- For the ConfirmOrder command, we need minimal state:
371
- ```text
372
- ConfirmOrderState:
373
- - orderId: 'order-123'
374
- - status: 'Draft'
375
- ```
376
-
377
- For the ShipOrder command, we need different data:
378
- ```text
379
- ShipOrderState:
380
- - orderId: 'order-123'
381
- - status: 'Confirmed'
382
- - paymentId: 'payment-456'
383
- ```
384
-
385
- ---
386
-
387
- ## Commands
388
-
389
- ### Command: CreateOrder
390
- - Input: customerId, items[], shippingAddress
391
- - Validation: Items valid, customerId exists
392
- - Events produced: OrderCreated
393
- - Possible outcomes: Success (OrderCreated) or Validation error
394
-
395
- ### Command: ConfirmOrder
396
- - Input: orderId, paymentId
397
- - Validation: Order in Draft status, payment validated
398
- - Events produced: OrderConfirmed
399
- - Possible outcomes: Success or "Already confirmed" error
400
-
401
- ---
402
-
403
- ## Read Models (Optional)
404
-
405
- ### ReadModel: OrderSummaryView
406
- - Purpose: Quick lookup of order status
407
- - Events: OrderCreated, OrderConfirmed, OrderShipped, OrderCancelled
408
- - Queries served: GetOrder(orderId), ListOrdersByCustomer(customerId)
409
-
410
- ---
411
-
412
- ## Implementation Notes
413
- - All state is derived from events
414
- - Commands validate against derived state
415
- - No transaction across streams
416
- - Events are source of truth
417
- - Read models can be rebuilt from events
418
- ```
419
-
420
- ## Key Event Sourcing Principles
421
-
422
- 1. **Events are Facts**: Events describe what happened, not what might happen
423
- 2. **Immutable Event Log**: Events are appended, never modified
424
- 3. **State is Minimal and Command-Driven**: State is built by replaying events, but ONLY for what a specific command needs to validate. Not all stream fields are needed for all commands.
425
- 4. **Not DDD Aggregates**: Stream roots group events logically, but aren't bundles of related data like DDD aggregates. State is determined per-command, not designed upfront for the whole stream.
426
- 5. **Commands are Pure**: No side effects, just decision logic against minimal state
427
- 6. **Read Models are Separate**: Read models (projections) are separate from command-validation state. Read models can have rich data; command state stays minimal.
428
- 7. **Event Causality**: Commands → [minimal state] → Events → [read models]
429
-
430
- ## Design Patterns
431
-
432
- ### Compensation Pattern
433
- Handle errors by appending compensation events:
434
- ```text
435
- Command: ProcessPayment failed
436
- → PaymentFailed event
437
- (triggered by external error)
438
- → OrderCancelled event (compensation)
439
- (or retry logic)
440
- ```
441
-
442
- ### Temporal Queries
443
- Answer "what was the state at time T?":
444
- ```text
445
- Replay events up to timestamp T
446
- → Get historical state
447
- ```
448
-
449
- ## Best Practices for Event Model Design
450
-
451
- ### 1. Design Minimal State Per Command
452
- Each command handler only loads the state it needs:
453
- - "LoadOrderState loads { id, items, total, shipping, customer, payment, status, ... }"
454
- - "ConfirmOrderState loads { status, orderId }"
455
- - "ShipOrderState loads { status, orderId, paymentConfirmed }"
456
-
457
- ### 2. Separate Command State from Query Models
458
- Keep command-validation state and read models strictly separate:
459
- - **Command State** (minimal): Used by handlers to validate commands
460
- - **Query Models** (rich): Used by UI/Processor to display/query data
461
- - Never share between them
462
-
463
- ### 3. Name State Interfaces by Command
464
- Use the pattern `[CommandName]State` to make the relationship explicit:
465
- - `PublishReviewState` for PublishReview command
466
- - `EditReviewState` for EditReview command
467
- - `ReviewState` (ambiguous - which command?)
468
-
469
- ### 4. Document State Transitions Clearly
470
- Show what state changes trigger what commands:
471
- - Include initial state
472
- - Show all valid transitions
473
- - Mark impossible transitions (and why)
474
- - Document rejection conditions
83
+ Present the complete model as a markdown document with sections for Events (per entity, chronological, each with its triggering command), Commands (input, preconditions, events produced, rejection outcomes), and Read Models (purpose, subscribed events, consumers). A full worked example of this document structure is in `references/examples.md`.
475
84
 
476
- ### 5. Make All Constraints Explicit
477
- Transform "obvious" business rules into documented invariants:
478
- - "Obviously can't ship an unconfirmed order"
479
- - "ShipOrder validation: requires status='Confirmed' with paymentId"
85
+ ## Key Principles
480
86
 
481
- ### 6. Keep Event Data Factual
482
- Events record facts, not derived values:
483
- - "OrderCreated { items, total }" (total is computed from items)
484
- - "OrderCreated { items[] with unitPrice, shippingAddress }" (total computed in projection)
87
+ See `eventmodeling-core-rules` for the element definitions and causality rules this design must follow (events are immutable facts, commands are checked against documented preconditions, read models never drive command validation).
485
88
 
486
89
  ## Quality Checklist
487
90
 
488
- - [ ] All events are immutable facts (past tense)
489
- - [ ] Events contain only captured data, no computed fields
490
- - [ ] State projection is deterministic from events
491
- - [ ] Each command validates against current state
492
- - [ ] Commands either produce events or reject
493
- - [ ] Event causality is clear
494
- - [ ] State transitions are documented
495
- - [ ] No references between streams in events
496
- - [ ] Read models are optional, not required
497
- - [ ] All logic is state → events (pure functions)
91
+ - [ ] All events are immutable business facts (past tense)
92
+ - [ ] Events contain only captured business data, no computed fields
93
+ - [ ] Each command's preconditions are documented explicitly
94
+ - [ ] Commands either produce events or are rejected — no silent failures
95
+ - [ ] Event causality is clear and traceable end to end
96
+ - [ ] State transitions are documented, including which ones are invalid and why
97
+ - [ ] Read models are optional — nothing requires one to exist