@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
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
# Checking Completeness — Worked Examples
|
|
2
|
+
|
|
3
|
+
These are conceptual worked examples (Order/Payment domain) illustrating the completeness-check reasoning this skill applies — useful for understanding the reasoning, but the actual mechanics live in the numbered Workflow sections of the main SKILL.md (reading board state and posting `TASK`/`QUESTION` comments via `handle-comment`), not in writing a document like this.
|
|
4
|
+
|
|
5
|
+
## 1. Field Origin & Destination Matrix
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
Event: OrderCreated
|
|
9
|
+
|
|
10
|
+
Field: orderId
|
|
11
|
+
Origin: Generated by system (UUID)
|
|
12
|
+
Destinations:
|
|
13
|
+
OrderConfirmed event (references)
|
|
14
|
+
OrderStatusView (displays)
|
|
15
|
+
OrderListView (displays)
|
|
16
|
+
OrderShipped event (references)
|
|
17
|
+
Status: Complete
|
|
18
|
+
|
|
19
|
+
Field: customerId
|
|
20
|
+
Origin: CreateOrder command (from UI)
|
|
21
|
+
Destinations:
|
|
22
|
+
OrderStatusView (displays)
|
|
23
|
+
OrderListView (displays)
|
|
24
|
+
Inventory System (knows who ordered)
|
|
25
|
+
Status: Complete
|
|
26
|
+
|
|
27
|
+
Field: items[]
|
|
28
|
+
Origin: CreateOrder command (user selects)
|
|
29
|
+
Destinations:
|
|
30
|
+
OrderStatusView (displays)
|
|
31
|
+
Inventory System (what to reserve)
|
|
32
|
+
Fulfillment System (what to ship)
|
|
33
|
+
Status: Complete
|
|
34
|
+
|
|
35
|
+
Field: total
|
|
36
|
+
Origin: Calculated from items[] and unit prices
|
|
37
|
+
Destinations:
|
|
38
|
+
OrderStatusView (displays)
|
|
39
|
+
OrderListView (displays)
|
|
40
|
+
PaymentSystem (amount to charge)
|
|
41
|
+
Accounting (for reconciliation)
|
|
42
|
+
Status: Complete
|
|
43
|
+
|
|
44
|
+
Field: shippingAddress
|
|
45
|
+
Origin: CreateOrder command (user enters)
|
|
46
|
+
Destinations:
|
|
47
|
+
OrderStatusView (displays)
|
|
48
|
+
Fulfillment System (where to ship)
|
|
49
|
+
Carrier (delivery address)
|
|
50
|
+
Status: Complete
|
|
51
|
+
|
|
52
|
+
Field: createdAt
|
|
53
|
+
Origin: System timestamp when event created
|
|
54
|
+
Destinations:
|
|
55
|
+
OrderStatusView (displays)
|
|
56
|
+
OrderListView (displays)
|
|
57
|
+
Metrics (average order age)
|
|
58
|
+
Status: Complete
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 2. Check All Commands
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
Command: CreateOrder
|
|
65
|
+
Input: customerId, items[], shippingAddress
|
|
66
|
+
customerId → OrderCreated.customerId
|
|
67
|
+
items[] → OrderCreated.items
|
|
68
|
+
shippingAddress → OrderCreated.shippingAddress
|
|
69
|
+
Status: All inputs captured
|
|
70
|
+
|
|
71
|
+
Command: ConfirmOrder
|
|
72
|
+
Input: orderId, paymentMethod
|
|
73
|
+
orderId → OrderConfirmed.orderId (implicit)
|
|
74
|
+
paymentMethod → OrderConfirmed.paymentMethod
|
|
75
|
+
Status: All inputs captured
|
|
76
|
+
|
|
77
|
+
Command: AuthorizePayment
|
|
78
|
+
Input: orderId, paymentId, authCode
|
|
79
|
+
orderId → PaymentAuthorized.orderId (implicit)
|
|
80
|
+
paymentId → PaymentAuthorized.paymentId
|
|
81
|
+
authCode → PaymentAuthorized.authCode
|
|
82
|
+
Status: All inputs captured
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## 3. Check All Read Models
|
|
86
|
+
|
|
87
|
+
```text
|
|
88
|
+
ReadModel: OrderStatusView
|
|
89
|
+
Needs to display:
|
|
90
|
+
orderId ← OrderCreated
|
|
91
|
+
customerId ← OrderCreated
|
|
92
|
+
status ← OrderConfirmed, PaymentAuthorized, etc.
|
|
93
|
+
items ← OrderCreated
|
|
94
|
+
total ← OrderCreated
|
|
95
|
+
createdAt ← OrderCreated
|
|
96
|
+
confirmedAt ← OrderConfirmed
|
|
97
|
+
paymentId ← PaymentAuthorized
|
|
98
|
+
paymentMethod ← OrderConfirmed
|
|
99
|
+
shipmentId ← OrderShipped
|
|
100
|
+
trackingNumber ← OrderShipped
|
|
101
|
+
Status: All fields sourced
|
|
102
|
+
|
|
103
|
+
ReadModel: OrderListView
|
|
104
|
+
Needs to display:
|
|
105
|
+
orderId ← OrderCreated
|
|
106
|
+
customerId ← OrderCreated
|
|
107
|
+
total ← OrderCreated
|
|
108
|
+
status ← OrderConfirmed, OrderCancelled, etc.
|
|
109
|
+
createdAt ← OrderCreated
|
|
110
|
+
Status: All fields sourced
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## 4. Check Slice Coverage
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
Column: CreateOrder (COMMAND)
|
|
117
|
+
Slice defined? Yes — "Place Order"
|
|
118
|
+
Status: Covered
|
|
119
|
+
|
|
120
|
+
Column: OrderStatusView (READMODEL)
|
|
121
|
+
Slice defined? No
|
|
122
|
+
Status: Missing slice — flag as gap
|
|
123
|
+
|
|
124
|
+
Column: ConfirmOrder (COMMAND, linkedTo set — copy of the original in another column)
|
|
125
|
+
Slice defined? N/A — linked copy, exempt
|
|
126
|
+
Status: Skip
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## 5. Check Event Stream Completeness
|
|
130
|
+
|
|
131
|
+
```text
|
|
132
|
+
Scenario: Order from creation to delivery
|
|
133
|
+
|
|
134
|
+
Timeline:
|
|
135
|
+
1. OrderCreated (from CreateOrder command)
|
|
136
|
+
2. OrderConfirmed (from ConfirmOrder command)
|
|
137
|
+
3. PaymentAuthorized (from AuthorizePayment processor command)
|
|
138
|
+
4. InventoryReserved (from ReserveInventory processor command)
|
|
139
|
+
5. OrderShipped (from CreateShipment processor command)
|
|
140
|
+
6. DeliveryConfirmed (from MarkDelivered processor command)
|
|
141
|
+
|
|
142
|
+
Missing events? None identified
|
|
143
|
+
|
|
144
|
+
Alternative paths:
|
|
145
|
+
- OrderCancelled (can happen after OrderCreated or OrderConfirmed)
|
|
146
|
+
- PaymentFailed (can happen during PaymentAuthorized)
|
|
147
|
+
- RefundInitiated (can happen after PaymentFailed or OrderCancelled)
|
|
148
|
+
|
|
149
|
+
Status: All paths covered
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## 6. Check System Boundaries
|
|
153
|
+
|
|
154
|
+
```text
|
|
155
|
+
Order System
|
|
156
|
+
Events: OrderCreated, OrderConfirmed, OrderCancelled
|
|
157
|
+
Processor: None (triggers other systems)
|
|
158
|
+
Status: Clean ownership
|
|
159
|
+
|
|
160
|
+
Payment System
|
|
161
|
+
Events: PaymentAuthorized, PaymentFailed, PaymentRefunded
|
|
162
|
+
Processor: PaymentAuthorizer (listens to OrderConfirmed)
|
|
163
|
+
Status: Clean ownership
|
|
164
|
+
|
|
165
|
+
Inventory System
|
|
166
|
+
Events: InventoryReserved, InventoryReleased
|
|
167
|
+
Processor: InventoryReserver (listens to PaymentAuthorized)
|
|
168
|
+
Status: Clean ownership
|
|
169
|
+
|
|
170
|
+
Fulfillment System
|
|
171
|
+
Events: OrderShipped, DeliveryConfirmed
|
|
172
|
+
Processor: ShipmentCreator (listens to InventoryReserved)
|
|
173
|
+
Status: Clean ownership
|
|
174
|
+
|
|
175
|
+
Notification System
|
|
176
|
+
Events: None (no persistence, info-only)
|
|
177
|
+
Processor: Notifier (listens to all events)
|
|
178
|
+
Status: Cross-cutting concern
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## 7. Define Workflow Step Contracts
|
|
182
|
+
|
|
183
|
+
```text
|
|
184
|
+
Workflow Step 1: CreateOrder (Step Owns: Order Creation)
|
|
185
|
+
|
|
186
|
+
Preconditions (what must exist before this step):
|
|
187
|
+
- Customer must exist
|
|
188
|
+
- Products must exist in catalog
|
|
189
|
+
- User must be authenticated
|
|
190
|
+
|
|
191
|
+
Postconditions (what exists after this step):
|
|
192
|
+
- OrderCreated event exists
|
|
193
|
+
- Event contains: orderId, customerId, items, total, shippingAddress, createdAt
|
|
194
|
+
|
|
195
|
+
Contract: Any system can assume if these postconditions are true,
|
|
196
|
+
the order has been properly created through this step.
|
|
197
|
+
|
|
198
|
+
--- Workflow Step 2: ConfirmOrder (Step Owns: Order Confirmation)
|
|
199
|
+
|
|
200
|
+
Preconditions (depends on Step 1 postcondition):
|
|
201
|
+
- OrderCreated event must exist ( from Step 1 contract)
|
|
202
|
+
- Customer must select payment method
|
|
203
|
+
|
|
204
|
+
Postconditions (what exists after this step):
|
|
205
|
+
- OrderConfirmed event exists
|
|
206
|
+
- Event contains: orderId, paymentMethod, confirmedAt
|
|
207
|
+
|
|
208
|
+
Contract: Any system can assume if these postconditions are true,
|
|
209
|
+
the order has been properly confirmed.
|
|
210
|
+
|
|
211
|
+
--- Workflow Step 3: AuthorizePayment (Step Owns: Payment Authorization)
|
|
212
|
+
|
|
213
|
+
Preconditions (depends on Step 2 postcondition):
|
|
214
|
+
- OrderConfirmed event must exist ( from Step 2 contract)
|
|
215
|
+
- Payment method must be valid
|
|
216
|
+
|
|
217
|
+
Postconditions (what exists after this step):
|
|
218
|
+
- PaymentAuthorized event exists
|
|
219
|
+
- Event contains: paymentId, authCode, amount
|
|
220
|
+
|
|
221
|
+
Contract: Once this postcondition is true, next steps can proceed
|
|
222
|
+
without re-checking payment (trust the contract).
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## 8. Check Field Traceability
|
|
226
|
+
|
|
227
|
+
```markdown
|
|
228
|
+
| Field | Event | Command | Read Model | Processor |
|
|
229
|
+
|-------|-------|---------|-----------|-----------|
|
|
230
|
+
| orderId | OrderCreated | - | All views | All |
|
|
231
|
+
| customerId | OrderCreated | CreateOrder | OrderStatusView | - |
|
|
232
|
+
| items | OrderCreated | CreateOrder | List/Status views | Inventory |
|
|
233
|
+
| total | OrderCreated | - | List/Status views | - |
|
|
234
|
+
| paymentId | PaymentAuthorized | AuthorizePayment | StatusView | Inventory |
|
|
235
|
+
| shipmentId | OrderShipped | CreateShipment | StatusView | Notification |
|
|
236
|
+
| trackingNumber | OrderShipped | - | TrackingView | Notification |
|
|
237
|
+
|
|
238
|
+
Status: All fields traceable
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## 9. Identify Gaps
|
|
242
|
+
|
|
243
|
+
```text
|
|
244
|
+
Analysis: Are there any missing fields?
|
|
245
|
+
- Estimated delivery date?
|
|
246
|
+
→ Need to add to OrderShipped event
|
|
247
|
+
→ Can be calculated from carrier
|
|
248
|
+
→ Add to ShipmentTrackingView
|
|
249
|
+
|
|
250
|
+
- Cancellation reason?
|
|
251
|
+
→ Already in OrderCancelled event
|
|
252
|
+
|
|
253
|
+
- Payment failure reason?
|
|
254
|
+
→ Already in PaymentFailed event
|
|
255
|
+
|
|
256
|
+
- Refund status?
|
|
257
|
+
→ Need to track in RefundInitiated event
|
|
258
|
+
→ Add to PaymentStatusView
|
|
259
|
+
|
|
260
|
+
Actions taken:
|
|
261
|
+
Add estimatedDelivery to OrderShipped
|
|
262
|
+
Add refundStatus to PaymentStatusView
|
|
263
|
+
Add refundInitiatedAt to OrderStatusView
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Legacy markdown-document format (superseded — kept for reference only)
|
|
267
|
+
|
|
268
|
+
Older versions of this skill wrote the completeness check as a markdown report. The actual mechanism today is reading board state and posting `TASK`/`QUESTION` comments via `handle-comment` (see "Board Context" in the main SKILL.md) — this template is kept only so the shape of the information (what a complete completeness report covers) stays documented somewhere.
|
|
269
|
+
|
|
270
|
+
```markdown
|
|
271
|
+
# Completeness Check: [Domain Name]
|
|
272
|
+
|
|
273
|
+
## Workflow Step Contracts
|
|
274
|
+
|
|
275
|
+
### Step 1: CreateOrder
|
|
276
|
+
|
|
277
|
+
**Preconditions**:
|
|
278
|
+
- Customer exists in system
|
|
279
|
+
- Products exist in catalog
|
|
280
|
+
|
|
281
|
+
**Postconditions**:
|
|
282
|
+
- OrderCreated event exists with fields: [list]
|
|
283
|
+
|
|
284
|
+
**Teams that depend on this contract**: [All downstream teams]
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
### Step 2: ConfirmOrder
|
|
289
|
+
|
|
290
|
+
**Preconditions** (depends on Step 1):
|
|
291
|
+
- OrderCreated event exists
|
|
292
|
+
|
|
293
|
+
**Postconditions**:
|
|
294
|
+
- OrderConfirmed event exists with fields: [list]
|
|
295
|
+
|
|
296
|
+
--- [Continue for each workflow step]
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## Field Traceability Matrix
|
|
301
|
+
|
|
302
|
+
### Events
|
|
303
|
+
|
|
304
|
+
| Event | Field | Origin | Destinations | Status |
|
|
305
|
+
|-------|-------|--------|-------------|--------|
|
|
306
|
+
| OrderCreated | orderId | System | ConfirmOrder, Views | |
|
|
307
|
+
| OrderCreated | customerId | CreateOrder | All views | |
|
|
308
|
+
| OrderCreated | items | CreateOrder | Inventory, Views | |
|
|
309
|
+
| OrderCreated | total | Calculated | Views, Payment | |
|
|
310
|
+
| OrderConfirmed | paymentId | AuthorizePayment | Views, Accounting | |
|
|
311
|
+
| OrderShipped | trackingNumber | Carrier | TrackingView | |
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## System Ownership Verification
|
|
316
|
+
|
|
317
|
+
### Order System
|
|
318
|
+
- Events owned: OrderCreated, OrderConfirmed, OrderCancelled
|
|
319
|
+
- Completeness: All order lifecycle events present
|
|
320
|
+
|
|
321
|
+
### Payment System
|
|
322
|
+
- Events owned: PaymentAuthorized, PaymentFailed, PaymentRefunded
|
|
323
|
+
- Completeness: All payment states covered
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Command → Event Verification
|
|
328
|
+
|
|
329
|
+
| Command | Input | Event | Captured |
|
|
330
|
+
|---------|-------|-------|----------|
|
|
331
|
+
| CreateOrder | customerId, items, address | OrderCreated | |
|
|
332
|
+
| ConfirmOrder | paymentMethod | OrderConfirmed | |
|
|
333
|
+
| AuthorizePayment | paymentId, authCode | PaymentAuthorized | |
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## Slice Coverage
|
|
338
|
+
|
|
339
|
+
| Column | Node | Has Slice? | Status |
|
|
340
|
+
|--------|------|-----------|--------|
|
|
341
|
+
| 1 | CreateOrder (COMMAND) | Yes — "Place Order" | |
|
|
342
|
+
| 2 | OrderStatusView (READMODEL) | No | Missing slice |
|
|
343
|
+
| 3 | ConfirmOrder (COMMAND, linked copy) | N/A | Exempt (linkedTo set) |
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Read Model Coverage
|
|
348
|
+
|
|
349
|
+
### OrderStatusView
|
|
350
|
+
- All relevant event data included
|
|
351
|
+
- All user display needs met
|
|
352
|
+
- All processor decision fields present
|
|
353
|
+
|
|
354
|
+
### OrderListView
|
|
355
|
+
- Summary fields captured
|
|
356
|
+
- Filtering/sorting fields present
|
|
357
|
+
- Linked to OrderStatusView for details
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
## Gap Analysis
|
|
362
|
+
|
|
363
|
+
### Issues Found
|
|
364
|
+
1. Estimated delivery date missing
|
|
365
|
+
- Fix: Add to OrderShipped event
|
|
366
|
+
- Type: DateTime (ISO 8601)
|
|
367
|
+
- Source: Calculated from carrier API
|
|
368
|
+
- Status: Will add in next iteration
|
|
369
|
+
|
|
370
|
+
2. Refund tracking incomplete
|
|
371
|
+
- Fix: Add RefundInitiated event timestamp
|
|
372
|
+
- Fix: Add refund status to PaymentStatusView
|
|
373
|
+
- Status: Will add in next iteration
|
|
374
|
+
|
|
375
|
+
### No Critical Gaps
|
|
376
|
+
- All events properly sourced
|
|
377
|
+
- All command inputs captured
|
|
378
|
+
- All read models have data
|
|
379
|
+
- Event flow complete
|
|
380
|
+
- System boundaries clear
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## Readiness Assessment
|
|
385
|
+
|
|
386
|
+
**Overall Completeness**: 95%
|
|
387
|
+
|
|
388
|
+
**Blockers**: None
|
|
389
|
+
|
|
390
|
+
**Ready for Code Generation**: YES
|
|
391
|
+
|
|
392
|
+
**Minor Improvements**:
|
|
393
|
+
- Add estimated delivery date (non-blocking)
|
|
394
|
+
- Enhance refund tracking (non-blocking)
|
|
395
|
+
|
|
396
|
+
**Recommendation**: Proceed to code generation phase.
|
|
397
|
+
```
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eventmodeling-designing-automation-chains
|
|
3
|
+
description: "Step 4b of Event Modeling - design every automation's todo-list read model and, for externally-triggered automations, its two-stage translation chain (external EVENT to internal EVENT). Runs immediately after eventmodeling-identifying-inputs places an AUTOMATION+COMMAND pair, before eventmodeling-identifying-outputs. Use right after Step 4 places any AUTOMATION. Do not use for: screen-facing read models (use eventmodeling-identifying-outputs), placing the automation's own COMMAND (use eventmodeling-identifying-inputs), or system/team boundary swimlanes (use eventmodeling-applying-conways-law)."
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- AskUserQuestion
|
|
6
|
+
- Write
|
|
7
|
+
- Bash
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Designing Automation Chains
|
|
11
|
+
|
|
12
|
+
> **Before doing anything else**, invoke the `connect` skill — if not already connected — to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Do not proceed until it has completed. Consult `learn-eventmodelers-api` only if you need to look up a specific endpoint or field this file doesn't cover — don't load it eagerly.
|
|
13
|
+
|
|
14
|
+
Prefer `mcp__eventmodelers__*` tools when available (registered by the `connect` skill) — the curl blocks below are the fallback for sessions without MCP connected.
|
|
15
|
+
|
|
16
|
+
This is **Step 4b**. It runs immediately after `eventmodeling-identifying-inputs` (Step 4) places an AUTOMATION and its COMMAND, and before `eventmodeling-identifying-outputs` (Step 5) designs any screen-facing read model. Designing an automation's todo list — and, when it applies, its translation chain — while the automation is still fresh from Step 4 is what prevents the alternative: discovering the gap only once Step 5's own verification pass runs, after commands and connections already built on top of the incomplete shape.
|
|
17
|
+
|
|
18
|
+
**Input**: Every AUTOMATION placed in Step 4, each already paired with its own COMMAND in the actor/interaction rows of one column (per `eventmodeling-orchestrating-event-modeling`'s Timeline Alignment Rules).
|
|
19
|
+
**Output to carry forward**: Every automation's todo-list READMODEL, placed and wired; every externally-triggered automation resolved into a two-stage translation chain (external EVENT → todo-list READMODEL → translation AUTOMATION+COMMAND+internal EVENT → worker automation's own todo list).
|
|
20
|
+
**Gate**: No AUTOMATION on the board lacks an incoming `READMODEL → AUTOMATION` connection to a todo-list read model, and no automation's todo list is opened directly by another system's (second-swimlane) event.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Every automation needs a todo-list read model — no exemption
|
|
25
|
+
|
|
26
|
+
**Every AUTOMATION needs a todo-list read model — this is not optional, and there is no "pure relay" exemption.** An automation is a processor: it reacts to events, decides what work is outstanding, and issues commands to get that work done. The read model that tells it what's outstanding is its **todo list** — a queue of pending work items, not a snapshot of current entity state.
|
|
27
|
+
|
|
28
|
+
**The pattern**: one or more events *open* an item on the todo list (something now needs doing); one or more events *close* it (the work is done — remove the item). A todo list can be opened and closed by more than one event type on either side, and the set of opening events doesn't need to match the set of closing events in count or shape — whatever the domain calls for.
|
|
29
|
+
|
|
30
|
+
**Worked example**: an automation that reacts to `CustomerRegistered` by sending a welcome notification.
|
|
31
|
+
- Todo list: **NotificationsToSend** — one row per pending notification.
|
|
32
|
+
- `CustomerRegistered` **opens** a row (a notification now needs sending).
|
|
33
|
+
- `NotificationSent` (the event this automation's own resulting command produces) **closes** that row (removes it — the list only ever shows outstanding work).
|
|
34
|
+
- The automation (`Send Welcome Notification`) reads `NotificationsToSend`, and for every open row issues `SendNotification`.
|
|
35
|
+
|
|
36
|
+
Even an automation that looks like a "pure signal relay" still has a todo list — model it anyway: it documents that the automation is idempotent/complete once its own event fires, and keeps every automation consistent with the same `READMODEL → AUTOMATION → COMMAND → EVENT` pattern instead of silently exempting some as "too simple to need one."
|
|
37
|
+
|
|
38
|
+
## The translation-chain rule for external triggers
|
|
39
|
+
|
|
40
|
+
**There is no such thing as an invisible or informal "signal" — a trigger is always a real EVENT node**, placed in a second swimlane when it belongs to another system (see `eventmodeling-brainstorming-events`'s swimlane rule).
|
|
41
|
+
|
|
42
|
+
**An automation can only ever be directly triggered by an internal event — never by another system's event.** A "trigger" arriving from a second swimlane is not itself the thing that drives your domain's work; it first has to be *translated* into an internal event. Do not model this as one automation whose todo list is opened by the external EVENT and that also does the real work (e.g. an automation reading a todo list opened by `ReservationRequested` from another system's swimlane and directly issuing `ReserveCopy`) — that lets an external system trigger domain work with no translation step, which this model doesn't allow. **Apply this now, in Step 4b** — Conway's Law (Step 6) only confirms the boundary, it doesn't introduce the chain. When an integration trigger comes from another team's system, model it as **two chained automations**, never one:
|
|
43
|
+
|
|
44
|
+
1. **Translation automation** — converts the external fact into an internal one; the other system's own decision logic is out of scope. Its todo list is opened by the external EVENT — the one and only place an external EVENT may open a todo list. **It is not closed by the internal EVENT its own command produces, and gets no backward arrow.** A translation automation's job is an instantaneous, always-succeeding relay: there is no real work-in-progress window between "signal arrived" and "internal fact recorded" worth modeling as an open/close lifecycle, unlike a worker automation that can genuinely have pending items. This read model exists only to satisfy "every automation reads from a todo list," not to accumulate and drain a queue — so it stays open-ended: fed by the external EVENT, read by the automation, never closed.
|
|
45
|
+
- **Three separate columns**, left to right: `[external EVENT] → [todo-list READMODEL] → [AUTOMATION + COMMAND + internal EVENT]`. Never crammed into one or two — the "one EVENT per column" rule applies here too.
|
|
46
|
+
- **Name the internal EVENT for its business meaning, not the transport** — usually the same name as the external EVENT (e.g. external `CopyReserved` → internal `CopyReserved`; the swimlane already shows which is which), never a mechanical `<X>SignalReceived`/`<X>RequestReceived` suffix. Same for the automation/command: `Record Reservation`/`RecordReservation`, not `Record Reservation Signal`/`RecordReservationSignal`.
|
|
47
|
+
- Its command and event carry no business decision — they only exist to produce the internal fact the next automation needs.
|
|
48
|
+
2. **Worker automation** — the one that does the actual work (the domain reaction the process is really about, e.g. `ReserveCopy`). Its todo list is opened **only** by the internal EVENT the translation automation produced (this chapter's own swimlane) — never by the external EVENT directly — and closed by whatever event marks that work done. Unlike the translation stage, the worker's todo list keeps its normal open/close accumulator shape, because real pending work can sit there (it's the point where actual domain decisions happen).
|
|
49
|
+
|
|
50
|
+
Wire the todo lists differently for each automation in the chain: for the translation automation, the external EVENT (second swimlane) **opens** the row and nothing closes it; for the worker automation, the internal EVENT **opens** its row and its own resulting EVENT **closes** it (backward arrow, per the exemption below). `EVENT → READMODEL` connections from both swimlanes are unaffected by which swimlane the event sits in.
|
|
51
|
+
|
|
52
|
+
## Fields on a todo-list read model
|
|
53
|
+
|
|
54
|
+
A todo-list read model's fields describe the pending item — the identity it's about (e.g. `customerId`) plus enough context to act on it (e.g. `email`, `notificationType`). Do not add a `status` field to mark items done — a todo list's "open" state is *membership in the list itself* (the row exists at all), not a status flag on a row that never leaves. If the same underlying data is also useful with an explicit status column for a different consumer, that is a different read model, not this one.
|
|
55
|
+
|
|
56
|
+
Every field must set a `mapping` per `eventmodeling-identifying-outputs`'s field data lineage rules (`"<EventTitle>.<fieldName>"`, `"latest:..."`, `"aggregate:..."`, `"derived:..."`), and `"cardinality"` (`"Single"` unless the field genuinely holds a list).
|
|
57
|
+
|
|
58
|
+
## Placement — todo-list READMODEL, one column before its automation
|
|
59
|
+
|
|
60
|
+
The todo-list read model goes in the interaction lane, **one column before** its automation (actor lane) — the automation's own column already holds the COMMAND it issues, so the read model can never share that column.
|
|
61
|
+
|
|
62
|
+
**Every `node:created` call MUST include `cellId`.** Without it the node has no cell reference and will appear stranded at position 0,0 — not in any timeline column.
|
|
63
|
+
|
|
64
|
+
**Prefer MCP** — `place_element` finds/creates the empty interaction cell one column before the automation and creates the node in one call:
|
|
65
|
+
```
|
|
66
|
+
mcp__eventmodelers__place_element {
|
|
67
|
+
"boardId": "<BOARD_ID>",
|
|
68
|
+
"timelineId": "<CHAPTER_ID>",
|
|
69
|
+
"elementType": "READMODEL",
|
|
70
|
+
"title": "NotificationsToSend",
|
|
71
|
+
"columnIndex": <automationColumnIndex - 1>
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
Then set `meta.fields` on the returned node id:
|
|
75
|
+
```
|
|
76
|
+
mcp__eventmodelers__submit_node_events {
|
|
77
|
+
"boardId": "<BOARD_ID>",
|
|
78
|
+
"events": [{
|
|
79
|
+
"id": "<event-uuid>", "eventType": "node:changed", "nodeId": "<returned-node-id>",
|
|
80
|
+
"boardId": "<BOARD_ID>", "timestamp": 1234567890,
|
|
81
|
+
"meta": {"type": "READMODEL", "title": "NotificationsToSend", "fields": [...]}
|
|
82
|
+
}]
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Fallback (no MCP):** see `references/api-fallback.md` — "Placement — todo-list READMODEL, one column before its automation".
|
|
87
|
+
|
|
88
|
+
**Place every node in a translation chain with `autoConnect: false`** (`place_element` / `create_screen` / `submit_node_events` all take the flag). A chain's columns are inserted into the middle of an existing timeline, so the default nearest-left auto-connect will wire the new todo-list READMODEL or internal EVENT to whatever unrelated event sits in the column before it — the recurring "spurious auto-connect edge near an automation chain" cleanup. Suppress it and build the chain's edges yourself in the `set_connections` batch below, then confirm with `validate_model`.
|
|
89
|
+
|
|
90
|
+
> **Never call `drop` after using `cellId` in `node:created`.** The drop endpoint adds a second cell reference without removing the first.
|
|
91
|
+
|
|
92
|
+
For a **translation-chain automation**, place its three columns left to right in the same pass: `[external EVENT]`, `[todo-list READMODEL]`, `[AUTOMATION + COMMAND + internal EVENT]` — the external EVENT normally already exists (placed in Step 1/brainstorming, second swimlane); if it doesn't, place it there first.
|
|
93
|
+
|
|
94
|
+
## Wiring connections
|
|
95
|
+
|
|
96
|
+
1. **READMODEL → AUTOMATION first** — the automation reads its own todo list. The closing connection below is only accepted once this edge exists.
|
|
97
|
+
```
|
|
98
|
+
mcp__eventmodelers__set_connection { "boardId": "<BOARD_ID>", "source": "<readmodelNodeId>", "target": "<automationNodeId>", "action": "connect" }
|
|
99
|
+
```
|
|
100
|
+
2. **Every opening EVENT → READMODEL.**
|
|
101
|
+
```
|
|
102
|
+
mcp__eventmodelers__set_connection { "boardId": "<BOARD_ID>", "source": "<openingEventNodeId>", "target": "<readmodelNodeId>", "action": "connect" }
|
|
103
|
+
```
|
|
104
|
+
3. **Every closing EVENT → READMODEL — worker-stage todo lists only.** Including the automation's own resulting event, even though that event is produced by the command this same automation issues. This is not a backward arrow: `EVENT → READMODEL` connections are exempt from column ordering when the read model already has a `READMODEL → AUTOMATION` edge (see `learn-eventmodelers-api` §3) — this todo-list read model qualifies because of the edge from step 1 above. A read model in this shape is a live projection, not a frozen snapshot — a later event closing an earlier-opened item is the normal case, not an exception to reach for only when convenient. **Do not add this edge for a translation automation's todo list** — it has no closing event at all (see the translation-chain rule above); wiring one back is a modeling error, not a convenience.
|
|
105
|
+
|
|
106
|
+
**Fallback (no MCP)** — same three edges via `POST /connections` with `{"source":"...","target":"..."}`, in the same order.
|
|
107
|
+
|
|
108
|
+
Skip a connection silently if the target cell is empty (the element may not exist yet). Log each created arrow, e.g. `→ connected READMODEL→AUTOMATION "NotificationsToSend"→"Send Welcome Notification"`.
|
|
109
|
+
|
|
110
|
+
If this step is designing more than one automation's chain in the same pass, batch every connection from every automation into one `set_connections` call (with `compact: true`) instead of one `set_connection` per edge — `set_connections` still applies its entries **in order**, so keep each automation's own three-edge sequence intact (READMODEL→AUTOMATION before its closing EVENT→READMODEL) within the combined array; different automations' triples can be interleaved or concatenated freely since they don't depend on each other.
|
|
111
|
+
|
|
112
|
+
## Verification (run before moving to Step 5)
|
|
113
|
+
|
|
114
|
+
Run `validate_model` (`{boardId, chapterId}`) first — with the chain placed `autoConnect: false`, its `backward-arrows` finding confirms no stray nearest-left edge was created and every real edge points the right way, and `command-issuers` confirms each chain's COMMAND is issued only by its own AUTOMATION. Then re-fetch every AUTOMATION on the board (`get_nodes`, `type: "AUTOMATION"`) and check each one:
|
|
115
|
+
|
|
116
|
+
1. Does it have an incoming `READMODEL → AUTOMATION` connection to a todo-list read model? An AUTOMATION is **never** exempt — if not, design and wire it now.
|
|
117
|
+
2. Is its todo list opened by an internal event only, **unless it is itself a translation automation** (which is the one case a second-swimlane event may open a todo list)? If a worker automation's todo list is opened directly by another system's event, that automation is missing its translation chain — split it into translation + worker automations per the rule above.
|
|
118
|
+
3. If it's a **translation** automation, does its todo list have no closing edge — i.e. no connection from its own resulting internal EVENT back to its own todo-list read model? If one exists, remove it: a translation automation's todo list is never closed.
|
|
119
|
+
4. If it's a **worker** automation, does its todo list have a proper closing edge from its own resulting event? If not, add it.
|
|
120
|
+
5. Does the todo-list read model's field set avoid a `status` flag (membership in the list is the state)?
|
|
121
|
+
|
|
122
|
+
List the result (connected / chain-resolved) for every automation checked — this is the evidence that `eventmodeling-identifying-outputs`'s later per-node verification pass (which re-checks automations defensively) finds nothing left to do here.
|
|
123
|
+
|
|
124
|
+
## Quality Checklist
|
|
125
|
+
|
|
126
|
+
- [ ] Every AUTOMATION has an incoming `READMODEL → AUTOMATION` connection to a todo-list read model — no exemption, even for a simple relay
|
|
127
|
+
- [ ] No automation's todo list is opened directly by another system's (second-swimlane) EVENT unless that automation is itself the translation automation
|
|
128
|
+
- [ ] Every externally-triggered automation is modeled as two chained automations (translation + worker), never one
|
|
129
|
+
- [ ] Every **worker**-stage todo-list read model's opening and closing events are identified, including the automation's own resulting event as a closing event
|
|
130
|
+
- [ ] Every **translation**-stage todo-list read model has an opening event (the external EVENT) and **no closing event at all** — no backward arrow from its own internal EVENT back to its own todo list
|
|
131
|
+
- [ ] No todo-list read model uses a `status` field instead of list membership
|
|
132
|
+
- [ ] Every todo-list read model sits one column before its automation, never sharing its column
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Designing Automation Chains — 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
|
+
## Placement — todo-list READMODEL, one column before its automation
|
|
6
|
+
|
|
7
|
+
1. Fetch the chapter to find the interaction row ID (`timelineData.rows`, `type === "interaction"`) and confirm the cell one column before the automation is free.
|
|
8
|
+
2. If that column doesn't exist yet or its interaction row is occupied, insert a new column immediately before the automation's column (`{"index": automationColumnIndex}`, shifting the automation right).
|
|
9
|
+
3. `cellId = interactionRow.id + "-" + columnId`
|
|
10
|
+
4. Create the node:
|
|
11
|
+
```bash
|
|
12
|
+
curl -s -X POST "$BASE_URL/api/org/$ORG_ID/boards/$BOARD_ID/nodes/events" \
|
|
13
|
+
-H "x-token: $TOKEN" -H "x-board-id: $BOARD_ID" -H "x-user-id: designing-automation-chains" \
|
|
14
|
+
-H "Content-Type: application/json" \
|
|
15
|
+
-d '[{
|
|
16
|
+
"id":"<event-uuid>","eventType":"node:created","nodeId":"<node-uuid>",
|
|
17
|
+
"boardId":"<BOARD_ID>","timestamp":1234567890,
|
|
18
|
+
"chapterId":"<CHAPTER_ID>","cellId":"<interactionRowId>-<columnId>",
|
|
19
|
+
"meta":{"type":"READMODEL","title":"NotificationsToSend","fields":[...]}
|
|
20
|
+
}]'
|
|
21
|
+
```
|