@eventmodelers/cli 1.0.37 → 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 +10 -3
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-applying-conways-law/SKILL.md +3 -61
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/SKILL.md +24 -93
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/SKILL.md +2 -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 +23 -7
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/SKILL.md +50 -223
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/references/examples.md +30 -120
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +3 -78
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/SKILL.md +3 -50
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md +3 -54
- 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 +27 -67
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/domain-patterns.md +15 -15
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/patterns.md +44 -52
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/SKILL.md +14 -15
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-plotting-events/SKILL.md +4 -0
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/SKILL.md +3 -15
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/SKILL.md +3 -50
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-translating-external-events/SKILL.md +4 -56
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/SKILL.md +58 -97
- package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models-checklist/SKILL.md +72 -127
- package/stacks/modeling-kit/templates/.claude/skills/place-element/SKILL.md +15 -1
- package/stacks/modeling-kit/templates/.claude/skills/place-element/references/api-fallback.md +11 -1
package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: eventmodeling-designing-event-models
|
|
3
|
-
description: "Designs event
|
|
3
|
+
description: "Designs the event model for a business process — maps Commands, Events, and Read Models with clear causality. Events are business facts; Read Models are projections built from them. Use when designing the Command/Event/Read-Model structure from domain analysis. Do not use for: brainstorming events from scratch (use eventmodeling-brainstorming-events), or checking whether an event belongs to the right entity/timeline (use eventmodeling-optimizing-stream-design)."
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- AskUserQuestion
|
|
6
6
|
- Write
|
|
@@ -11,260 +11,87 @@ allowed-tools:
|
|
|
11
11
|
|
|
12
12
|
> **Before doing anything else**, invoke the `connect` skill — if not already connected — to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Do not proceed until it has completed. Consult `learn-eventmodelers-api` only if you need to look up a specific endpoint or field this file doesn't cover — don't load it eagerly.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
**When to Interview**: Skip if the user has specified: stream identity strategy, command-specific state needs, and read model requirements. Interview when stream boundaries or state design are unclear.
|
|
17
|
-
|
|
18
|
-
**Interview Strategy**: Establish stream identity and per-command state boundaries before designing. Ambiguous boundaries are the primary cause of the DDD aggregate anti-pattern appearing in event-sourced models.
|
|
19
|
-
|
|
20
|
-
### Critical Questions
|
|
21
|
-
|
|
22
|
-
1. **Stream Identity** (Impact: Determines how events are grouped into streams)
|
|
23
|
-
- Question: "What's the entity that owns events? (e.g., orderId, reviewId, customerId) What's the lifetime? Single transaction or years?"
|
|
24
|
-
- Why it matters: Wrong stream identity causes design problems; correct identity keeps streams appropriately scoped
|
|
25
|
-
- Follow-up triggers: If multiple candidates → ask "Which entity's identity would you use to load events for a single command decision?"
|
|
26
|
-
|
|
27
|
-
2. **Minimal State vs Bundled State** (Impact: Prevents DDD aggregate anti-pattern)
|
|
28
|
-
- Question: "Will different commands need different state? Or does every command need the same full state?"
|
|
29
|
-
- Why it matters: Each command should have minimal, command-specific state—not bundled DDD aggregates
|
|
30
|
-
- Follow-up triggers: If "same full state" → walk through two commands and ask what each actually reads during validation
|
|
31
|
-
|
|
32
|
-
### Interview Flow
|
|
33
|
-
|
|
34
|
-
**Conditional Entry**:
|
|
35
|
-
```text
|
|
36
|
-
If user has provided:
|
|
37
|
-
- Stream identity (which entity ID anchors the stream)
|
|
38
|
-
- AND at least two commands with explicitly different state needs documented
|
|
39
|
-
- AND read model requirements (what queries the UI or processors make)
|
|
40
|
-
|
|
41
|
-
Then: Skip interview, proceed directly to design
|
|
42
|
-
|
|
43
|
-
Else: Conduct interview
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
**Phase 1: Stream Boundaries** (Question 1)
|
|
47
|
-
- Confirm which entity anchors the stream
|
|
48
|
-
- Establish stream lifetime expectations
|
|
49
|
-
- Identify whether multiple candidate roots exist and resolve them
|
|
50
|
-
|
|
51
|
-
**Phase 2: State Design** (Question 2)
|
|
52
|
-
- Confirm per-command state isolation
|
|
53
|
-
- Identify whether DDD aggregate thinking is present upfront
|
|
54
|
-
- Establish minimal state shapes for at least two commands
|
|
55
|
-
|
|
56
|
-
### Capturing Interview Findings
|
|
57
|
-
|
|
58
|
-
Append findings to the project's event modeling file:
|
|
59
|
-
|
|
60
|
-
**File**: `.trogonai/interviews/[project-name]/EVENTMODELING.md`
|
|
61
|
-
|
|
62
|
-
Use Write tool to add/update this section:
|
|
63
|
-
|
|
64
|
-
```markdown
|
|
65
|
-
## Designing Event Models (eventmodeling-designing-event-models)
|
|
66
|
-
|
|
67
|
-
### Stream Identity
|
|
68
|
-
[From Q1: Which entity? What identity key? Lifetime?]
|
|
69
|
-
|
|
70
|
-
### Per-Command State Decisions
|
|
71
|
-
[From Q2: Which commands need different state? Initial minimal state shapes?]
|
|
72
|
-
|
|
73
|
-
### Design Decisions
|
|
74
|
-
- Stream root: [entity name] identified by [id field]
|
|
75
|
-
- State isolation: [confirmed / DDD pattern caught and corrected]
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
Update Interview Trail:
|
|
79
|
-
```markdown
|
|
80
|
-
| Design | eventmodeling-designing-event-models | Done | Stream identity, per-command state shapes |
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
---
|
|
84
|
-
|
|
85
|
-
## Core Architectural Rule
|
|
86
|
-
|
|
87
|
-
**NEVER use a "DDD Aggregate Root" (bundled state) for command validation** Every command handler has its own minimal state projection. What DDD calls an "aggregate root" is actually a **read model**, not command-validation state.
|
|
88
|
-
|
|
89
|
-
The anti-pattern is a single bundled "aggregate" state object reused across every command handler; the correct approach is one minimal, command-specific state shape per command (e.g. `ConfirmOrderState` carries only `status`/`orderId`, while `ShipOrderState` also needs `paymentId`), with any rich, all-fields view kept entirely separate as a read model rather than fed into command validation. A full worked WRONG/CORRECT comparison (Order domain) is in `references/examples.md`.
|
|
14
|
+
This step applies the shared element rules in **`eventmodeling-core-rules`** — read it once per session if you haven't already; it defines what a COMMAND/EVENT/READMODEL/SCREEN/AUTOMATION is, how each is named, and the anti-patterns to reject, so this step doesn't restate them.
|
|
90
15
|
|
|
91
16
|
## Purpose
|
|
92
|
-
Converts domain analysis into the event sourcing architecture pattern:
|
|
93
|
-
|
|
94
|
-
**UI/Processor** → **Command** → [Command State Read Model] → **Event** → **Query Read Models** - **UI/Processor**: Entry points that trigger intent
|
|
95
|
-
- **Command**: Intent data (can be rejected)
|
|
96
|
-
- **Stream Root**: Logical grouping of immutable events (NOT a DDD aggregate bundle)
|
|
97
|
-
- **Command State Read Model**: Minimal projection derived from events, optimized for this specific command's validation. Each command gets its own read model interface. Different commands = different shapes. (Categorized as "Command State" for semantic clarity)
|
|
98
|
-
- **Event**: Result of successful command (immutable fact: command data + implicit context)
|
|
99
|
-
- **Query Read Models**: Rich projections of events optimized for UI/Processor queries. Separate from command state. (Categorized as "Query Models" for semantic clarity)
|
|
100
|
-
|
|
101
|
-
## Workflow
|
|
102
17
|
|
|
103
|
-
|
|
18
|
+
Converts domain analysis into the event modeling structure:
|
|
104
19
|
|
|
105
|
-
|
|
106
|
-
Events are the immutable source of truth. Each stream holds facts about one entity:
|
|
107
|
-
- **Stream Name**: Entity type + identity (Order:order-123)
|
|
108
|
-
- **Event Type**: What changed? (past tense: Created, Confirmed, Shipped)
|
|
109
|
-
- **Event Data**: Combines command input + implicit stream state facts
|
|
110
|
-
- **Causality**: Triggered by which command?
|
|
20
|
+
**UI/Processor** → **Command** → **Event** → **Read Model** → **UI/Processor**
|
|
111
21
|
|
|
112
|
-
|
|
22
|
+
- **UI/Processor**: entry points that trigger intent
|
|
23
|
+
- **Command**: business intent, expressed in business language, can be rejected
|
|
24
|
+
- **Event**: a business fact — the result of a successful command
|
|
25
|
+
- **Read Model**: a projection of events, shaped for a specific query need
|
|
113
26
|
|
|
114
|
-
|
|
115
|
-
- Events are **immutable facts** from successful commands
|
|
116
|
-
- Event data = command input + implicit stream state context
|
|
117
|
-
- Stream identity is explicit (Order:order-123)
|
|
118
|
-
- Event order matters for state reconstruction
|
|
119
|
-
- Never modify or delete events
|
|
120
|
-
- Events only exist if command succeeded
|
|
121
|
-
|
|
122
|
-
### 2. Design Command State Read Models (Minimal Per-Command)
|
|
123
|
-
|
|
124
|
-
**Critical Rule: Each command must have its own read model (command state). NEVER share read models between commands.** **Naming Convention (for Automation)**:
|
|
125
|
-
- `[CommandName]State` = Implemented command state read model
|
|
126
|
-
- `[CommandName]StateToDo` = Planned command state read model (marked for implementation)
|
|
27
|
+
## Workflow
|
|
127
28
|
|
|
128
|
-
|
|
129
|
-
- `PublishReviewState` = implemented
|
|
130
|
-
- `EditReviewStateToDo` = planned, needs implementation
|
|
131
|
-
- `SellerRespondState` = implemented
|
|
29
|
+
Given a domain analysis, design the event model:
|
|
132
30
|
|
|
133
|
-
|
|
31
|
+
### 1. Design Events
|
|
134
32
|
|
|
135
|
-
|
|
136
|
-
-
|
|
137
|
-
-
|
|
138
|
-
- **
|
|
139
|
-
- Each command handler defines what state projection it needs (and ONLY what it needs)
|
|
140
|
-
- Projection can be regenerated from events at any time
|
|
33
|
+
Events are business facts, not technical occurrences:
|
|
34
|
+
- **Event Type**: what changed, in past tense business language (Created, Confirmed, Shipped)
|
|
35
|
+
- **Event Data**: the business fields, noting which came directly from the triggering command versus which are implicit context (e.g. a calculated total, or the entity's identity)
|
|
36
|
+
- **Causality**: which command triggered it
|
|
141
37
|
|
|
142
|
-
|
|
38
|
+
Document each entity's events as a chronological list, giving each event's triggering command and its data. A full worked example (an Order) is in `references/examples.md`.
|
|
143
39
|
|
|
144
|
-
**
|
|
145
|
-
-
|
|
146
|
-
-
|
|
147
|
-
-
|
|
148
|
-
-
|
|
40
|
+
**Key Rules**:
|
|
41
|
+
- Events are immutable business facts
|
|
42
|
+
- Events use past tense, business language
|
|
43
|
+
- Event order matters — it tells the story
|
|
44
|
+
- Never modify or delete an event once it exists
|
|
45
|
+
- Events only exist if the triggering command succeeded
|
|
149
46
|
|
|
150
|
-
|
|
47
|
+
### 2. Design Commands
|
|
151
48
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
- Represent what user/system wants to do
|
|
49
|
+
Commands are business intent from a UI or Processor:
|
|
50
|
+
- Represent what a user or system wants to do
|
|
155
51
|
- Can be rejected (validation failure)
|
|
156
|
-
- Only UI or Processor can issue
|
|
157
|
-
- Load current stream state for validation
|
|
52
|
+
- Only a UI or Processor can issue a command
|
|
158
53
|
- Produce events if valid, or reject if invalid
|
|
159
54
|
|
|
160
|
-
Document each command's source, its input fields, the preconditions it
|
|
55
|
+
Document each command's source, its input fields, the preconditions it's checked against, the event(s) it produces on success (noting which data comes from the command versus implicit context), and its rejection outcomes. A full worked example (ConfirmOrder) is in `references/examples.md`.
|
|
161
56
|
|
|
162
57
|
**Key Rules**:
|
|
163
|
-
- Only UI or Processor can issue commands (entry points)
|
|
58
|
+
- Only a UI or Processor can issue commands (entry points)
|
|
164
59
|
- One command per UI/Processor action
|
|
165
|
-
- Commands validate against stream state
|
|
166
60
|
- Successful command → Event(s) created
|
|
167
61
|
- Failed validation → Command rejected, no event
|
|
168
|
-
- Commands are synchronous decision logic (pure)
|
|
169
62
|
|
|
170
|
-
###
|
|
171
|
-
Read models are **projections of events for UI/Processor queries**:
|
|
172
|
-
- Built from events (only source is events)
|
|
173
|
-
- Optimized for specific query patterns
|
|
174
|
-
- Consumed by UI or Processor (for display/decision)
|
|
175
|
-
- Can be regenerated from events anytime
|
|
63
|
+
### 3. Design Read Models
|
|
176
64
|
|
|
177
|
-
|
|
65
|
+
Read models are projections of events, built for UI/Processor queries:
|
|
66
|
+
- Built from events (their only source)
|
|
67
|
+
- Optimized for a specific query pattern
|
|
68
|
+
- Consumed by UI (for display) or Processor (for a decision)
|
|
69
|
+
- Can be regenerated from events at any time
|
|
178
70
|
|
|
179
|
-
|
|
180
|
-
Show how events relate to each other:
|
|
71
|
+
Document each read model's purpose, which events it subscribes to, its query-shaped data, how each subscribed event updates that data, and who consumes it. A full worked example (OrderSummaryView) is in `references/examples.md`.
|
|
181
72
|
|
|
182
|
-
|
|
73
|
+
### 4. Document Event Causality
|
|
183
74
|
|
|
184
|
-
|
|
185
|
-
Show valid state transitions:
|
|
75
|
+
Trace the causal chain from the first command through the events and downstream commands it can trigger, showing how a later command's decision depends on events produced earlier. A full worked example (an Order create→confirm→ship chain) is in `references/examples.md`.
|
|
186
76
|
|
|
187
|
-
|
|
77
|
+
### 5. Document State Transitions
|
|
188
78
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
Present the complete model as a markdown document with sections for Event Streams (each stream's identity, its events, and a human-readable state-projection example per command), Commands (input, validation, events produced, outcomes), Read Models (purpose, subscribed events, queries served), and Implementation Notes. A full worked example of this document structure (Order domain) is in `references/examples.md`.
|
|
192
|
-
|
|
193
|
-
## Key Event Sourcing Principles
|
|
194
|
-
|
|
195
|
-
1. **Events are Facts**: Events describe what happened, not what might happen
|
|
196
|
-
2. **Immutable Event Log**: Events are appended, never modified
|
|
197
|
-
3. **State is Minimal and Command-Driven**: State is built by replaying events, but ONLY for what a specific command needs to validate. Not all stream fields are needed for all commands.
|
|
198
|
-
4. **Not DDD Aggregates**: Stream roots group events logically, but aren't bundles of related data like DDD aggregates. State is determined per-command, not designed upfront for the whole stream.
|
|
199
|
-
5. **Commands are Pure**: No side effects, just decision logic against minimal state
|
|
200
|
-
6. **Read Models are Separate**: Read models (projections) are separate from command-validation state. Read models can have rich data; command state stays minimal.
|
|
201
|
-
7. **Event Causality**: Commands → [minimal state] → Events → [read models]
|
|
202
|
-
|
|
203
|
-
## Design Patterns
|
|
204
|
-
|
|
205
|
-
### Compensation Pattern
|
|
206
|
-
Handle errors by appending compensation events:
|
|
207
|
-
```text
|
|
208
|
-
Command: ProcessPayment failed
|
|
209
|
-
→ PaymentFailed event
|
|
210
|
-
(triggered by external error)
|
|
211
|
-
→ OrderCancelled event (compensation)
|
|
212
|
-
(or retry logic)
|
|
213
|
-
```
|
|
79
|
+
Map the valid states a process can be in, which command causes which transition, and which transitions are invalid from a given state (e.g. cancelling an already-shipped order), ending at any terminal states. A full worked example (Order transitions) is in `references/examples.md`.
|
|
214
80
|
|
|
215
|
-
###
|
|
216
|
-
Answer "what was the state at time T?":
|
|
217
|
-
```text
|
|
218
|
-
Replay events up to timestamp T
|
|
219
|
-
→ Get historical state
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
## Best Practices for Event Model Design
|
|
223
|
-
|
|
224
|
-
### 1. Design Minimal State Per Command
|
|
225
|
-
Each command handler only loads the state it needs:
|
|
226
|
-
- "LoadOrderState loads { id, items, total, shipping, customer, payment, status, ... }"
|
|
227
|
-
- "ConfirmOrderState loads { status, orderId }"
|
|
228
|
-
- "ShipOrderState loads { status, orderId, paymentConfirmed }"
|
|
229
|
-
|
|
230
|
-
### 2. Separate Command State from Query Models
|
|
231
|
-
Keep command-validation state and read models strictly separate:
|
|
232
|
-
- **Command State** (minimal): Used by handlers to validate commands
|
|
233
|
-
- **Query Models** (rich): Used by UI/Processor to display/query data
|
|
234
|
-
- Never share between them
|
|
235
|
-
|
|
236
|
-
### 3. Name State Interfaces by Command
|
|
237
|
-
Use the pattern `[CommandName]State` to make the relationship explicit:
|
|
238
|
-
- `PublishReviewState` for PublishReview command
|
|
239
|
-
- `EditReviewState` for EditReview command
|
|
240
|
-
- `ReviewState` (ambiguous - which command?)
|
|
81
|
+
### Output Format
|
|
241
82
|
|
|
242
|
-
|
|
243
|
-
Show what state changes trigger what commands:
|
|
244
|
-
- Include initial state
|
|
245
|
-
- Show all valid transitions
|
|
246
|
-
- Mark impossible transitions (and why)
|
|
247
|
-
- Document rejection conditions
|
|
83
|
+
Present the complete model as a markdown document with sections for Events (per entity, chronological, each with its triggering command), Commands (input, preconditions, events produced, rejection outcomes), and Read Models (purpose, subscribed events, consumers). A full worked example of this document structure is in `references/examples.md`.
|
|
248
84
|
|
|
249
|
-
|
|
250
|
-
Transform "obvious" business rules into documented invariants:
|
|
251
|
-
- "Obviously can't ship an unconfirmed order"
|
|
252
|
-
- "ShipOrder validation: requires status='Confirmed' with paymentId"
|
|
85
|
+
## Key Principles
|
|
253
86
|
|
|
254
|
-
|
|
255
|
-
Events record facts, not derived values:
|
|
256
|
-
- "OrderCreated { items, total }" (total is computed from items)
|
|
257
|
-
- "OrderCreated { items[] with unitPrice, shippingAddress }" (total computed in projection)
|
|
87
|
+
See `eventmodeling-core-rules` for the element definitions and causality rules this design must follow (events are immutable facts, commands are checked against documented preconditions, read models never drive command validation).
|
|
258
88
|
|
|
259
89
|
## Quality Checklist
|
|
260
90
|
|
|
261
|
-
- [ ] All events are immutable facts (past tense)
|
|
262
|
-
- [ ] Events contain only captured data, no computed fields
|
|
263
|
-
- [ ]
|
|
264
|
-
- [ ]
|
|
265
|
-
- [ ]
|
|
266
|
-
- [ ]
|
|
267
|
-
- [ ]
|
|
268
|
-
- [ ] No references between streams in events
|
|
269
|
-
- [ ] Read models are optional, not required
|
|
270
|
-
- [ ] All logic is state → events (pure functions)
|
|
91
|
+
- [ ] All events are immutable business facts (past tense)
|
|
92
|
+
- [ ] Events contain only captured business data, no computed fields
|
|
93
|
+
- [ ] Each command's preconditions are documented explicitly
|
|
94
|
+
- [ ] Commands either produce events or are rejected — no silent failures
|
|
95
|
+
- [ ] Event causality is clear and traceable end to end
|
|
96
|
+
- [ ] State transitions are documented, including which ones are invalid and why
|
|
97
|
+
- [ ] Read models are optional — nothing requires one to exist
|
|
@@ -1,39 +1,11 @@
|
|
|
1
1
|
# Designing Event Models — Worked Examples
|
|
2
2
|
|
|
3
|
-
These are conceptual worked examples (Order domain) illustrating the event-model design reasoning this skill applies — useful for understanding the reasoning, but the actual instructions to follow live in the
|
|
3
|
+
These are conceptual worked examples (Order domain) illustrating the event-model design reasoning this skill applies — useful for understanding the reasoning, but the actual instructions to follow live in the numbered Workflow sections of the main SKILL.md.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 1. Design Events — worked example
|
|
6
6
|
|
|
7
7
|
```text
|
|
8
|
-
|
|
9
|
-
OrderAggregate { orderId, customerId, items[], total, status, paymentId, address, shippedAt, cancelledAt, ... }
|
|
10
|
-
↑ This is a READ MODEL, not command state
|
|
11
|
-
↓ NEVER use for command validation
|
|
12
|
-
handleConfirmOrder(OrderAggregate)
|
|
13
|
-
handleShipOrder(OrderAggregate)
|
|
14
|
-
handleCancelOrder(OrderAggregate)
|
|
15
|
-
|
|
16
|
-
CORRECT: Minimal state per command
|
|
17
|
-
ConfirmOrderState { status, orderId }
|
|
18
|
-
↓
|
|
19
|
-
handleConfirmOrder(ConfirmOrderState)
|
|
20
|
-
|
|
21
|
-
ShipOrderState { status, orderId, paymentId }
|
|
22
|
-
↓
|
|
23
|
-
handleShipOrder(ShipOrderState)
|
|
24
|
-
|
|
25
|
-
CancelOrderState { status, orderId, createdAt }
|
|
26
|
-
↓
|
|
27
|
-
handleCancelOrder(CancelOrderState)
|
|
28
|
-
|
|
29
|
-
OrderSummaryView { orderId, customerId, items[], total, status, paymentId, ... }
|
|
30
|
-
↑ This is for UI queries, NOT command validation
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## 1. Design Event Streams — worked example
|
|
34
|
-
|
|
35
|
-
```text
|
|
36
|
-
Stream: Order:order-123
|
|
8
|
+
Entity: Order (order-123)
|
|
37
9
|
|
|
38
10
|
Events (chronological):
|
|
39
11
|
1. OrderCreated
|
|
@@ -46,7 +18,7 @@ Events (chronological):
|
|
|
46
18
|
Triggered by: ConfirmOrder command
|
|
47
19
|
Data: paymentId, confirmedAt
|
|
48
20
|
(from command: paymentId)
|
|
49
|
-
(implicit: orderId
|
|
21
|
+
(implicit: orderId, previous status verified)
|
|
50
22
|
|
|
51
23
|
3. OrderShipped
|
|
52
24
|
Triggered by: ShipOrder command
|
|
@@ -55,62 +27,25 @@ Events (chronological):
|
|
|
55
27
|
(implicit: orderId, confirmed status verified)
|
|
56
28
|
```
|
|
57
29
|
|
|
58
|
-
## 2. Design
|
|
59
|
-
|
|
60
|
-
Example for the Order stream, with a separate command state read model for each command:
|
|
61
|
-
|
|
62
|
-
```text
|
|
63
|
-
## ConfirmOrder Command (IMPLEMENTED)
|
|
64
|
-
State interface: ConfirmOrderState { status, orderId }
|
|
65
|
-
Builder: buildConfirmOrderState(events)
|
|
66
|
-
Naming: [CommandName]State = implemented
|
|
67
|
-
- OrderCreated event → Set status='Draft'
|
|
68
|
-
- OrderConfirmed event → Set status='Confirmed'
|
|
69
|
-
(SKIP: items, total, shipping - not needed for this command)
|
|
70
|
-
|
|
71
|
-
## ShipOrder Command (IMPLEMENTED)
|
|
72
|
-
State interface: ShipOrderState { status, orderId, paymentId }
|
|
73
|
-
Builder: buildShipOrderState(events)
|
|
74
|
-
Naming: [CommandName]State = implemented
|
|
75
|
-
(DIFFERENT from ConfirmOrderState)
|
|
76
|
-
- OrderCreated event → (skip)
|
|
77
|
-
- OrderConfirmed event → Set status='Confirmed', set paymentId
|
|
78
|
-
- OrderShipped event → Set status='Shipped'
|
|
79
|
-
|
|
80
|
-
## CancelOrder Command (PLANNED - NOT IMPLEMENTED)
|
|
81
|
-
State interface: CancelOrderStateToDo { status, orderId, createdAt }
|
|
82
|
-
Builder: buildCancelOrderStateToDo(events) [STUB - TODO]
|
|
83
|
-
Naming: [CommandName]StateToDo = planned, needs implementation
|
|
84
|
-
(DIFFERENT from both above)
|
|
85
|
-
- OrderCreated event → Set status='Draft', createdAt
|
|
86
|
-
- OrderCancelled event → Set status='Cancelled'
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
## 3. Design Commands — worked example
|
|
30
|
+
## 2. Design Commands — worked example
|
|
90
31
|
|
|
91
32
|
```text
|
|
92
33
|
Command: ConfirmOrder
|
|
93
34
|
Source: UI or Processor (only these can issue)
|
|
94
35
|
Input: orderId, paymentId
|
|
95
36
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
- state.status === 'Draft' (reject: already confirmed)
|
|
100
|
-
- paymentId is valid (reject: invalid payment)
|
|
101
|
-
3. If all valid:
|
|
102
|
-
- Produce: OrderConfirmed event
|
|
103
|
-
- Data: paymentId, confirmedAt
|
|
104
|
-
- Implicit: orderId (from stream), previous status (from state)
|
|
105
|
-
4. If any validation fails:
|
|
106
|
-
- Reject: return error (no event created)
|
|
37
|
+
Preconditions:
|
|
38
|
+
- order status is 'Draft' (reject: already confirmed)
|
|
39
|
+
- paymentId is valid (reject: invalid payment)
|
|
107
40
|
|
|
108
41
|
Outcomes:
|
|
109
|
-
|
|
110
|
-
|
|
42
|
+
Success: OrderConfirmed event
|
|
43
|
+
Data: paymentId, confirmedAt
|
|
44
|
+
Implicit: orderId, previous status
|
|
45
|
+
Rejection: error returned, no event created
|
|
111
46
|
```
|
|
112
47
|
|
|
113
|
-
##
|
|
48
|
+
## 3. Design Read Models — worked example
|
|
114
49
|
|
|
115
50
|
```text
|
|
116
51
|
ReadModel: OrderSummaryView
|
|
@@ -144,26 +79,26 @@ Consumed by:
|
|
|
144
79
|
- Processor: checks if order can be shipped
|
|
145
80
|
```
|
|
146
81
|
|
|
147
|
-
##
|
|
82
|
+
## 4. Document Event Causality — worked example
|
|
148
83
|
|
|
149
84
|
```text
|
|
150
85
|
Command Flow:
|
|
151
86
|
CreateOrder command
|
|
152
87
|
→ OrderCreated event
|
|
153
|
-
↓ (may trigger
|
|
154
|
-
ConfirmOrder command (
|
|
88
|
+
↓ (may trigger downstream action)
|
|
89
|
+
ConfirmOrder command (depends on OrderCreated having happened)
|
|
155
90
|
→ OrderConfirmed event
|
|
156
|
-
↓ (may trigger)
|
|
157
|
-
ShipOrder command (
|
|
91
|
+
↓ (may trigger downstream action)
|
|
92
|
+
ShipOrder command (depends on OrderCreated + OrderConfirmed having happened)
|
|
158
93
|
→ OrderShipped event
|
|
159
94
|
```
|
|
160
95
|
|
|
161
|
-
##
|
|
96
|
+
## 5. Document State Transitions — worked example
|
|
162
97
|
|
|
163
98
|
```text
|
|
164
|
-
Order
|
|
99
|
+
Order State Transitions:
|
|
165
100
|
|
|
166
|
-
Initial state: (
|
|
101
|
+
Initial state: (no order yet)
|
|
167
102
|
↓
|
|
168
103
|
CreateOrder → OrderCreated
|
|
169
104
|
↓
|
|
@@ -186,40 +121,24 @@ Shipped state:
|
|
|
186
121
|
```markdown
|
|
187
122
|
# Event Model: [Domain]
|
|
188
123
|
|
|
189
|
-
##
|
|
124
|
+
## Events
|
|
190
125
|
|
|
191
|
-
###
|
|
126
|
+
### Entity: Order
|
|
192
127
|
|
|
193
128
|
**Identity**: orderId
|
|
194
129
|
|
|
195
130
|
**Events**:
|
|
196
131
|
- OrderCreated: Initial event creating the order
|
|
197
|
-
Data: customerId, items[], total, shippingAddress
|
|
132
|
+
Data: customerId, items[], total, shippingAddress
|
|
198
133
|
|
|
199
134
|
- OrderConfirmed: Payment confirmed
|
|
200
|
-
Data: paymentId, confirmedAt
|
|
135
|
+
Data: paymentId, confirmedAt
|
|
201
136
|
|
|
202
137
|
- OrderShipped: Order shipped
|
|
203
|
-
Data: shipmentId, shippedAt
|
|
138
|
+
Data: shipmentId, shippedAt
|
|
204
139
|
|
|
205
140
|
- OrderCancelled: Order cancelled
|
|
206
|
-
Data: cancelledAt, reason
|
|
207
|
-
|
|
208
|
-
**State Projection (Human Example)**:
|
|
209
|
-
For the ConfirmOrder command, we need minimal state:
|
|
210
|
-
```text
|
|
211
|
-
ConfirmOrderState:
|
|
212
|
-
- orderId: 'order-123'
|
|
213
|
-
- status: 'Draft'
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
For the ShipOrder command, we need different data:
|
|
217
|
-
```text
|
|
218
|
-
ShipOrderState:
|
|
219
|
-
- orderId: 'order-123'
|
|
220
|
-
- status: 'Confirmed'
|
|
221
|
-
- paymentId: 'payment-456'
|
|
222
|
-
```
|
|
141
|
+
Data: cancelledAt, reason
|
|
223
142
|
|
|
224
143
|
---
|
|
225
144
|
|
|
@@ -227,13 +146,13 @@ ShipOrderState:
|
|
|
227
146
|
|
|
228
147
|
### Command: CreateOrder
|
|
229
148
|
- Input: customerId, items[], shippingAddress
|
|
230
|
-
-
|
|
149
|
+
- Preconditions: Items valid, customerId exists
|
|
231
150
|
- Events produced: OrderCreated
|
|
232
|
-
- Possible outcomes: Success (OrderCreated) or
|
|
151
|
+
- Possible outcomes: Success (OrderCreated) or validation error
|
|
233
152
|
|
|
234
153
|
### Command: ConfirmOrder
|
|
235
154
|
- Input: orderId, paymentId
|
|
236
|
-
-
|
|
155
|
+
- Preconditions: Order in Draft status, payment validated
|
|
237
156
|
- Events produced: OrderConfirmed
|
|
238
157
|
- Possible outcomes: Success or "Already confirmed" error
|
|
239
158
|
|
|
@@ -245,13 +164,4 @@ ShipOrderState:
|
|
|
245
164
|
- Purpose: Quick lookup of order status
|
|
246
165
|
- Events: OrderCreated, OrderConfirmed, OrderShipped, OrderCancelled
|
|
247
166
|
- Queries served: GetOrder(orderId), ListOrdersByCustomer(customerId)
|
|
248
|
-
|
|
249
|
-
---
|
|
250
|
-
|
|
251
|
-
## Implementation Notes
|
|
252
|
-
- All state is derived from events
|
|
253
|
-
- Commands validate against derived state
|
|
254
|
-
- No transaction across streams
|
|
255
|
-
- Events are source of truth
|
|
256
|
-
- Read models can be rebuilt from events
|
|
257
167
|
```
|
package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md
CHANGED
|
@@ -11,6 +11,8 @@ allowed-tools:
|
|
|
11
11
|
|
|
12
12
|
> **Before doing anything else**, invoke the `connect` skill — if not already connected — to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Do not proceed until it has completed. Consult `learn-eventmodelers-api` only if you need to look up a specific endpoint or field this file doesn't cover — don't load it eagerly.
|
|
13
13
|
|
|
14
|
+
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.
|
|
15
|
+
|
|
14
16
|
Prefer `mcp__eventmodelers__*` tools when available (registered by the `connect` skill) — the curl blocks below are the fallback for sessions without MCP connected.
|
|
15
17
|
|
|
16
18
|
## GWT vs. Storyline — Decision Rule
|
|
@@ -83,12 +85,8 @@ in a sibling `meta.storylines` collection.
|
|
|
83
85
|
|
|
84
86
|
**When to Interview**: Skip if the user has already specified: scenario coverage depth (happy path + validation + state violations), known edge cases to include, and stakeholders available for review. Interview when coverage goals are unclear or edge cases haven't been identified.
|
|
85
87
|
|
|
86
|
-
**Interview Strategy**: Align on scenario depth and coverage strategy to avoid under-specification or excessive documentation. Identify stakeholders who can validate business rules.
|
|
87
|
-
|
|
88
88
|
### Critical Questions
|
|
89
89
|
|
|
90
|
-
When scenario coverage is uncertain:
|
|
91
|
-
|
|
92
90
|
1. **Scenario Depth & Coverage Goals** (Impact: Determines scope—happy path only vs. comprehensive coverage)
|
|
93
91
|
- Question: "How comprehensive should scenario coverage be? (A) Happy path + basic validation, (B) All command variations, (C) Comprehensive including edge cases and error paths"
|
|
94
92
|
- Why it matters: Affects time investment and implementation complexity; production code needs (C), design validation might use (A) or (B)
|
|
@@ -109,80 +107,7 @@ When scenario coverage is uncertain:
|
|
|
109
107
|
- Why it matters: Multi-role review catches business logic errors; single role may miss perspective
|
|
110
108
|
- Follow-up triggers: If (A) only → ask "Will PO have time for detailed review?"; if (C) → plan review workshop
|
|
111
109
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
**Conditional Entry**:
|
|
115
|
-
```
|
|
116
|
-
If user has provided:
|
|
117
|
-
- Clear scenario coverage goals (happy path + validation + state violations)
|
|
118
|
-
- AND identified edge cases or known business rules to test
|
|
119
|
-
- AND specified who will review/validate scenarios
|
|
120
|
-
|
|
121
|
-
Then: Skip interview, proceed directly to scenario elaboration
|
|
122
|
-
|
|
123
|
-
Else: Conduct interview
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
**Phase 1: Coverage Planning** (Questions 1-2)
|
|
127
|
-
- Determine depth (happy path vs. comprehensive)
|
|
128
|
-
- Identify critical edge cases to cover
|
|
129
|
-
- Establish coverage priorities
|
|
130
|
-
|
|
131
|
-
**Phase 2: Implementation & Review** (Questions 3-4)
|
|
132
|
-
- Decide on automation vs. documentation
|
|
133
|
-
- Confirm stakeholder availability
|
|
134
|
-
- Plan review workflow
|
|
135
|
-
|
|
136
|
-
### Capturing Interview Findings
|
|
137
|
-
|
|
138
|
-
Append findings to the project's event modeling file:
|
|
139
|
-
|
|
140
|
-
**File**: `.trogonai/interviews/[project-name]/EVENTMODELING.md`
|
|
141
|
-
|
|
142
|
-
Use Write tool to add/update this section:
|
|
143
|
-
|
|
144
|
-
```markdown
|
|
145
|
-
## 7. Scenarios (eventmodeling-elaborating-scenarios)
|
|
146
|
-
|
|
147
|
-
### Coverage Goals
|
|
148
|
-
[From Q1: Happy path / Comprehensive / Deep]
|
|
149
|
-
|
|
150
|
-
### Critical Edge Cases
|
|
151
|
-
[From Q2]
|
|
152
|
-
- Edge case 1: [Case] → [Why important]
|
|
153
|
-
- Edge case 2: [Case] → [Why important]
|
|
154
|
-
|
|
155
|
-
### Business Rules Requiring Scenarios
|
|
156
|
-
[From Q2]
|
|
157
|
-
- Rule 1: [Statement] → Success + Failure scenarios
|
|
158
|
-
- Rule 2: [Statement] → Success + Failure scenarios
|
|
159
|
-
|
|
160
|
-
### Testing Strategy
|
|
161
|
-
[From Q3: Automated / Manual / Documentation]
|
|
162
|
-
|
|
163
|
-
### Review & Validation
|
|
164
|
-
[From Q4: Who reviews, when, workflow]
|
|
165
|
-
|
|
166
|
-
### Key Scenario Specifications
|
|
167
|
-
[GWT format scenarios for critical commands and views]
|
|
168
|
-
|
|
169
|
-
---
|
|
170
|
-
|
|
171
|
-
## Validation & Completeness
|
|
172
|
-
|
|
173
|
-
### Validated
|
|
174
|
-
- [ ] All fields traced (completeness check)
|
|
175
|
-
- [ ] Events are immutable
|
|
176
|
-
- [ ] State projections deterministic
|
|
177
|
-
- [ ] Model ready for code generation
|
|
178
|
-
|
|
179
|
-
**Validation Date**: [Date]
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
Update Interview Trail:
|
|
183
|
-
```markdown
|
|
184
|
-
| 7 | eventmodeling-elaborating-scenarios | [today] | Scenario coverage, testing strategy, edge cases |
|
|
185
|
-
```
|
|
110
|
+
Follow **`eventmodeling-interview-protocol`** to run this interview and record its findings — label this step "**7. Scenarios** (`eventmodeling-elaborating-scenarios`)". Findings should cover: coverage goals, critical edge cases, business rules requiring scenarios, testing strategy, review/validation plan, and the key scenario specifications themselves (GWT format for critical commands and views).
|
|
186
111
|
|
|
187
112
|
Scenarios are done, but the model is not yet ready for implementation — Steps 8–11
|
|
188
113
|
(Completeness, Validation, Slicing, Documentation) still follow. Proceed to Step 8
|