@eventmodelers/cli 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/README.md +175 -0
  2. package/cli.js +676 -0
  3. package/package.json +35 -0
  4. package/shared/build-kit/code-export.mjs +560 -0
  5. package/shared/build-kit/lib/ollama-agent.js +147 -0
  6. package/shared/build-kit/package.json +11 -0
  7. package/shared/build-kit/ralph-ollama.js +39 -0
  8. package/shared/build-kit/realtime-agent.js +18 -0
  9. package/stacks/axon/templates/.claude/skills/build-automation/SKILL.md +407 -0
  10. package/stacks/axon/templates/.claude/skills/build-automation/references/feature-flag-patterns.md +114 -0
  11. package/stacks/axon/templates/.claude/skills/build-automation-workflow/SKILL.md +496 -0
  12. package/stacks/axon/templates/.claude/skills/build-automation-workflow/references/axon-workflow-api.md +279 -0
  13. package/stacks/axon/templates/.claude/skills/build-automation-workflow/references/feature-flag-patterns.md +114 -0
  14. package/stacks/axon/templates/.claude/skills/build-state-change/SKILL.md +396 -0
  15. package/stacks/axon/templates/.claude/skills/build-state-change/references/axon-test-fixture-patterns.md +162 -0
  16. package/stacks/axon/templates/.claude/skills/build-state-change/references/feature-flag-patterns.md +56 -0
  17. package/stacks/axon/templates/.claude/skills/build-state-change/references/rest-api-patterns.md +115 -0
  18. package/stacks/axon/templates/.claude/skills/build-state-view/SKILL.md +282 -0
  19. package/stacks/axon/templates/.claude/skills/connect/SKILL.md +178 -0
  20. package/stacks/axon/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +611 -0
  21. package/stacks/axon/templates/.claude/skills/load-slice/SKILL.md +141 -0
  22. package/stacks/axon/templates/.claude/skills/update-slice-status/SKILL.md +105 -0
  23. package/stacks/axon/templates/build-kit/lib/AGENT.md +47 -0
  24. package/stacks/axon/templates/build-kit/lib/agent.sh +20 -0
  25. package/stacks/axon/templates/build-kit/lib/backend-prompt.md +158 -0
  26. package/stacks/axon/templates/build-kit/lib/prompt.md +126 -0
  27. package/stacks/axon/templates/build-kit/lib/ralph.js +369 -0
  28. package/stacks/axon/templates/build-kit/ralph-claude.js +44 -0
  29. package/stacks/axon/templates/build-kit/ralph.sh +98 -0
  30. package/stacks/axon/templates/root/.env.example +5 -0
  31. package/stacks/axon/templates/root/CLAUDE.md +60 -0
  32. package/stacks/axon/templates/root/README.md +44 -0
  33. package/stacks/axon/templates/root/docker-compose.yml +64 -0
  34. package/stacks/axon/templates/root/mvnw +259 -0
  35. package/stacks/axon/templates/root/mvnw.cmd +149 -0
  36. package/stacks/axon/templates/root/pom.xml +125 -0
  37. package/stacks/axon/templates/root/src/main/java/io/axoniq/quickstart/QuickstartApplication.java +128 -0
  38. package/stacks/axon/templates/root/src/main/java/io/axoniq/quickstart/config/WebConfig.java +155 -0
  39. package/stacks/axon/templates/root/src/main/resources/application.properties +2 -0
  40. package/stacks/axon/templates/root/src/main/resources/static/bg-body.png +0 -0
  41. package/stacks/axon/templates/root/src/main/resources/static/bg-header.png +0 -0
  42. package/stacks/axon/templates/root/src/main/resources/static/index.html +596 -0
  43. package/stacks/cratis-csharp/templates/.claude/skills/_shared/cratis-conventions.md +251 -0
  44. package/stacks/cratis-csharp/templates/.claude/skills/build-automation/SKILL.md +99 -0
  45. package/stacks/cratis-csharp/templates/.claude/skills/build-automation/references/patterns.md +115 -0
  46. package/stacks/cratis-csharp/templates/.claude/skills/build-state-change/SKILL.md +163 -0
  47. package/stacks/cratis-csharp/templates/.claude/skills/build-state-change/references/patterns.md +234 -0
  48. package/stacks/cratis-csharp/templates/.claude/skills/build-state-view/SKILL.md +120 -0
  49. package/stacks/cratis-csharp/templates/.claude/skills/build-state-view/references/patterns.md +166 -0
  50. package/stacks/cratis-csharp/templates/.claude/skills/connect/SKILL.md +169 -0
  51. package/stacks/cratis-csharp/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +609 -0
  52. package/stacks/cratis-csharp/templates/.claude/skills/load-slice/SKILL.md +141 -0
  53. package/stacks/cratis-csharp/templates/.claude/skills/update-slice-status/SKILL.md +105 -0
  54. package/stacks/cratis-csharp/templates/build-kit/lib/AGENT.md +58 -0
  55. package/stacks/cratis-csharp/templates/build-kit/lib/agent.sh +20 -0
  56. package/stacks/cratis-csharp/templates/build-kit/lib/backend-prompt.md +129 -0
  57. package/stacks/cratis-csharp/templates/build-kit/lib/prompt.md +124 -0
  58. package/stacks/cratis-csharp/templates/build-kit/lib/ralph.js +302 -0
  59. package/stacks/cratis-csharp/templates/build-kit/ralph-claude.js +37 -0
  60. package/stacks/cratis-csharp/templates/build-kit/ralph.sh +98 -0
  61. package/stacks/cratis-csharp/templates/root/.frontend/index.css +29 -0
  62. package/stacks/cratis-csharp/templates/root/.frontend/index.html +17 -0
  63. package/stacks/cratis-csharp/templates/root/.frontend/main.tsx +18 -0
  64. package/stacks/cratis-csharp/templates/root/.frontend/tsconfig.json +42 -0
  65. package/stacks/cratis-csharp/templates/root/.frontend/tsconfig.node.json +11 -0
  66. package/stacks/cratis-csharp/templates/root/.frontend/vite.config.ts +56 -0
  67. package/stacks/cratis-csharp/templates/root/App.tsx +23 -0
  68. package/stacks/cratis-csharp/templates/root/CLAUDE.md +62 -0
  69. package/stacks/cratis-csharp/templates/root/CratisApp.csproj +25 -0
  70. package/stacks/cratis-csharp/templates/root/CratisApp.sln +18 -0
  71. package/stacks/cratis-csharp/templates/root/GlobalUsings.cs +3 -0
  72. package/stacks/cratis-csharp/templates/root/Home.tsx +102 -0
  73. package/stacks/cratis-csharp/templates/root/Program.cs +26 -0
  74. package/stacks/cratis-csharp/templates/root/README.md +192 -0
  75. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/AllListings.ts +47 -0
  76. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/Listing.cs +11 -0
  77. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/Listing.ts +12 -0
  78. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/ListingDataTable.tsx +17 -0
  79. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Listing/index.ts +1 -0
  80. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/Register.ts +51 -0
  81. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/RegisterDialog.tsx +18 -0
  82. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/Registration.cs +27 -0
  83. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/Registration/index.ts +1 -0
  84. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/SomeFeature.tsx +22 -0
  85. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/SomeName.cs +3 -0
  86. package/stacks/cratis-csharp/templates/root/SomeModule/SomeFeature/index.ts +1 -0
  87. package/stacks/cratis-csharp/templates/root/appsettings.Development.json +9 -0
  88. package/stacks/cratis-csharp/templates/root/appsettings.json +26 -0
  89. package/stacks/cratis-csharp/templates/root/docker-compose.yml +23 -0
  90. package/stacks/cratis-csharp/templates/root/package.json +33 -0
  91. package/stacks/cratis-csharp/templates/root/tsconfig.json +3 -0
  92. package/stacks/modeling-kit/templates/.claude/settings.local.json +13 -0
  93. package/stacks/modeling-kit/templates/.claude/skills/analyze-existing-model/SKILL.md +215 -0
  94. package/stacks/modeling-kit/templates/.claude/skills/attributes/SKILL.md +176 -0
  95. package/stacks/modeling-kit/templates/.claude/skills/connect/SKILL.md +182 -0
  96. package/stacks/modeling-kit/templates/.claude/skills/discover-storyboard/SKILL.md +383 -0
  97. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-applying-conways-law/SKILL.md +465 -0
  98. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/SKILL.md +587 -0
  99. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-brainstorming-events/references/facilitating-event-modeling-workshops.md +626 -0
  100. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-checking-completeness/SKILL.md +542 -0
  101. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-designing-event-models/SKILL.md +497 -0
  102. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-elaborating-scenarios/SKILL.md +783 -0
  103. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-inputs/SKILL.md +604 -0
  104. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-identifying-outputs/SKILL.md +699 -0
  105. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-integrating-legacy-systems/SKILL.md +674 -0
  106. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/SKILL.md +231 -0
  107. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/domain-patterns.md +150 -0
  108. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/patterns.md +329 -0
  109. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-optimizing-stream-design/references/snapshotting.md +204 -0
  110. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/SKILL.md +352 -0
  111. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-orchestrating-event-modeling/references/project-planning-with-event-modeling.md +341 -0
  112. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-plotting-events/SKILL.md +153 -0
  113. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/SKILL.md +136 -0
  114. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/examples.md +78 -0
  115. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-slicing-event-models/references/patterns.md +85 -0
  116. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-storyboarding-events/SKILL.md +655 -0
  117. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-translating-external-events/SKILL.md +479 -0
  118. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models/SKILL.md +234 -0
  119. package/stacks/modeling-kit/templates/.claude/skills/eventmodeling-validating-event-models-checklist/SKILL.md +353 -0
  120. package/stacks/modeling-kit/templates/.claude/skills/examples/SKILL.md +200 -0
  121. package/stacks/modeling-kit/templates/.claude/skills/handle-comment/SKILL.md +94 -0
  122. package/stacks/modeling-kit/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +441 -0
  123. package/stacks/modeling-kit/templates/.claude/skills/place-element/SKILL.md +290 -0
  124. package/stacks/modeling-kit/templates/.claude/skills/storyboard/SKILL.md +212 -0
  125. package/stacks/modeling-kit/templates/.claude/skills/storyboard-screen/SKILL.md +123 -0
  126. package/stacks/modeling-kit/templates/.claude/skills/timeline/SKILL.md +353 -0
  127. package/stacks/modeling-kit/templates/.claude/skills/update-slice-status/SKILL.md +110 -0
  128. package/stacks/modeling-kit/templates/.claude/skills/wdyt/SKILL.md +134 -0
  129. package/stacks/modeling-kit/templates/kit/lib/agent.sh +20 -0
  130. package/stacks/modeling-kit/templates/kit/lib/ollama-agent.js +147 -0
  131. package/stacks/modeling-kit/templates/kit/lib/ralph.js +286 -0
  132. package/stacks/modeling-kit/templates/kit/package.json +12 -0
  133. package/stacks/modeling-kit/templates/kit/ralph-claude.js +50 -0
  134. package/stacks/modeling-kit/templates/kit/ralph-ollama.js +38 -0
  135. package/stacks/modeling-kit/templates/kit/ralph.sh +61 -0
  136. package/stacks/modeling-kit/templates/kit/realtime-agent.js +18 -0
  137. package/stacks/modeling-kit/templates/root/CLAUDE.md +56 -0
  138. package/stacks/node/templates/.claude/skills/build-automation/SKILL.md +266 -0
  139. package/stacks/node/templates/.claude/skills/build-state-change/SKILL.md +344 -0
  140. package/stacks/node/templates/.claude/skills/build-state-view/SKILL.md +412 -0
  141. package/stacks/node/templates/.claude/skills/connect/SKILL.md +178 -0
  142. package/stacks/node/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +628 -0
  143. package/stacks/node/templates/.claude/skills/load-slice/SKILL.md +143 -0
  144. package/stacks/node/templates/.claude/skills/update-slice-status/SKILL.md +110 -0
  145. package/stacks/node/templates/build-kit/README.md +86 -0
  146. package/stacks/node/templates/build-kit/lib/AGENT.md +47 -0
  147. package/stacks/node/templates/build-kit/lib/agent.sh +20 -0
  148. package/stacks/node/templates/build-kit/lib/backend-prompt.md +152 -0
  149. package/stacks/node/templates/build-kit/lib/prompt.md +122 -0
  150. package/stacks/node/templates/build-kit/lib/ralph.js +369 -0
  151. package/stacks/node/templates/build-kit/ralph-claude.js +44 -0
  152. package/stacks/node/templates/build-kit/ralph.sh +98 -0
  153. package/stacks/node/templates/root/.env.example +15 -0
  154. package/stacks/node/templates/root/CLAUDE.md +60 -0
  155. package/stacks/node/templates/root/docker-compose.yml +15 -0
  156. package/stacks/node/templates/root/flyway.conf +17 -0
  157. package/stacks/node/templates/root/migrations/V1__schema.sql.example +12 -0
  158. package/stacks/node/templates/root/package.json +50 -0
  159. package/stacks/node/templates/root/server.ts +130 -0
  160. package/stacks/node/templates/root/setup-env.sh +53 -0
  161. package/stacks/node/templates/root/src/common/assertions.ts +6 -0
  162. package/stacks/node/templates/root/src/common/db.ts +32 -0
  163. package/stacks/node/templates/root/src/common/loadPostgresEventstore.ts +23 -0
  164. package/stacks/node/templates/root/src/common/parseEndpoint.ts +51 -0
  165. package/stacks/node/templates/root/src/common/processorDlq.ts +28 -0
  166. package/stacks/node/templates/root/src/common/realtimeBroadcast.ts +12 -0
  167. package/stacks/node/templates/root/src/common/replay.ts +16 -0
  168. package/stacks/node/templates/root/src/common/routes.ts +19 -0
  169. package/stacks/node/templates/root/src/common/testHelpers.ts +44 -0
  170. package/stacks/node/templates/root/src/swagger.ts +34 -0
  171. package/stacks/node/templates/root/src/util/assertions.ts +6 -0
  172. package/stacks/node/templates/root/src/util/hash.ts +9 -0
  173. package/stacks/node/templates/root/src/util/sanitize.ts +23 -0
  174. package/stacks/node/templates/root/tsconfig.json +32 -0
  175. package/stacks/node/templates/root/vercel.json +8 -0
  176. package/stacks/supabase/templates/.claude/skills/build-automation/SKILL.md +266 -0
  177. package/stacks/supabase/templates/.claude/skills/build-state-change/SKILL.md +344 -0
  178. package/stacks/supabase/templates/.claude/skills/build-state-view/SKILL.md +390 -0
  179. package/stacks/supabase/templates/.claude/skills/build-webhook/SKILL.md +303 -0
  180. package/stacks/supabase/templates/.claude/skills/connect/SKILL.md +178 -0
  181. package/stacks/supabase/templates/.claude/skills/learn-eventmodelers-api/SKILL.md +628 -0
  182. package/stacks/supabase/templates/.claude/skills/load-slice/SKILL.md +143 -0
  183. package/stacks/supabase/templates/.claude/skills/update-slice-status/SKILL.md +110 -0
  184. package/stacks/supabase/templates/build-kit/README.md +86 -0
  185. package/stacks/supabase/templates/build-kit/lib/AGENT.md +47 -0
  186. package/stacks/supabase/templates/build-kit/lib/agent.sh +20 -0
  187. package/stacks/supabase/templates/build-kit/lib/backend-prompt.md +152 -0
  188. package/stacks/supabase/templates/build-kit/lib/prompt.md +123 -0
  189. package/stacks/supabase/templates/build-kit/lib/ralph.js +369 -0
  190. package/stacks/supabase/templates/build-kit/ralph-claude.js +44 -0
  191. package/stacks/supabase/templates/build-kit/ralph.sh +98 -0
  192. package/stacks/supabase/templates/root/.env.example +22 -0
  193. package/stacks/supabase/templates/root/CLAUDE.md +61 -0
  194. package/stacks/supabase/templates/root/flyway.conf +17 -0
  195. package/stacks/supabase/templates/root/package.json +52 -0
  196. package/stacks/supabase/templates/root/server.ts +177 -0
  197. package/stacks/supabase/templates/root/setup-env.sh +53 -0
  198. package/stacks/supabase/templates/root/src/common/assertions.ts +6 -0
  199. package/stacks/supabase/templates/root/src/common/db.ts +32 -0
  200. package/stacks/supabase/templates/root/src/common/loadPostgresEventstore.ts +23 -0
  201. package/stacks/supabase/templates/root/src/common/parseEndpoint.ts +51 -0
  202. package/stacks/supabase/templates/root/src/common/processorDlq.ts +28 -0
  203. package/stacks/supabase/templates/root/src/common/realtimeBroadcast.ts +19 -0
  204. package/stacks/supabase/templates/root/src/common/replay.ts +16 -0
  205. package/stacks/supabase/templates/root/src/common/routes.ts +23 -0
  206. package/stacks/supabase/templates/root/src/common/testHelpers.ts +54 -0
  207. package/stacks/supabase/templates/root/src/supabase/README.md +141 -0
  208. package/stacks/supabase/templates/root/src/supabase/api.ts +56 -0
  209. package/stacks/supabase/templates/root/src/supabase/requireOrgaAdmin.ts +32 -0
  210. package/stacks/supabase/templates/root/src/supabase/requireSysUser.ts +40 -0
  211. package/stacks/supabase/templates/root/src/supabase/requireUser.ts +72 -0
  212. package/stacks/supabase/templates/root/src/swagger.ts +34 -0
  213. package/stacks/supabase/templates/root/src/util/assertions.ts +6 -0
  214. package/stacks/supabase/templates/root/src/util/hash.ts +9 -0
  215. package/stacks/supabase/templates/root/src/util/sanitize.ts +23 -0
  216. package/stacks/supabase/templates/root/supabase/config.toml +295 -0
  217. package/stacks/supabase/templates/root/supabase/migrations/V1__schema.sql.example +12 -0
  218. package/stacks/supabase/templates/root/supabase/seed.sql +1 -0
  219. package/stacks/supabase/templates/root/tsconfig.json +32 -0
  220. package/stacks/supabase/templates/root/vercel.json +8 -0
@@ -0,0 +1,497 @@
1
+ ---
2
+ name: eventmodeling-designing-event-models
3
+ description: "Designs event-sourced domain models. Maps business processes to immutable events and state projections. Events are the source of truth; state is derived from events for command validation. Use when designing event streaming architectures from domain analysis. Do not use for: brainstorming events from scratch (use eventmodeling-brainstorming-events), optimizing stream sizing or snapshotting (use eventmodeling-optimizing-stream-design), or translating external system events (use eventmodeling-translating-external-events)."
4
+ allowed-tools:
5
+ - AskUserQuestion
6
+ - Write
7
+ - Bash
8
+ ---
9
+
10
+ # Designing Event Models
11
+
12
+ > **Before doing anything else**, invoke the `connect` skill to resolve `TOKEN`, `BOARD_ID`, `ORG_ID`, and `BASE_URL`. Then invoke the `learn-eventmodelers-api` skill to load the full API reference. Do not proceed until both skills have been loaded.
13
+
14
+ ## Interview Phase (Optional)
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
+ ```text
90
+ WRONG: Using DDD Aggregate as command state
91
+ OrderAggregate { orderId, customerId, items[], total, status, paymentId, address, shippedAt, cancelledAt, ... }
92
+ ↑ This is a READ MODEL, not command state
93
+ ↓ NEVER use for command validation
94
+ handleConfirmOrder(OrderAggregate)
95
+ handleShipOrder(OrderAggregate)
96
+ handleCancelOrder(OrderAggregate)
97
+
98
+ CORRECT: Minimal state per command
99
+ ConfirmOrderState { status, orderId }
100
+
101
+ handleConfirmOrder(ConfirmOrderState)
102
+
103
+ ShipOrderState { status, orderId, paymentId }
104
+
105
+ handleShipOrder(ShipOrderState)
106
+
107
+ CancelOrderState { status, orderId, createdAt }
108
+
109
+ handleCancelOrder(CancelOrderState)
110
+
111
+ OrderSummaryView { orderId, customerId, items[], total, status, paymentId, ... }
112
+ ↑ This is for UI queries, NOT command validation
113
+ ```
114
+
115
+ ## Purpose
116
+ Converts domain analysis into the event sourcing architecture pattern:
117
+
118
+ **UI/Processor** → **Command** → [Command State Read Model] → **Event** → **Query Read Models** - **UI/Processor**: Entry points that trigger intent
119
+ - **Command**: Intent data (can be rejected)
120
+ - **Stream Root**: Logical grouping of immutable events (NOT a DDD aggregate bundle)
121
+ - **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)
122
+ - **Event**: Result of successful command (immutable fact: command data + implicit context)
123
+ - **Query Read Models**: Rich projections of events optimized for UI/Processor queries. Separate from command state. (Categorized as "Query Models" for semantic clarity)
124
+
125
+ ## Workflow
126
+
127
+ Given a domain analysis, design a complete event-sourced model:
128
+
129
+ ### 1. Design Event Streams
130
+ Events are the immutable source of truth. Each stream holds facts about one entity:
131
+ - **Stream Name**: Entity type + identity (Order:order-123)
132
+ - **Event Type**: What changed? (past tense: Created, Confirmed, Shipped)
133
+ - **Event Data**: Combines command input + implicit stream state facts
134
+ - **Causality**: Triggered by which command?
135
+
136
+ Format:
137
+ ```text
138
+ Stream: Order:order-123
139
+
140
+ Events (chronological):
141
+ 1. OrderCreated
142
+ Triggered by: CreateOrder command
143
+ Data: customerId, items[], total, shippingAddress, createdAt
144
+ (from command: customerId, items[], shippingAddress)
145
+ (implicit: total calculated from items)
146
+
147
+ 2. OrderConfirmed
148
+ Triggered by: ConfirmOrder command
149
+ Data: paymentId, confirmedAt
150
+ (from command: paymentId)
151
+ (implicit: orderId from stream, previous status verified)
152
+
153
+ 3. OrderShipped
154
+ Triggered by: ShipOrder command
155
+ Data: shipmentId, shippedAt
156
+ (from command: shipmentId)
157
+ (implicit: orderId, confirmed status verified)
158
+ ```
159
+
160
+ **Key Rules**:
161
+ - Events are **immutable facts** from successful commands
162
+ - Event data = command input + implicit stream state context
163
+ - Stream identity is explicit (Order:order-123)
164
+ - Event order matters for state reconstruction
165
+ - Never modify or delete events
166
+ - Events only exist if command succeeded
167
+
168
+ ### 2. Design Command State Read Models (Minimal Per-Command)
169
+
170
+ **Critical Rule: Each command must have its own read model (command state). NEVER share read models between commands.** **Naming Convention (for Automation)**:
171
+ - `[CommandName]State` = Implemented command state read model
172
+ - `[CommandName]StateToDo` = Planned command state read model (marked for implementation)
173
+
174
+ Examples:
175
+ - `PublishReviewState` = implemented
176
+ - `EditReviewStateToDo` = planned, needs implementation
177
+ - `SellerRespondState` = implemented
178
+
179
+ **Semantic Categorization**: These are read models, but categorized as "Command State" based on their purpose (command validation, not UI queries).
180
+
181
+ Command state read models are **derived** from events and **minimal**:
182
+ - Read only events needed for a specific command's decision
183
+ - Build state by replaying only relevant events
184
+ - **ENFORCEMENT**: Different commands = different read model interfaces. Period.
185
+ - Each command handler defines what state projection it needs (and ONLY what it needs)
186
+ - Projection can be regenerated from events at any time
187
+
188
+ Example for Order stream with separate command state read model for EACH command:
189
+
190
+ ```text
191
+ ## ConfirmOrder Command (IMPLEMENTED)
192
+ State interface: ConfirmOrderState { status, orderId }
193
+ Builder: buildConfirmOrderState(events)
194
+ Naming: [CommandName]State = implemented
195
+ - OrderCreated event → Set status='Draft'
196
+ - OrderConfirmed event → Set status='Confirmed'
197
+ (SKIP: items, total, shipping - not needed for this command)
198
+
199
+ ## ShipOrder Command (IMPLEMENTED)
200
+ State interface: ShipOrderState { status, orderId, paymentId }
201
+ Builder: buildShipOrderState(events)
202
+ Naming: [CommandName]State = implemented
203
+ (DIFFERENT from ConfirmOrderState)
204
+ - OrderCreated event → (skip)
205
+ - OrderConfirmed event → Set status='Confirmed', set paymentId
206
+ - OrderShipped event → Set status='Shipped'
207
+
208
+ ## CancelOrder Command (PLANNED - NOT IMPLEMENTED)
209
+ State interface: CancelOrderStateToDo { status, orderId, createdAt }
210
+ Builder: buildCancelOrderStateToDo(events) [STUB - TODO]
211
+ Naming: [CommandName]StateToDo = planned, needs implementation
212
+ (DIFFERENT from both above)
213
+ - OrderCreated event → Set status='Draft', createdAt
214
+ - OrderCancelled event → Set status='Cancelled'
215
+ ```
216
+
217
+ **Enforcement Rule**:
218
+ - ConfirmOrderState used ONLY by handleConfirmOrder
219
+ - ShipOrderState used ONLY by handleShipOrder
220
+ - NEVER share state between commands
221
+ - NEVER create a single "OrderState" for all Order commands
222
+
223
+ This is **NOT** a full aggregate state bundle—it's minimal, command-specific state access.
224
+
225
+ ### 3. Design Commands
226
+ Commands are **intent data from UI or Processor**:
227
+ - Represent what user/system wants to do
228
+ - Can be rejected (validation failure)
229
+ - Only UI or Processor can issue commands
230
+ - Load current stream state for validation
231
+ - Produce events if valid, or reject if invalid
232
+
233
+ Format:
234
+ ```text
235
+ Command: ConfirmOrder
236
+ Source: UI or Processor (only these can issue)
237
+ Input: orderId, paymentId
238
+
239
+ Processing:
240
+ 1. Load current state from Order:orderId stream
241
+ 2. Validate preconditions:
242
+ - state.status === 'Draft' (reject: already confirmed)
243
+ - paymentId is valid (reject: invalid payment)
244
+ 3. If all valid:
245
+ - Produce: OrderConfirmed event
246
+ - Data: paymentId, confirmedAt
247
+ - Implicit: orderId (from stream), previous status (from state)
248
+ 4. If any validation fails:
249
+ - Reject: return error (no event created)
250
+
251
+ Outcomes:
252
+ Success: OrderConfirmed event appended to stream
253
+ Rejection: Error returned, no event created
254
+ ```
255
+
256
+ **Key Rules**:
257
+ - Only UI or Processor can issue commands (entry points)
258
+ - One command per UI/Processor action
259
+ - Commands validate against stream state
260
+ - Successful command → Event(s) created
261
+ - Failed validation → Command rejected, no event
262
+ - Commands are synchronous decision logic (pure)
263
+
264
+ ### 4. Design Read Models
265
+ Read models are **projections of events for UI/Processor queries**:
266
+ - Built from events (only source is events)
267
+ - Optimized for specific query patterns
268
+ - Consumed by UI or Processor (for display/decision)
269
+ - Can be regenerated from events anytime
270
+
271
+ Format:
272
+ ```text
273
+ ReadModel: OrderSummaryView
274
+ Purpose: UI displays customer order list, Processor checks order status
275
+
276
+ Subscribed to events:
277
+ - OrderCreated
278
+ - OrderConfirmed
279
+ - OrderShipped
280
+ - OrderCancelled
281
+
282
+ Data (optimized for queries):
283
+ {
284
+ orderId: string
285
+ customerId: string
286
+ total: number
287
+ status: string
288
+ createdAt: Date
289
+ confirmedAt?: Date
290
+ shippedAt?: Date
291
+ }
292
+
293
+ Update from events:
294
+ - OrderCreated → Insert row (id, customer, total, status='Draft')
295
+ - OrderConfirmed → Update status='Confirmed', set confirmedAt
296
+ - OrderShipped → Update status='Shipped', set shippedAt
297
+ - OrderCancelled → Update status='Cancelled'
298
+
299
+ Consumed by:
300
+ - UI: displays list of orders
301
+ - Processor: checks if order can be shipped
302
+ ```
303
+
304
+ ### 5. Document Event Causality
305
+ Show how events relate to each other:
306
+
307
+ ```text
308
+ Command Flow:
309
+ CreateOrder command
310
+ → OrderCreated event
311
+ ↓ (may trigger external process)
312
+ ConfirmOrder command (reads OrderCreated state)
313
+ → OrderConfirmed event
314
+ ↓ (may trigger)
315
+ ShipOrder command (reads OrderCreated + OrderConfirmed state)
316
+ → OrderShipped event
317
+ ```
318
+
319
+ ### 6. Document State Transitions
320
+ Show valid state transitions:
321
+
322
+ ```text
323
+ Order Stream State Transitions:
324
+
325
+ Initial state: (empty stream)
326
+
327
+ CreateOrder → OrderCreated
328
+
329
+ State: Draft
330
+
331
+ Draft state:
332
+ → ConfirmOrder → OrderConfirmed → State: Confirmed
333
+ → CancelOrder → OrderCancelled → State: Cancelled
334
+
335
+ Confirmed state:
336
+ → ShipOrder → OrderShipped → State: Shipped
337
+ → CancelOrder (rejected - already confirmed)
338
+
339
+ Shipped state:
340
+ → No more transitions allowed
341
+ ```
342
+
343
+ ### Output Format
344
+
345
+ Present complete model as:
346
+
347
+ ```markdown
348
+ # Event Model: [Domain]
349
+
350
+ ## Event Streams
351
+
352
+ ### Stream: Order
353
+
354
+ **Identity**: orderId
355
+
356
+ **Events**:
357
+ - OrderCreated: Initial event creating the order
358
+ Data: customerId, items[], total, shippingAddress
359
+
360
+ - OrderConfirmed: Payment confirmed
361
+ Data: paymentId, confirmedAt
362
+
363
+ - OrderShipped: Order shipped
364
+ Data: shipmentId, shippedAt
365
+
366
+ - OrderCancelled: Order cancelled
367
+ Data: cancelledAt, reason
368
+
369
+ **State Projection (Human Example)**:
370
+ For the ConfirmOrder command, we need minimal state:
371
+ ```text
372
+ ConfirmOrderState:
373
+ - orderId: 'order-123'
374
+ - status: 'Draft'
375
+ ```
376
+
377
+ For the ShipOrder command, we need different data:
378
+ ```text
379
+ ShipOrderState:
380
+ - orderId: 'order-123'
381
+ - status: 'Confirmed'
382
+ - paymentId: 'payment-456'
383
+ ```
384
+
385
+ ---
386
+
387
+ ## Commands
388
+
389
+ ### Command: CreateOrder
390
+ - Input: customerId, items[], shippingAddress
391
+ - Validation: Items valid, customerId exists
392
+ - Events produced: OrderCreated
393
+ - Possible outcomes: Success (OrderCreated) or Validation error
394
+
395
+ ### Command: ConfirmOrder
396
+ - Input: orderId, paymentId
397
+ - Validation: Order in Draft status, payment validated
398
+ - Events produced: OrderConfirmed
399
+ - Possible outcomes: Success or "Already confirmed" error
400
+
401
+ ---
402
+
403
+ ## Read Models (Optional)
404
+
405
+ ### ReadModel: OrderSummaryView
406
+ - Purpose: Quick lookup of order status
407
+ - Events: OrderCreated, OrderConfirmed, OrderShipped, OrderCancelled
408
+ - Queries served: GetOrder(orderId), ListOrdersByCustomer(customerId)
409
+
410
+ ---
411
+
412
+ ## Implementation Notes
413
+ - All state is derived from events
414
+ - Commands validate against derived state
415
+ - No transaction across streams
416
+ - Events are source of truth
417
+ - Read models can be rebuilt from events
418
+ ```
419
+
420
+ ## Key Event Sourcing Principles
421
+
422
+ 1. **Events are Facts**: Events describe what happened, not what might happen
423
+ 2. **Immutable Event Log**: Events are appended, never modified
424
+ 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.
425
+ 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.
426
+ 5. **Commands are Pure**: No side effects, just decision logic against minimal state
427
+ 6. **Read Models are Separate**: Read models (projections) are separate from command-validation state. Read models can have rich data; command state stays minimal.
428
+ 7. **Event Causality**: Commands → [minimal state] → Events → [read models]
429
+
430
+ ## Design Patterns
431
+
432
+ ### Compensation Pattern
433
+ Handle errors by appending compensation events:
434
+ ```text
435
+ Command: ProcessPayment failed
436
+ → PaymentFailed event
437
+ (triggered by external error)
438
+ → OrderCancelled event (compensation)
439
+ (or retry logic)
440
+ ```
441
+
442
+ ### Temporal Queries
443
+ Answer "what was the state at time T?":
444
+ ```text
445
+ Replay events up to timestamp T
446
+ → Get historical state
447
+ ```
448
+
449
+ ## Best Practices for Event Model Design
450
+
451
+ ### 1. Design Minimal State Per Command
452
+ Each command handler only loads the state it needs:
453
+ - "LoadOrderState loads { id, items, total, shipping, customer, payment, status, ... }"
454
+ - "ConfirmOrderState loads { status, orderId }"
455
+ - "ShipOrderState loads { status, orderId, paymentConfirmed }"
456
+
457
+ ### 2. Separate Command State from Query Models
458
+ Keep command-validation state and read models strictly separate:
459
+ - **Command State** (minimal): Used by handlers to validate commands
460
+ - **Query Models** (rich): Used by UI/Processor to display/query data
461
+ - Never share between them
462
+
463
+ ### 3. Name State Interfaces by Command
464
+ Use the pattern `[CommandName]State` to make the relationship explicit:
465
+ - `PublishReviewState` for PublishReview command
466
+ - `EditReviewState` for EditReview command
467
+ - `ReviewState` (ambiguous - which command?)
468
+
469
+ ### 4. Document State Transitions Clearly
470
+ Show what state changes trigger what commands:
471
+ - Include initial state
472
+ - Show all valid transitions
473
+ - Mark impossible transitions (and why)
474
+ - Document rejection conditions
475
+
476
+ ### 5. Make All Constraints Explicit
477
+ Transform "obvious" business rules into documented invariants:
478
+ - "Obviously can't ship an unconfirmed order"
479
+ - "ShipOrder validation: requires status='Confirmed' with paymentId"
480
+
481
+ ### 6. Keep Event Data Factual
482
+ Events record facts, not derived values:
483
+ - "OrderCreated { items, total }" (total is computed from items)
484
+ - "OrderCreated { items[] with unitPrice, shippingAddress }" (total computed in projection)
485
+
486
+ ## Quality Checklist
487
+
488
+ - [ ] All events are immutable facts (past tense)
489
+ - [ ] Events contain only captured data, no computed fields
490
+ - [ ] State projection is deterministic from events
491
+ - [ ] Each command validates against current state
492
+ - [ ] Commands either produce events or reject
493
+ - [ ] Event causality is clear
494
+ - [ ] State transitions are documented
495
+ - [ ] No references between streams in events
496
+ - [ ] Read models are optional, not required
497
+ - [ ] All logic is state → events (pure functions)