@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.
- package/package.json +1 -1
- package/shared/skills/learn-eventmodelers-api/SKILL.md +22 -13
- 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 +12 -380
- 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 +45 -290
- 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 +15 -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-core-rules/SKILL.md +182 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-automation-chains/SKILL.md +148 -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 +48 -448
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/references/examples.md +167 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +31 -380
- 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 +33 -393
- 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 +54 -454
- 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-interview-protocol/SKILL.md +31 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/SKILL.md +37 -184
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/domain-patterns.md +58 -99
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/patterns.md +82 -163
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/SKILL.md +86 -78
- 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 +5 -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 +22 -51
- 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 +29 -382
- 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 +12 -349
- 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 +69 -107
- 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 +75 -160
- 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 +34 -180
- package/stacks/modeling-kit/templates/.claude/skills/place-element/references/api-fallback.md +203 -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
|
@@ -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
|
+
```
|
package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-interview-protocol/SKILL.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eventmodeling-interview-protocol
|
|
3
|
+
description: Shared procedure for deciding whether to ask the user clarifying questions before an event-modeling step proceeds, and how to record what was decided. Not a step of its own — referenced by other eventmodeling-* skills' Interview Phase section. Do not use standalone.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Interview Protocol
|
|
7
|
+
|
|
8
|
+
Shared by every event-modeling step that has an "Interview Phase" section. A step's own SKILL.md defines only what's specific to it — when to interview and its Critical Questions. Everything below is common to all of them.
|
|
9
|
+
|
|
10
|
+
## When to ask
|
|
11
|
+
|
|
12
|
+
Missing information, or something ambiguous that this step needs? Ask the user — using the step's own Critical Questions as a guide, via `AskUserQuestion` where appropriate. Follow any listed follow-up trigger based on the answer.
|
|
13
|
+
|
|
14
|
+
Already have everything the step needs? Skip straight to the step's own workflow — don't ask questions whose answers you already have.
|
|
15
|
+
|
|
16
|
+
**Unless told not to ask** (an autonomous/unattended run, or the user has said not to stop for questions): don't block. Proceed with the most reasonable assumption for anything missing, and say so plainly in this step's findings below — visibly, so it can be corrected later. Never silently guess.
|
|
17
|
+
|
|
18
|
+
## Recording the outcome
|
|
19
|
+
|
|
20
|
+
Append to the project's event modeling file: `.trogonai/interviews/[project-name]/EVENTMODELING.md`, under a section for this step:
|
|
21
|
+
|
|
22
|
+
```markdown
|
|
23
|
+
## <Step Number>. <Step Name> (<skill-name>)
|
|
24
|
+
[What was asked and decided — or, if nothing was asked, what was assumed and why]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Then add or update this step's row in the `## Interview Trail` table (create it if this is the first step to run):
|
|
28
|
+
|
|
29
|
+
```markdown
|
|
30
|
+
| <Step Number> | <skill-name> | Done | <one-line summary of key outputs> |
|
|
31
|
+
```
|
package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: eventmodeling-optimizing-stream-design
|
|
3
|
-
description: "
|
|
3
|
+
description: "Validate and fix an entity's event timeline boundary — is it anchored on a single business identity, or is it secretly a collection/log that will grow unbounded? Use when concerned about a timeline mixing concerns, reviewing timeline boundaries, or when a timeline feels like it's absorbing unrelated events. Do not use for: designing the initial event model structure (use eventmodeling-designing-event-models) or general model validation (use eventmodeling-validating-event-models)."
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- AskUserQuestion
|
|
6
6
|
- Write
|
|
@@ -8,224 +8,77 @@ allowed-tools:
|
|
|
8
8
|
|
|
9
9
|
# Optimizing Stream Design
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
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.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## Timeline Boundary Optimization
|
|
14
14
|
|
|
15
|
-
**
|
|
15
|
+
**Purpose**: Validate timeline boundaries — confirm each entity's event timeline 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 modeled further.
|
|
16
16
|
|
|
17
|
-
|
|
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 lifetime → ask "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
|
|
52
|
-
|
|
53
|
-
### Capturing Interview Findings
|
|
54
|
-
|
|
55
|
-
Append findings to the project's event modeling file:
|
|
56
|
-
|
|
57
|
-
**File**: `.trogonai/interviews/[project-name]/EVENTMODELING.md`
|
|
58
|
-
|
|
59
|
-
Use Write tool to add/update this section:
|
|
60
|
-
|
|
61
|
-
```markdown
|
|
62
|
-
## Optimizing Stream Design (eventmodeling-optimizing-stream-design)
|
|
63
|
-
|
|
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]
|
|
69
|
-
|
|
70
|
-
### Optimization Decisions
|
|
71
|
-
- Streams requiring redesign: [list or "None"]
|
|
72
|
-
- Streams where snapshotting is justified: [list or "None"]
|
|
73
|
-
- Streams within acceptable bounds: [list]
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
Update Interview Trail:
|
|
77
|
-
```markdown
|
|
78
|
-
| Optimization | eventmodeling-optimizing-stream-design | Done | Stream growth estimates, SLA review, snapshotting decisions |
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
---
|
|
82
|
-
|
|
83
|
-
## Stream Design Optimization
|
|
84
|
-
|
|
85
|
-
**Purpose**: Optimize event stream design by validating stream boundaries, estimating growth, and making snapshotting decisions based on design quality—not just size.
|
|
86
|
-
|
|
87
|
-
**Applies To**: Any domain - e-commerce, banking, SaaS, marketplace, healthcare, etc.
|
|
17
|
+
**Applies To**: Any domain — e-commerce, banking, SaaS, marketplace, healthcare, etc.
|
|
88
18
|
|
|
89
19
|
**When to Use**:
|
|
90
|
-
- After defining
|
|
91
|
-
- When
|
|
92
|
-
-
|
|
93
|
-
- During performance planning to determine snapshotting strategy
|
|
94
|
-
- When redesigning streams for scalability
|
|
20
|
+
- After defining events in domain analysis
|
|
21
|
+
- When a timeline feels like it's growing for reasons unrelated to one entity's own story
|
|
22
|
+
- When redesigning a timeline whose boundary turned out to be wrong
|
|
95
23
|
|
|
96
24
|
**What It Does**:
|
|
97
|
-
1.
|
|
98
|
-
2.
|
|
99
|
-
3.
|
|
100
|
-
4.
|
|
101
|
-
5. Balances performance optimization against complexity
|
|
102
|
-
6. Provides snapshotting strategy without over-engineering
|
|
25
|
+
1. Checks that each timeline has a single, natural business identity
|
|
26
|
+
2. Identifies timelines that are actually collections or logs in disguise
|
|
27
|
+
3. Recommends the correct boundary when one is wrong
|
|
28
|
+
4. Distinguishes "this timeline is long because the entity has a long history" (fine) from "this timeline is long because it's absorbing events that don't belong to it" (a boundary bug)
|
|
103
29
|
|
|
104
30
|
---
|
|
105
31
|
|
|
106
|
-
## Core Principle:
|
|
32
|
+
## Core Principle: Get the Identity Right
|
|
107
33
|
|
|
108
34
|
**Golden Rule**:
|
|
109
|
-
> If
|
|
35
|
+
> If a timeline feels like it's growing for the wrong reasons, first ask: "Does this timeline actually have one business identity, or is it a collection/log wearing an entity's name?"
|
|
110
36
|
|
|
111
|
-
|
|
37
|
+
A long timeline is not, by itself, evidence of a design problem — an account open for thirty years is correctly one long timeline. What *is* always a design problem is a timeline whose events don't all belong to the same entity's own lifecycle.
|
|
112
38
|
|
|
113
39
|
---
|
|
114
40
|
|
|
115
|
-
##
|
|
41
|
+
## Timeline Boundary Review
|
|
116
42
|
|
|
117
|
-
|
|
43
|
+
For each entity's timeline in scope, work through:
|
|
118
44
|
|
|
119
|
-
|
|
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
|
-
```
|
|
45
|
+
### 1. Name the identity
|
|
126
46
|
|
|
127
|
-
|
|
47
|
+
What single business entity does this timeline represent the history of? Write it down explicitly (e.g. `orderId`, not "orders").
|
|
128
48
|
|
|
129
|
-
|
|
49
|
+
### 2. Check every event against that identity
|
|
130
50
|
|
|
131
|
-
|
|
51
|
+
Does each event on the timeline 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).
|
|
132
52
|
|
|
133
|
-
|
|
53
|
+
### 3. Classify the result
|
|
134
54
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
|
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 |
|
|
55
|
+
| Result | Meaning | Action |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| Every event belongs to one clear entity | Boundary is correct | Keep as-is, regardless of how long the history gets |
|
|
58
|
+
| 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 an event timeline |
|
|
59
|
+
| Events span unrelated concerns (users, orders, payments mixed) | Pattern 4 (Event Log) anti-pattern | Split into one timeline per concern |
|
|
60
|
+
| Timeline conflates an entity's active life with its historical record | Missing the Pattern 5 split | Separate active vs. archived/historical timelines |
|
|
161
61
|
|
|
162
62
|
---
|
|
163
63
|
|
|
164
64
|
## Reference Files
|
|
165
65
|
|
|
166
|
-
**
|
|
167
|
-
- 5
|
|
168
|
-
-
|
|
169
|
-
- Red flags that indicate
|
|
170
|
-
- Tips for
|
|
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
|
|
66
|
+
**Timeline Boundary Design**: See [patterns.md](references/patterns.md) for:
|
|
67
|
+
- 5 boundary patterns (single entity, composite, collection anti-pattern, event-log anti-pattern, historical)
|
|
68
|
+
- The timeline boundary decision tree
|
|
69
|
+
- Red flags that indicate the boundary — not the volume — is wrong
|
|
70
|
+
- Tips for finding the right boundary
|
|
177
71
|
|
|
178
72
|
**Domain-Specific Guidance**: See [domain-patterns.md](references/domain-patterns.md) for:
|
|
179
73
|
- E-commerce patterns (orders, carts, accounts)
|
|
180
74
|
- Banking patterns (accounts, transactions, loans)
|
|
181
75
|
- 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
76
|
|
|
221
77
|
---
|
|
222
78
|
|
|
223
79
|
## Quality Checklist
|
|
224
80
|
|
|
225
|
-
- [ ] Each
|
|
226
|
-
- [ ]
|
|
227
|
-
- [ ]
|
|
228
|
-
- [ ]
|
|
229
|
-
- [ ] Command handler state is reconstructed from stream events — no persistent state stored outside the stream
|
|
230
|
-
- [ ] Each stream can be independently versioned and replayed without affecting other streams
|
|
231
|
-
|
|
81
|
+
- [ ] Each timeline is identified by a business entity identity (e.g., `orderId`), not a category or type
|
|
82
|
+
- [ ] Every event on a timeline belongs to that one entity's own lifecycle — none of them describe a different entity or an unrelated system concern
|
|
83
|
+
- [ ] No timeline is secretly a collection ("all X") or a log ("everything that happened") wearing an entity's name
|
|
84
|
+
- [ ] A timeline that conflates an entity's active life with its historical record has been split (active vs. archived)
|