@eventmodelers/cli 1.0.35 → 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.
Files changed (69) hide show
  1. package/package.json +1 -1
  2. package/shared/skills/learn-eventmodelers-api/SKILL.md +12 -10
  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 +9 -319
  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 +23 -199
  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 +13 -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-designing-automation-chains/SKILL.md +132 -0
  20. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-automation-chains/references/api-fallback.md +21 -0
  21. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/SKILL.md +9 -236
  22. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/references/examples.md +257 -0
  23. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +28 -302
  24. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/references/api-fallback.md +31 -0
  25. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/references/examples.md +216 -0
  26. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/SKILL.md +30 -343
  27. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/references/api-fallback.md +79 -0
  28. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/references/examples.md +282 -0
  29. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md +51 -399
  30. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/references/api-fallback.md +67 -0
  31. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/references/examples.md +273 -0
  32. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/SKILL.md +45 -152
  33. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/domain-patterns.md +49 -90
  34. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/patterns.md +64 -137
  35. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/SKILL.md +74 -65
  36. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/references/api-fallback.md +51 -0
  37. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-plotting-events/SKILL.md +1 -5
  38. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-plotting-events/references/api-fallback.md +10 -0
  39. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/SKILL.md +19 -36
  40. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/api-fallback.md +41 -0
  41. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/examples.md +12 -9
  42. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/patterns.md +1 -10
  43. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/SKILL.md +26 -332
  44. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/references/api-fallback.md +77 -0
  45. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/references/examples.md +271 -0
  46. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-translating-external-events/SKILL.md +9 -294
  47. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-translating-external-events/references/examples.md +306 -0
  48. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/SKILL.md +12 -11
  49. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/references/api-fallback.md +14 -0
  50. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models-checklist/SKILL.md +6 -36
  51. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models-checklist/references/api-fallback.md +14 -0
  52. package/stacks/modeling-kit/templates/.claude/skills/examples/SKILL.md +3 -110
  53. package/stacks/modeling-kit/templates/.claude/skills/examples/references/api-fallback.md +118 -0
  54. package/stacks/modeling-kit/templates/.claude/skills/handle-comment/SKILL.md +5 -25
  55. package/stacks/modeling-kit/templates/.claude/skills/handle-comment/references/api-fallback.md +35 -0
  56. package/stacks/modeling-kit/templates/.claude/skills/html-screen/SKILL.md +9 -44
  57. package/stacks/modeling-kit/templates/.claude/skills/html-screen/references/api-fallback.md +51 -0
  58. package/stacks/modeling-kit/templates/.claude/skills/place-element/SKILL.md +23 -183
  59. package/stacks/modeling-kit/templates/.claude/skills/place-element/references/api-fallback.md +193 -0
  60. package/stacks/modeling-kit/templates/.claude/skills/storyboard/SKILL.md +14 -81
  61. package/stacks/modeling-kit/templates/.claude/skills/storyboard/references/api-fallback.md +74 -0
  62. package/stacks/modeling-kit/templates/.claude/skills/storyboard-screen/SKILL.md +4 -45
  63. package/stacks/modeling-kit/templates/.claude/skills/storyboard-screen/references/api-fallback.md +44 -0
  64. package/stacks/modeling-kit/templates/.claude/skills/timeline/SKILL.md +19 -88
  65. package/stacks/modeling-kit/templates/.claude/skills/timeline/references/api-fallback.md +91 -0
  66. package/stacks/modeling-kit/templates/.claude/skills/update-prompt-status/SKILL.md +1 -9
  67. package/stacks/modeling-kit/templates/.claude/skills/update-prompt-status/references/api-fallback.md +14 -0
  68. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-integrating-legacy-systems/SKILL.md +0 -674
  69. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/snapshotting.md +0 -204
@@ -0,0 +1,67 @@
1
+ # Identifying Outputs — curl Fallback Calls
2
+
3
+ Only needed when MCP is not connected. Every call below has an MCP equivalent in the main SKILL.md — always prefer that.
4
+
5
+ ## Step 5f — Placing a READMODEL node (full manual sequence)
6
+
7
+ 1. Find the column where the consumer SCREEN or AUTOMATION lives. For an AUTOMATION, the read model's target column is always the one immediately **before** it (skip straight to inserting that column — its interaction row is guaranteed occupied by the automation's own COMMAND). For a SCREEN, target the screen's own column. Fetch the timeline to get the interaction row ID:
8
+ ```bash
9
+ curl -s -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" \
10
+ "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/$CHAPTER_ID"
11
+ # → timelineData.rows — find the row where type === "interaction"
12
+ ```
13
+ 2. Check if the target interaction cell is already occupied (existing COMMAND):
14
+ ```bash
15
+ curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?cellId=<interactionRowId>-<columnId>" \
16
+ -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID"
17
+ ```
18
+ If a COMMAND occupies that cell, insert a new column immediately **before** it (`{"index": currentIndex}` — this shifts the consumer's column, and everything after it, one to the right) and use that new column's ID instead. The read model must end up upstream of (to the left of) its consumer, never downstream of it.
19
+ 3. `cellId = interactionRow.id + "-" + columnId`
20
+ 4. Create the READMODEL:
21
+ ```bash
22
+ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
23
+ -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" -H "x-user-id: identifying-outputs" \
24
+ -H "Content-Type: application/json" \
25
+ -d '[{
26
+ "id": "<event-uuid>",
27
+ "eventType": "node:created",
28
+ "nodeId": "<node-uuid>",
29
+ "boardId": "<BOARD_ID>",
30
+ "timestamp": 1234567890,
31
+ "chapterId": "<CHAPTER_ID>",
32
+ "cellId": "<interactionRowId>-<columnId>",
33
+ "meta": {"type": "READMODEL", "title": "ActiveReservationView", "fields": [...]}
34
+ }]'
35
+ ```
36
+
37
+ ## Step 5h.1 — Wire EVENT → READMODEL
38
+
39
+ ```bash
40
+ curl -s "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes?cellId=<swimlaneRowId>-<columnId>" \
41
+ -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" -H "x-user-id: eventmodeling-identifying-outputs"
42
+ ```
43
+ Connect it:
44
+ ```bash
45
+ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/connections" \
46
+ -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" -H "x-user-id: eventmodeling-identifying-outputs" \
47
+ -H "Content-Type: application/json" \
48
+ -d '{"source":"<eventNodeId>","target":"<readmodelNodeId>"}'
49
+ ```
50
+
51
+ ## Step 5h.2 — Wire READMODEL → SCREEN
52
+
53
+ ```bash
54
+ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/connections" \
55
+ -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" -H "x-user-id: eventmodeling-identifying-outputs" \
56
+ -H "Content-Type: application/json" \
57
+ -d '{"source":"<readmodelNodeId>","target":"<screenNodeId>"}'
58
+ ```
59
+
60
+ ## Step 5h.3 — Wire READMODEL → AUTOMATION
61
+
62
+ ```bash
63
+ curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/connections" \
64
+ -H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" -H "x-user-id: eventmodeling-identifying-outputs" \
65
+ -H "Content-Type: application/json" \
66
+ -d '{"source":"<readmodelNodeId>","target":"<automationNodeId>"}'
67
+ ```
@@ -0,0 +1,273 @@
1
+ # Identifying Outputs — Worked Examples
2
+
3
+ These are conceptual worked examples of the read-model design thinking this step applies — useful for understanding the reasoning, but the actual mechanics live in the numbered Step 5a–5i sections of the main SKILL.md (placing nodes on the board via the API), not in writing a document like this.
4
+
5
+ ## Conceptual walkthrough — mapping events to a read model (Order domain)
6
+
7
+ ### 1. Map Event Data to UI Screens
8
+
9
+ ```
10
+ Screen: Order Status View
11
+ Displays data from events:
12
+ orderId ← OrderCreated event
13
+ customerId ← OrderCreated event
14
+ items ← OrderCreated event
15
+ total ← OrderCreated event
16
+ status ← OrderConfirmed event (or OrderCancelled)
17
+ confirmedAt ← OrderConfirmed event
18
+ paymentId ← PaymentAuthorized event
19
+ shipmentId ← OrderShipped event
20
+ shippedAt ← OrderShipped event
21
+
22
+ This screen is a projection of these events:
23
+ - OrderCreated
24
+ - OrderConfirmed
25
+ - PaymentAuthorized
26
+ - OrderShipped
27
+ ```
28
+
29
+ ### 2. Define Read Models
30
+
31
+ ```
32
+ ReadModel: OrderStatusView
33
+ Purpose: UI displays current order status
34
+ Events subscribed: OrderCreated, OrderConfirmed, PaymentAuthorized, OrderShipped, OrderCancelled
35
+ Data:
36
+ {
37
+ orderId: string (from OrderCreated)
38
+ customerId: string (from OrderCreated)
39
+ status: enum (from events: Draft → Confirmed → Authorized → Shipped → Delivered)
40
+ createdAt: Date (from OrderCreated)
41
+ confirmedAt: Date (from OrderConfirmed)
42
+ paymentId: string (from PaymentAuthorized)
43
+ shipmentId: string (from OrderShipped)
44
+ shippedAt: Date (from OrderShipped)
45
+ }
46
+ ```
47
+
48
+ ### 3. Document Event → Data Mapping
49
+
50
+ ```
51
+ Event: OrderCreated
52
+ Provides to UI/Processors:
53
+ orderId
54
+ customerId
55
+ items[]
56
+ total
57
+ shippingAddress
58
+ createdAt
59
+
60
+ Event: OrderConfirmed
61
+ Provides to UI/Processors:
62
+ orderId (link to stream)
63
+ paymentMethod (user selected method)
64
+ confirmedAt (timestamp)
65
+ paymentId (payment system reference)
66
+
67
+ Event: PaymentAuthorized
68
+ Provides to UI/Processors:
69
+ orderId (link to stream)
70
+ paymentId
71
+ authCode
72
+ authorizedAt (timestamp)
73
+ amount (verified amount)
74
+
75
+ Event: OrderShipped
76
+ Provides to UI/Processors:
77
+ orderId (link to stream)
78
+ shipmentId
79
+ shippedAt (timestamp)
80
+ carrier (shipping company)
81
+ trackingNumber (for delivery tracking)
82
+ ```
83
+
84
+ ### 4. Create Output Catalog
85
+
86
+ ```
87
+ ReadModel Catalog: Order System
88
+
89
+ 1. OrderStatusReadModel
90
+ Purpose: UI shows current order status
91
+ Events: OrderCreated, OrderConfirmed, PaymentAuthorized, OrderShipped, OrderCancelled
92
+ Data: orderId, status, createdAt, confirmedAt, paymentId, shipmentId
93
+ Consumed by:
94
+ - Order Status screen (UI)
95
+ - Customer Dashboard (UI)
96
+ - Order Processing Processor (decides if can ship)
97
+
98
+ 2. OrderListReadModel
99
+ Purpose: UI lists all orders for a customer
100
+ Events: OrderCreated, OrderConfirmed, OrderCancelled
101
+ Data: orderId, customerId, total, status, createdAt
102
+ Consumed by:
103
+ - Customer Order History (UI)
104
+ - Order Search/Filter (UI)
105
+
106
+ 3. PaymentStatusReadModel
107
+ Purpose: UI shows payment status
108
+ Events: OrderConfirmed, PaymentAuthorized, PaymentFailed
109
+ Data: orderId, paymentId, status, authCode, failureReason, timestamp
110
+ Consumed by:
111
+ - Payment Status screen (UI)
112
+ - Accounting Processor (reconciliation)
113
+
114
+ 4. ShipmentTrackingReadModel
115
+ Purpose: UI shows tracking information
116
+ Events: OrderShipped, DeliveryConfirmed
117
+ Data: orderId, shipmentId, trackingNumber, carrier, shippedAt, estimatedDelivery
118
+ Consumed by:
119
+ - Order Tracking screen (UI)
120
+ - Customer notifications (Processor)
121
+ ```
122
+
123
+ ### 5. Identify Missing Data
124
+
125
+ ```
126
+ Question: What if UI needs "estimated delivery date"?
127
+ Event: OrderShipped has carrier + trackingNumber
128
+ Action needed: Add estimatedDelivery to OrderShipped event
129
+ (or compute from carrier info)
130
+
131
+ Question: What if UI needs to show "payment method" on status?
132
+ Event: OrderConfirmed has paymentMethod
133
+ Action needed: Include paymentMethod in relevant read models
134
+
135
+ Question: What if UI needs "item descriptions"?
136
+ Event: OrderCreated has items[]
137
+ But: items[] only has productId
138
+ Action needed: Enrich with product descriptions from catalog
139
+ (via join with product service)
140
+ ```
141
+
142
+ ### 6. Processor Outputs
143
+
144
+ ```
145
+ Processor: Inventory System
146
+ Consumes from read models:
147
+ - Orders in "PaymentAuthorized" status
148
+ - Items and quantities needed
149
+ Produces commands:
150
+ - ReserveInventory
151
+
152
+ Processor: Fulfillment System
153
+ Consumes from read models:
154
+ - Orders in "InventoryReserved" status
155
+ - Items and quantities
156
+ - Shipping address
157
+ Produces commands:
158
+ - CreateShipment
159
+
160
+ Processor: Notification System
161
+ Consumes from read models:
162
+ - OrderCreated (sends confirmation)
163
+ - OrderConfirmed (sends receipt)
164
+ - OrderShipped (sends tracking)
165
+ - DeliveryConfirmed (sends thank you)
166
+ Does not produce commands (info-only)
167
+ ```
168
+
169
+ ## Legacy markdown-document format (superseded — kept for reference only)
170
+
171
+ Older versions of this skill wrote the read model catalog as a markdown document instead of placing nodes on the board. The actual mechanism today is the board API (Step 5a–5i in the main SKILL.md) — this template is kept only so the shape of the information (what a complete read-model catalog covers) stays documented somewhere.
172
+
173
+ ```markdown
174
+ # Outputs: [Domain Name]
175
+
176
+ ## Read Models Summary
177
+
178
+ | ReadModel | Purpose | Events | Consumed By |
179
+ |-----------|---------|--------|-------------|
180
+ | OrderStatus | Show order state | OrderCreated, OrderConfirmed | UI, Processor |
181
+ | OrderList | List orders | OrderCreated, OrderCancelled | UI |
182
+ | PaymentStatus | Payment info | OrderConfirmed, PaymentAuthorized | UI, Accounting |
183
+ | Shipment Tracking | Track delivery | OrderShipped, DeliveryConfirmed | UI, Notifications |
184
+
185
+ ---
186
+
187
+ ## Detailed Read Models
188
+
189
+ ### ReadModel: OrderStatusView
190
+
191
+ **Purpose**: Order Status screen displays current order state
192
+
193
+ **Events subscribed**:
194
+ - OrderCreated
195
+ - OrderConfirmed
196
+ - PaymentAuthorized
197
+ - OrderShipped
198
+ - OrderCancelled
199
+ - DeliveryConfirmed
200
+
201
+ **Data**:
202
+ ```
203
+ {
204
+ orderId: string
205
+ customerId: string
206
+ status: 'Draft' | 'Confirmed' | 'Authorized' | 'Shipped' | 'Delivered' | 'Cancelled'
207
+ items: Array<{productId, quantity, unitPrice}>
208
+ total: number
209
+ shippingAddress: Address
210
+
211
+ createdAt: Date
212
+ confirmedAt: Date
213
+ paymentId: string
214
+ paymentMethod: 'card' | 'transfer'
215
+ authorizedAt: Date
216
+
217
+ shipmentId: string
218
+ carrier: string
219
+ trackingNumber: string
220
+ shippedAt: Date
221
+ estimatedDelivery: Date
222
+ }
223
+ ```
224
+
225
+ **Update Logic**:
226
+ - OrderCreated: Insert with status='Draft'
227
+ - OrderConfirmed: Update status='Confirmed'
228
+ - PaymentAuthorized: Update status='Authorized', set paymentId
229
+ - OrderShipped: Update status='Shipped', set shipmentId, carrier, trackingNumber
230
+ - DeliveryConfirmed: Update status='Delivered'
231
+ - OrderCancelled: Update status='Cancelled'
232
+
233
+ **Consumed By**:
234
+ - Order Status Screen (displays)
235
+ - Order Processing Processor (checks status)
236
+ - Notification System (sends updates)
237
+
238
+ --- [Repeat for each read model]
239
+
240
+ ---
241
+
242
+ ## Data Completeness Check
243
+
244
+ ### Events → UI Needs
245
+
246
+ Verify all UI needs have event sources:
247
+
248
+ | UI Need | Event Source | Status |
249
+ |---------|-------------|--------|
250
+ | Order status | OrderConfirmed, OrderShipped | |
251
+ | Tracking number | OrderShipped | |
252
+ | Order items | OrderCreated | |
253
+ | Estimated delivery | OrderShipped | |
254
+ | Cancellation reason | OrderCancelled | |
255
+
256
+ ### Missing Data
257
+
258
+ Identify UI needs without event sources:
259
+ - None identified
260
+
261
+ ---
262
+
263
+ ## Processor Consumption
264
+
265
+ ### Processors and their reads:
266
+
267
+ | Processor | Reads From | Writes Commands |
268
+ |-----------|-----------|-----------------|
269
+ | Inventory | OrderStatusView (Authorized) | ReserveInventory |
270
+ | Fulfillment | OrderStatusView (InventoryReserved) | CreateShipment |
271
+ | Notification | OrderStatusView (all) | None (info-only) |
272
+ | Accounting | PaymentStatusView | None (reporting) |
273
+ ```
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: eventmodeling-optimizing-stream-design
3
- description: "Design event streams with proper stream identity to keep streams appropriately sized, avoid unnecessary snapshotting, and balance performance with simplicity. Use when concerned about stream length, planning performance, or validating stream design before implementation. Do not use for: designing the initial event model structure (use eventmodeling-designing-event-models) or general architectural validation (use eventmodeling-validating-event-models)."
3
+ description: "Validate and fix event stream boundaries is each stream anchored on a single business identity, or is it secretly a collection/log that will grow unbounded? Use when concerned about stream length, reviewing stream design before implementation, or when a stream feels like it's absorbing unrelated events. Do not use for: designing the initial event model structure (use eventmodeling-designing-event-models) or general architectural validation (use eventmodeling-validating-event-models)."
4
4
  allowed-tools:
5
5
  - AskUserQuestion
6
6
  - Write
@@ -10,45 +10,16 @@ allowed-tools:
10
10
 
11
11
  ## Interview Phase (Optional)
12
12
 
13
- **When to Interview**: Skip if the user has specified: expected event frequency, stream lifetime, and growth patterns. Interview when stream length concerns exist but growth estimates are unclear.
13
+ **When to Interview**: Skip if the user has already named the entity each stream is anchored on and confirmed every event in it belongs to that entity's own lifecycle. Interview when a stream's boundary feels unclear or it seems to be absorbing events from more than one concern.
14
14
 
15
- **Interview Strategy**: Establish growth expectations and performance requirements before recommending snapshotting. Most snapshotting proposals stem from poor stream boundary design, not genuine volume — surface the estimates first to distinguish real performance concerns from design problems.
15
+ **Interview Strategy**: This is a boundary question, not a performance question establish what single business identity a stream is supposed to represent before judging whether it's well-designed.
16
16
 
17
- ### Critical Questions
17
+ ### Critical Question
18
18
 
19
- 1. **Growth Estimates** (Impact: Determines if snapshotting is needed or if stream design should change)
20
- - Question: "Estimate events: (A) Per entity per day, (B) Lifetime total, (C) Growth over years. Example: 5-10 events/order, 1-10 million orders/year?"
21
- - Why it matters: Growth estimates reveal if streams will genuinely be too long or if design is wrong
22
- - Follow-up triggers: If estimates exceed 300 events per stream lifetimeask "Is the stream identity correct? Could this stream be split by a narrower business entity?"
23
-
24
- 2. **Performance SLAs** (Impact: Determines acceptable latency and snapshotting decisions)
25
- - Question: "Performance requirements? (A) <100ms read latency, (B) <1s acceptable, (C) Eventual consistency OK?"
26
- - Why it matters: Strict SLAs might need snapshotting; loose SLAs often don't
27
- - Follow-up triggers: If (A) → ask "Which commands specifically need sub-100ms replay? Are those commands reading from a read model or replaying the stream directly?"
28
-
29
- ### Interview Flow
30
-
31
- **Conditional Entry**:
32
- ```
33
- If user has provided:
34
- - Event frequency estimate (per entity per day or per transaction)
35
- - AND stream lifetime estimate (months or years)
36
- - AND read latency SLA (or confirmation that eventual consistency is acceptable)
37
-
38
- Then: Skip interview, proceed directly to stream analysis
39
-
40
- Else: Conduct interview
41
- ```
42
-
43
- **Phase 1: Growth Estimation** (Question 1)
44
- - Establish per-entity event volume
45
- - Project lifetime stream length using the estimation formula
46
- - Determine whether redesign or snapshotting analysis is warranted
47
-
48
- **Phase 2: SLA Requirements** (Question 2)
49
- - Identify read latency requirements per command
50
- - Determine whether read models or direct stream replay satisfies the SLA
51
- - Establish whether snapshotting is justified by SLA alone
19
+ **Stream Identity** (Impact: Determines whether the stream is a real aggregate or a disguised collection/log)
20
+ - Question: "What one business entity does this stream represent the history of? Does every event in it belong to that entity's own lifecycle, or does it also pick up events from a broader category?"
21
+ - Why it matters: A stream with no single identity, or one that mixes in events belonging to other entities, is the root cause behind almost every stream-design complaint — not stream length itself.
22
+ - Follow-up triggers: If the answer names a category ("all orders", "system events") rather than one entity that's Pattern 3/4 in `references/patterns.md` (Collection/Event Log anti-patterns) walk through the fix directly.
52
23
 
53
24
  ### Capturing Interview Findings
54
25
 
@@ -61,171 +32,93 @@ Use Write tool to add/update this section:
61
32
  ```markdown
62
33
  ## Optimizing Stream Design (eventmodeling-optimizing-stream-design)
63
34
 
64
- ### Growth Estimates
65
- [From Q1: Events per entity per day, lifetime total, annual growth]
66
-
67
- ### Performance SLAs
68
- [From Q2: Latency requirements per command or view]
35
+ ### Stream Identity Review
36
+ [Which streams were reviewed? What entity does each represent? Any that turned out to be a disguised collection/log?]
69
37
 
70
- ### Optimization Decisions
38
+ ### Boundary Decisions
71
39
  - Streams requiring redesign: [list or "None"]
72
- - Streams where snapshotting is justified: [list or "None"]
73
- - Streams within acceptable bounds: [list]
40
+ - Streams confirmed well-bounded: [list]
74
41
  ```
75
42
 
76
43
  Update Interview Trail:
77
44
  ```markdown
78
- | Optimization | eventmodeling-optimizing-stream-design | Done | Stream growth estimates, SLA review, snapshotting decisions |
45
+ | Optimization | eventmodeling-optimizing-stream-design | Done | Stream identity review, boundary decisions |
79
46
  ```
80
47
 
81
48
  ---
82
49
 
83
50
  ## Stream Design Optimization
84
51
 
85
- **Purpose**: Optimize event stream design by validating stream boundaries, estimating growth, and making snapshotting decisions based on design quality—not just size.
52
+ **Purpose**: Validate stream boundaries confirm each stream is anchored on a single business entity's own lifecycle, and catch the two common anti-patterns (an unbounded collection, or an unrelated event log) before they get built.
86
53
 
87
- **Applies To**: Any domain - e-commerce, banking, SaaS, marketplace, healthcare, etc.
54
+ **Applies To**: Any domain e-commerce, banking, SaaS, marketplace, healthcare, etc.
88
55
 
89
56
  **When to Use**:
90
57
  - After defining event streams in domain analysis
91
- - When concerned about stream length or performance
92
- - Before implementing to validate stream design
93
- - During performance planning to determine snapshotting strategy
94
- - When redesigning streams for scalability
58
+ - Before implementing, to validate stream design
59
+ - When a stream feels like it's growing for reasons unrelated to one entity's own story
60
+ - When redesigning a stream whose boundary turned out to be wrong
95
61
 
96
62
  **What It Does**:
97
- 1. Analyzes event stream design for proper event organization
98
- 2. Estimates stream growth over time
99
- 3. Identifies when snapshotting is genuinely needed vs. design issue
100
- 4. Recommends optimal stream identity boundaries
101
- 5. Balances performance optimization against complexity
102
- 6. Provides snapshotting strategy without over-engineering
63
+ 1. Checks that each stream has a single, natural business identity
64
+ 2. Identifies streams that are actually collections or logs in disguise
65
+ 3. Recommends the correct stream boundary when one is wrong
66
+ 4. Distinguishes "this stream is long because the entity has a long history" (fine) from "this stream is long because it's absorbing events that don't belong to it" (a boundary bug)
103
67
 
104
68
  ---
105
69
 
106
- ## Core Principle: Design First, Snapshot Second
70
+ ## Core Principle: Get the Identity Right
107
71
 
108
72
  **Golden Rule**:
109
- > If you find yourself needing to snapshot because the stream is too long, first ask: "Is my stream identity wrong?" Usually, the answer is yes.
73
+ > If a stream feels like it's growing for the wrong reasons, first ask: "Does this stream actually have one business identity, or is it a collection/log wearing an aggregate's name?"
110
74
 
111
- Snapshotting is a **performance optimization**, not a design problem. Good stream design (proper identity boundaries) often eliminates the need for snapshotting entirely.
75
+ A long stream is not, by itself, evidence of a design problem an account open for thirty years is correctly one long stream. What *is* always a design problem is a stream whose events don't all belong to the same entity's own lifecycle.
112
76
 
113
77
  ---
114
78
 
115
- ## Stream Design Analysis Framework
79
+ ## Stream Boundary Review
116
80
 
117
- ### 1. Estimate Stream Growth
81
+ For each stream in scope, work through:
118
82
 
119
- **Formula**:
120
- ```
121
- Estimated Stream Length (total events/instance) =
122
- Events Per Aggregate Instance Per Year (events/instance/year)
123
- × Lifetime of Instance (years)
124
- × Annual Growth Factor (dimensionless year-over-year multiplier ≥ 1.0)
125
- ```
126
-
127
- **Quick Examples**:
83
+ ### 1. Name the identity
128
84
 
129
- **E-commerce Order**: 8 events/year × 1.5 year lifetime = 8-16 events NOT NEEDED
85
+ What single business entity does this stream represent the history of? Write it down explicitly (e.g. `orderId`, not "orders").
130
86
 
131
- **Banking Account**: 100-200 events/year × 10 years = 1000-2000 events → CONSIDER AT 1000+
87
+ ### 2. Check every event against that identity
132
88
 
133
- **Order Processing**: 100+ events/year × 5 years = 300-500+ events PROBABLY NEEDED
89
+ Does each event in the stream describe something that happened to *this* entity — not to a category of entities, not to the system in general? If any event fails this test, the boundary is wrong (see `references/patterns.md`'s Red Flags).
134
90
 
135
- **SaaS User**: 12-60 events/year × 5 years = 60-300 events → RARELY NEEDED
91
+ ### 3. Classify the result
136
92
 
137
- ### 2. Identify Stream Length Categories
138
-
139
- | Length | Status | Action | Snapshotting |
140
- |--------|--------|--------|--------------|
141
- | < 50 events | IDEAL | Keep as-is | NOT NEEDED |
142
- | 50-100 events | GOOD | Monitor growth | NOT NEEDED |
143
- | 100-300 events | ACCEPTABLE | Review boundary | CONSIDER if replayed |
144
- | 300-1000 events | LONG | REDESIGN first | Only last resort |
145
- | 1000+ events | CRITICAL | REDESIGN required | Won't help |
146
-
147
- ---
148
-
149
- ## Quick Decision Matrix
150
-
151
- | Stream Length | Read Pattern | Frequency | Action |
152
- |---|---|---|---|
153
- | < 50 | Any | Any | IDEAL - Keep as-is |
154
- | 50-100 | Any | Any | Good - Monitor |
155
- | 100-300 | From Model | Any | OK - No snapshot |
156
- | 100-300 | Stream Replay | Low | OK - Monitor |
157
- | 100-300 | Stream Replay | High | REDESIGN |
158
- | 300-1000 | From Model | Any | OK - No snapshot |
159
- | 300-1000 | Stream Replay | Any | REDESIGN |
160
- | 1000+ | Any | Any | CRITICAL - REDESIGN |
93
+ | Result | Meaning | Action |
94
+ |---|---|---|
95
+ | Every event belongs to one clear entity | Boundary is correct | Keep as-is, regardless of how long the history gets |
96
+ | Events span a category or "all X" | Pattern 3 (Collection) anti-pattern | Re-scope to the real per-entity identity; the category becomes a read model/query, not a stream |
97
+ | Events span unrelated concerns (users, orders, payments mixed) | Pattern 4 (Event Log) anti-pattern | Split into one stream per concern |
98
+ | Stream conflates an entity's active life with its historical record | Missing the Pattern 5 split | Separate active vs. archived/historical streams |
161
99
 
162
100
  ---
163
101
 
164
102
  ## Reference Files
165
103
 
166
104
  **Aggregate Boundary Design**: See [patterns.md](references/patterns.md) for:
167
- - 5 aggregate patterns (single entity, composite, collections, event logs, historical)
168
- - Stream size decision tree
169
- - Red flags that indicate redesign needed
170
- - Tips for optimal stream design
171
-
172
- **Snapshotting Strategy**: See [snapshotting.md](references/snapshotting.md) for:
173
- - Criteria for when snapshotting is truly needed
174
- - Context-based decision thresholds
175
- - Snapshot frequency, versioning, and cleanup strategies
176
- - Cost-benefit analysis
105
+ - 5 aggregate boundary patterns (single entity, composite, collection anti-pattern, event-log anti-pattern, historical)
106
+ - The stream boundary decision tree
107
+ - Red flags that indicate the boundary — not the volume — is wrong
108
+ - Tips for finding the right boundary
177
109
 
178
110
  **Domain-Specific Guidance**: See [domain-patterns.md](references/domain-patterns.md) for:
179
111
  - E-commerce patterns (orders, carts, accounts)
180
112
  - Banking patterns (accounts, transactions, loans)
181
113
  - SaaS patterns (subscriptions, workspaces, data collections)
182
- - Implementation checklist
183
-
184
- ---
185
-
186
- ## Key Insights
187
-
188
- ### Why Snapshotting Usually Isn't the Answer
189
-
190
- ```
191
- Before implementing snapshotting, ask:
192
-
193
- 1. Can I split this aggregate into smaller ones?
194
- → YES: Do that instead. Simpler, better design.
195
-
196
- 2. Can I reduce event granularity?
197
- → YES: Batch events or create coarser state changes.
198
-
199
- 3. Am I using a read model for this aggregate?
200
- → NO: Create a read model (cached projection).
201
- Stream size becomes irrelevant.
202
-
203
- 4. Have I measured actual replay latency?
204
- → NO: Measure first. Most systems exceed expectations.
205
-
206
- If ANY of these is YES, do that before snapshotting.
207
- Only after exhausting design improvements, consider snapshots.
208
- ```
209
-
210
- ### The Snapshotting Trade-off
211
-
212
- ```
213
- Snapshotting Complexity ≈ 2-3x Complexity of Better Design
214
-
215
- Before snapshot: 50 lines of code, simple, testable
216
- With snapshots: 150+ lines, versioning, recovery logic, testing matrix
217
-
218
- Better to redesign and keep streams < 300 events.
219
- ```
220
114
 
221
115
  ---
222
116
 
223
117
  ## Quality Checklist
224
118
 
225
119
  - [ ] Each stream is identified by a business entity identity (e.g., `orderId`), not a category or type
226
- - [ ] No stream grows unboundedly without a design reasonevent frequency and stream lifetime estimated
227
- - [ ] Streams under 1000 events require no snapshotting justification
228
- - [ ] If snapshotting is proposed, all simpler alternatives (split stream, shorter lifetime) have been eliminated first
120
+ - [ ] Every event in a stream belongs to that one entity's own lifecycle none of them describe a different entity or an unrelated system concern
121
+ - [ ] No stream is secretly a collection ("all X") or a log ("everything that happened") wearing an aggregate's name
229
122
  - [ ] Command handler state is reconstructed from stream events — no persistent state stored outside the stream
230
123
  - [ ] Each stream can be independently versioned and replayed without affecting other streams
231
-
124
+ - [ ] A stream that conflates an entity's active life with its historical record has been split (active vs. archived)