@eventmodelers/cli 1.0.36 → 1.0.37
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.
- package/package.json +1 -1
- package/shared/skills/learn-eventmodelers-api/SKILL.md +12 -10
- package/stacks/modeling-kit/templates/.claude/skills/add-next-slice/SKILL.md +2 -23
- package/stacks/modeling-kit/templates/.claude/skills/add-next-slice/references/api-fallback.md +11 -0
- package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/SKILL.md +6 -57
- package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/references/api-fallback.md +68 -0
- package/stacks/modeling-kit/templates/.claude/skills/attributes/SKILL.md +4 -61
- package/stacks/modeling-kit/templates/.claude/skills/attributes/references/api-fallback.md +39 -0
- package/stacks/modeling-kit/templates/.claude/skills/discover-storyboard/SKILL.md +9 -53
- package/stacks/modeling-kit/templates/.claude/skills/discover-storyboard/references/api-fallback.md +63 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-applying-conways-law/SKILL.md +9 -319
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-applying-conways-law/references/examples.md +329 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/SKILL.md +23 -199
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/references/api-fallback.md +97 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/references/examples.md +35 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/SKILL.md +13 -410
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/references/api-fallback.md +22 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/references/examples.md +397 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-automation-chains/SKILL.md +132 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-automation-chains/references/api-fallback.md +21 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/SKILL.md +9 -236
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/references/examples.md +257 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +28 -302
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/references/api-fallback.md +31 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/references/examples.md +216 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/SKILL.md +30 -343
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/references/api-fallback.md +79 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/references/examples.md +282 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md +51 -400
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/references/api-fallback.md +67 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/references/examples.md +273 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/SKILL.md +45 -152
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/domain-patterns.md +49 -90
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/patterns.md +64 -137
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/SKILL.md +74 -65
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/references/api-fallback.md +51 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-plotting-events/SKILL.md +1 -5
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-plotting-events/references/api-fallback.md +10 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/SKILL.md +19 -36
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/api-fallback.md +41 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/examples.md +12 -9
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/patterns.md +1 -10
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/SKILL.md +26 -332
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/references/api-fallback.md +77 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/references/examples.md +271 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-translating-external-events/SKILL.md +9 -294
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-translating-external-events/references/examples.md +306 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/SKILL.md +12 -11
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/references/api-fallback.md +14 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models-checklist/SKILL.md +6 -36
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models-checklist/references/api-fallback.md +14 -0
- package/stacks/modeling-kit/templates/.claude/skills/examples/SKILL.md +3 -110
- package/stacks/modeling-kit/templates/.claude/skills/examples/references/api-fallback.md +118 -0
- package/stacks/modeling-kit/templates/.claude/skills/handle-comment/SKILL.md +5 -25
- package/stacks/modeling-kit/templates/.claude/skills/handle-comment/references/api-fallback.md +35 -0
- package/stacks/modeling-kit/templates/.claude/skills/html-screen/SKILL.md +9 -44
- package/stacks/modeling-kit/templates/.claude/skills/html-screen/references/api-fallback.md +51 -0
- package/stacks/modeling-kit/templates/.claude/skills/place-element/SKILL.md +23 -183
- package/stacks/modeling-kit/templates/.claude/skills/place-element/references/api-fallback.md +193 -0
- package/stacks/modeling-kit/templates/.claude/skills/storyboard/SKILL.md +14 -81
- package/stacks/modeling-kit/templates/.claude/skills/storyboard/references/api-fallback.md +74 -0
- package/stacks/modeling-kit/templates/.claude/skills/storyboard-screen/SKILL.md +4 -45
- package/stacks/modeling-kit/templates/.claude/skills/storyboard-screen/references/api-fallback.md +44 -0
- package/stacks/modeling-kit/templates/.claude/skills/timeline/SKILL.md +19 -88
- package/stacks/modeling-kit/templates/.claude/skills/timeline/references/api-fallback.md +91 -0
- package/stacks/modeling-kit/templates/.claude/skills/update-prompt-status/SKILL.md +1 -9
- package/stacks/modeling-kit/templates/.claude/skills/update-prompt-status/references/api-fallback.md +14 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-integrating-legacy-systems/SKILL.md +0 -674
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/snapshotting.md +0 -204
package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/SKILL.md
CHANGED
|
@@ -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),
|
|
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), validating stream boundaries (use eventmodeling-optimizing-stream-design), or translating external system events (use eventmodeling-translating-external-events)."
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- AskUserQuestion
|
|
6
6
|
- Write
|
|
@@ -86,31 +86,7 @@ Update Interview Trail:
|
|
|
86
86
|
|
|
87
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
88
|
|
|
89
|
-
|
|
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
|
-
```
|
|
89
|
+
The anti-pattern is a single bundled "aggregate" state object reused across every command handler; the correct approach is one minimal, command-specific state shape per command (e.g. `ConfirmOrderState` carries only `status`/`orderId`, while `ShipOrderState` also needs `paymentId`), with any rich, all-fields view kept entirely separate as a read model rather than fed into command validation. A full worked WRONG/CORRECT comparison (Order domain) is in `references/examples.md`.
|
|
114
90
|
|
|
115
91
|
## Purpose
|
|
116
92
|
Converts domain analysis into the event sourcing architecture pattern:
|
|
@@ -133,29 +109,7 @@ Events are the immutable source of truth. Each stream holds facts about one enti
|
|
|
133
109
|
- **Event Data**: Combines command input + implicit stream state facts
|
|
134
110
|
- **Causality**: Triggered by which command?
|
|
135
111
|
|
|
136
|
-
|
|
137
|
-
```text
|
|
138
|
-
Stream: Order:order-123
|
|
139
|
-
|
|
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)
|
|
146
|
-
|
|
147
|
-
2. OrderConfirmed
|
|
148
|
-
Triggered by: ConfirmOrder command
|
|
149
|
-
Data: paymentId, confirmedAt
|
|
150
|
-
(from command: paymentId)
|
|
151
|
-
(implicit: orderId from stream, previous status verified)
|
|
152
|
-
|
|
153
|
-
3. OrderShipped
|
|
154
|
-
Triggered by: ShipOrder command
|
|
155
|
-
Data: shipmentId, shippedAt
|
|
156
|
-
(from command: shipmentId)
|
|
157
|
-
(implicit: orderId, confirmed status verified)
|
|
158
|
-
```
|
|
112
|
+
Document each event stream as a chronological list of events, giving each event's triggering command and its data — noting which fields came directly from the command versus which are implicit stream-state facts (e.g. a calculated total, or context carried forward from the stream's identity). A full worked example (an Order stream) is in `references/examples.md`.
|
|
159
113
|
|
|
160
114
|
**Key Rules**:
|
|
161
115
|
- Events are **immutable facts** from successful commands
|
|
@@ -185,34 +139,7 @@ Command state read models are **derived** from events and **minimal**:
|
|
|
185
139
|
- Each command handler defines what state projection it needs (and ONLY what it needs)
|
|
186
140
|
- Projection can be regenerated from events at any time
|
|
187
141
|
|
|
188
|
-
|
|
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
|
-
```
|
|
142
|
+
Design a separate, minimal state interface for each command on the same stream — e.g. `ConfirmOrderState` reads only `status`/`orderId`, while `ShipOrderState` also needs `paymentId` — each built by its own state builder that replays only the events it needs and skips the rest; a not-yet-implemented command's state gets the `ToDo` suffix. A full worked example spanning several commands on the same Order stream is in `references/examples.md`.
|
|
216
143
|
|
|
217
144
|
**Enforcement Rule**:
|
|
218
145
|
- ConfirmOrderState used ONLY by handleConfirmOrder
|
|
@@ -230,28 +157,7 @@ Commands are **intent data from UI or Processor**:
|
|
|
230
157
|
- Load current stream state for validation
|
|
231
158
|
- Produce events if valid, or reject if invalid
|
|
232
159
|
|
|
233
|
-
|
|
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
|
-
```
|
|
160
|
+
Document each command's source, its input fields, the preconditions it validates against the loaded state, 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
161
|
|
|
256
162
|
**Key Rules**:
|
|
257
163
|
- Only UI or Processor can issue commands (entry points)
|
|
@@ -268,154 +174,21 @@ Read models are **projections of events for UI/Processor queries**:
|
|
|
268
174
|
- Consumed by UI or Processor (for display/decision)
|
|
269
175
|
- Can be regenerated from events anytime
|
|
270
176
|
|
|
271
|
-
|
|
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
|
-
|
|
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'
|
|
298
|
-
|
|
299
|
-
Consumed by:
|
|
300
|
-
- UI: displays list of orders
|
|
301
|
-
- Processor: checks if order can be shipped
|
|
302
|
-
```
|
|
177
|
+
Document each read model's purpose, which events it subscribes to, its query-optimized data shape, how each subscribed event updates that data, and who consumes it (UI display vs. processor decision-making). A full worked example (OrderSummaryView) is in `references/examples.md`.
|
|
303
178
|
|
|
304
179
|
### 5. Document Event Causality
|
|
305
180
|
Show how events relate to each other:
|
|
306
181
|
|
|
307
|
-
|
|
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
|
-
```
|
|
182
|
+
Trace the causal chain from the first command through the events and downstream commands it can trigger, showing how the state a later command reads depends on events produced by earlier ones. A full worked example (an Order create→confirm→ship chain) is in `references/examples.md`.
|
|
318
183
|
|
|
319
184
|
### 6. Document State Transitions
|
|
320
185
|
Show valid state transitions:
|
|
321
186
|
|
|
322
|
-
|
|
323
|
-
Order Stream State Transitions:
|
|
324
|
-
|
|
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
|
-
```
|
|
187
|
+
Map every valid state transition for the stream — the initial (empty) state, each transition a command can cause, and which transitions are rejected from a given state (e.g. cancelling an already-shipped order) — ending at any terminal states. A full worked example (Order stream transitions) is in `references/examples.md`.
|
|
342
188
|
|
|
343
189
|
### Output Format
|
|
344
190
|
|
|
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
|
-
```
|
|
191
|
+
Present the complete model as a markdown document with sections for Event Streams (each stream's identity, its events, and a human-readable state-projection example per command), Commands (input, validation, events produced, outcomes), Read Models (purpose, subscribed events, queries served), and Implementation Notes. A full worked example of this document structure (Order domain) is in `references/examples.md`.
|
|
419
192
|
|
|
420
193
|
## Key Event Sourcing Principles
|
|
421
194
|
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# Designing Event Models — Worked Examples
|
|
2
|
+
|
|
3
|
+
These are conceptual worked examples (Order domain) illustrating the event-model design reasoning this skill applies — useful for understanding the reasoning, but the actual instructions to follow live in the "Core Architectural Rule" statement and the numbered Workflow sections of the main SKILL.md.
|
|
4
|
+
|
|
5
|
+
## Core Architectural Rule — WRONG vs. CORRECT
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
WRONG: Using DDD Aggregate as command state
|
|
9
|
+
OrderAggregate { orderId, customerId, items[], total, status, paymentId, address, shippedAt, cancelledAt, ... }
|
|
10
|
+
↑ This is a READ MODEL, not command state
|
|
11
|
+
↓ NEVER use for command validation
|
|
12
|
+
handleConfirmOrder(OrderAggregate)
|
|
13
|
+
handleShipOrder(OrderAggregate)
|
|
14
|
+
handleCancelOrder(OrderAggregate)
|
|
15
|
+
|
|
16
|
+
CORRECT: Minimal state per command
|
|
17
|
+
ConfirmOrderState { status, orderId }
|
|
18
|
+
↓
|
|
19
|
+
handleConfirmOrder(ConfirmOrderState)
|
|
20
|
+
|
|
21
|
+
ShipOrderState { status, orderId, paymentId }
|
|
22
|
+
↓
|
|
23
|
+
handleShipOrder(ShipOrderState)
|
|
24
|
+
|
|
25
|
+
CancelOrderState { status, orderId, createdAt }
|
|
26
|
+
↓
|
|
27
|
+
handleCancelOrder(CancelOrderState)
|
|
28
|
+
|
|
29
|
+
OrderSummaryView { orderId, customerId, items[], total, status, paymentId, ... }
|
|
30
|
+
↑ This is for UI queries, NOT command validation
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 1. Design Event Streams — worked example
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
Stream: Order:order-123
|
|
37
|
+
|
|
38
|
+
Events (chronological):
|
|
39
|
+
1. OrderCreated
|
|
40
|
+
Triggered by: CreateOrder command
|
|
41
|
+
Data: customerId, items[], total, shippingAddress, createdAt
|
|
42
|
+
(from command: customerId, items[], shippingAddress)
|
|
43
|
+
(implicit: total calculated from items)
|
|
44
|
+
|
|
45
|
+
2. OrderConfirmed
|
|
46
|
+
Triggered by: ConfirmOrder command
|
|
47
|
+
Data: paymentId, confirmedAt
|
|
48
|
+
(from command: paymentId)
|
|
49
|
+
(implicit: orderId from stream, previous status verified)
|
|
50
|
+
|
|
51
|
+
3. OrderShipped
|
|
52
|
+
Triggered by: ShipOrder command
|
|
53
|
+
Data: shipmentId, shippedAt
|
|
54
|
+
(from command: shipmentId)
|
|
55
|
+
(implicit: orderId, confirmed status verified)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## 2. Design Command State Read Models — worked example
|
|
59
|
+
|
|
60
|
+
Example for the Order stream, with a separate command state read model for each command:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
## ConfirmOrder Command (IMPLEMENTED)
|
|
64
|
+
State interface: ConfirmOrderState { status, orderId }
|
|
65
|
+
Builder: buildConfirmOrderState(events)
|
|
66
|
+
Naming: [CommandName]State = implemented
|
|
67
|
+
- OrderCreated event → Set status='Draft'
|
|
68
|
+
- OrderConfirmed event → Set status='Confirmed'
|
|
69
|
+
(SKIP: items, total, shipping - not needed for this command)
|
|
70
|
+
|
|
71
|
+
## ShipOrder Command (IMPLEMENTED)
|
|
72
|
+
State interface: ShipOrderState { status, orderId, paymentId }
|
|
73
|
+
Builder: buildShipOrderState(events)
|
|
74
|
+
Naming: [CommandName]State = implemented
|
|
75
|
+
(DIFFERENT from ConfirmOrderState)
|
|
76
|
+
- OrderCreated event → (skip)
|
|
77
|
+
- OrderConfirmed event → Set status='Confirmed', set paymentId
|
|
78
|
+
- OrderShipped event → Set status='Shipped'
|
|
79
|
+
|
|
80
|
+
## CancelOrder Command (PLANNED - NOT IMPLEMENTED)
|
|
81
|
+
State interface: CancelOrderStateToDo { status, orderId, createdAt }
|
|
82
|
+
Builder: buildCancelOrderStateToDo(events) [STUB - TODO]
|
|
83
|
+
Naming: [CommandName]StateToDo = planned, needs implementation
|
|
84
|
+
(DIFFERENT from both above)
|
|
85
|
+
- OrderCreated event → Set status='Draft', createdAt
|
|
86
|
+
- OrderCancelled event → Set status='Cancelled'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## 3. Design Commands — worked example
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
Command: ConfirmOrder
|
|
93
|
+
Source: UI or Processor (only these can issue)
|
|
94
|
+
Input: orderId, paymentId
|
|
95
|
+
|
|
96
|
+
Processing:
|
|
97
|
+
1. Load current state from Order:orderId stream
|
|
98
|
+
2. Validate preconditions:
|
|
99
|
+
- state.status === 'Draft' (reject: already confirmed)
|
|
100
|
+
- paymentId is valid (reject: invalid payment)
|
|
101
|
+
3. If all valid:
|
|
102
|
+
- Produce: OrderConfirmed event
|
|
103
|
+
- Data: paymentId, confirmedAt
|
|
104
|
+
- Implicit: orderId (from stream), previous status (from state)
|
|
105
|
+
4. If any validation fails:
|
|
106
|
+
- Reject: return error (no event created)
|
|
107
|
+
|
|
108
|
+
Outcomes:
|
|
109
|
+
Success: OrderConfirmed event appended to stream
|
|
110
|
+
Rejection: Error returned, no event created
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## 4. Design Read Models — worked example
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
ReadModel: OrderSummaryView
|
|
117
|
+
Purpose: UI displays customer order list, Processor checks order status
|
|
118
|
+
|
|
119
|
+
Subscribed to events:
|
|
120
|
+
- OrderCreated
|
|
121
|
+
- OrderConfirmed
|
|
122
|
+
- OrderShipped
|
|
123
|
+
- OrderCancelled
|
|
124
|
+
|
|
125
|
+
Data (optimized for queries):
|
|
126
|
+
{
|
|
127
|
+
orderId: string
|
|
128
|
+
customerId: string
|
|
129
|
+
total: number
|
|
130
|
+
status: string
|
|
131
|
+
createdAt: Date
|
|
132
|
+
confirmedAt?: Date
|
|
133
|
+
shippedAt?: Date
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
Update from events:
|
|
137
|
+
- OrderCreated → Insert row (id, customer, total, status='Draft')
|
|
138
|
+
- OrderConfirmed → Update status='Confirmed', set confirmedAt
|
|
139
|
+
- OrderShipped → Update status='Shipped', set shippedAt
|
|
140
|
+
- OrderCancelled → Update status='Cancelled'
|
|
141
|
+
|
|
142
|
+
Consumed by:
|
|
143
|
+
- UI: displays list of orders
|
|
144
|
+
- Processor: checks if order can be shipped
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## 5. Document Event Causality — worked example
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
Command Flow:
|
|
151
|
+
CreateOrder command
|
|
152
|
+
→ OrderCreated event
|
|
153
|
+
↓ (may trigger external process)
|
|
154
|
+
ConfirmOrder command (reads OrderCreated state)
|
|
155
|
+
→ OrderConfirmed event
|
|
156
|
+
↓ (may trigger)
|
|
157
|
+
ShipOrder command (reads OrderCreated + OrderConfirmed state)
|
|
158
|
+
→ OrderShipped event
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## 6. Document State Transitions — worked example
|
|
162
|
+
|
|
163
|
+
```text
|
|
164
|
+
Order Stream State Transitions:
|
|
165
|
+
|
|
166
|
+
Initial state: (empty stream)
|
|
167
|
+
↓
|
|
168
|
+
CreateOrder → OrderCreated
|
|
169
|
+
↓
|
|
170
|
+
State: Draft
|
|
171
|
+
|
|
172
|
+
Draft state:
|
|
173
|
+
→ ConfirmOrder → OrderConfirmed → State: Confirmed
|
|
174
|
+
→ CancelOrder → OrderCancelled → State: Cancelled
|
|
175
|
+
|
|
176
|
+
Confirmed state:
|
|
177
|
+
→ ShipOrder → OrderShipped → State: Shipped
|
|
178
|
+
→ CancelOrder (rejected - already confirmed)
|
|
179
|
+
|
|
180
|
+
Shipped state:
|
|
181
|
+
→ No more transitions allowed
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Output Format — full worked example
|
|
185
|
+
|
|
186
|
+
```markdown
|
|
187
|
+
# Event Model: [Domain]
|
|
188
|
+
|
|
189
|
+
## Event Streams
|
|
190
|
+
|
|
191
|
+
### Stream: Order
|
|
192
|
+
|
|
193
|
+
**Identity**: orderId
|
|
194
|
+
|
|
195
|
+
**Events**:
|
|
196
|
+
- OrderCreated: Initial event creating the order
|
|
197
|
+
Data: customerId, items[], total, shippingAddress
|
|
198
|
+
|
|
199
|
+
- OrderConfirmed: Payment confirmed
|
|
200
|
+
Data: paymentId, confirmedAt
|
|
201
|
+
|
|
202
|
+
- OrderShipped: Order shipped
|
|
203
|
+
Data: shipmentId, shippedAt
|
|
204
|
+
|
|
205
|
+
- OrderCancelled: Order cancelled
|
|
206
|
+
Data: cancelledAt, reason
|
|
207
|
+
|
|
208
|
+
**State Projection (Human Example)**:
|
|
209
|
+
For the ConfirmOrder command, we need minimal state:
|
|
210
|
+
```text
|
|
211
|
+
ConfirmOrderState:
|
|
212
|
+
- orderId: 'order-123'
|
|
213
|
+
- status: 'Draft'
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
For the ShipOrder command, we need different data:
|
|
217
|
+
```text
|
|
218
|
+
ShipOrderState:
|
|
219
|
+
- orderId: 'order-123'
|
|
220
|
+
- status: 'Confirmed'
|
|
221
|
+
- paymentId: 'payment-456'
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Commands
|
|
227
|
+
|
|
228
|
+
### Command: CreateOrder
|
|
229
|
+
- Input: customerId, items[], shippingAddress
|
|
230
|
+
- Validation: Items valid, customerId exists
|
|
231
|
+
- Events produced: OrderCreated
|
|
232
|
+
- Possible outcomes: Success (OrderCreated) or Validation error
|
|
233
|
+
|
|
234
|
+
### Command: ConfirmOrder
|
|
235
|
+
- Input: orderId, paymentId
|
|
236
|
+
- Validation: Order in Draft status, payment validated
|
|
237
|
+
- Events produced: OrderConfirmed
|
|
238
|
+
- Possible outcomes: Success or "Already confirmed" error
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Read Models (Optional)
|
|
243
|
+
|
|
244
|
+
### ReadModel: OrderSummaryView
|
|
245
|
+
- Purpose: Quick lookup of order status
|
|
246
|
+
- Events: OrderCreated, OrderConfirmed, OrderShipped, OrderCancelled
|
|
247
|
+
- Queries served: GetOrder(orderId), ListOrdersByCustomer(customerId)
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Implementation Notes
|
|
252
|
+
- All state is derived from events
|
|
253
|
+
- Commands validate against derived state
|
|
254
|
+
- No transaction across streams
|
|
255
|
+
- Events are source of truth
|
|
256
|
+
- Read models can be rebuilt from events
|
|
257
|
+
```
|