eva4j 1.0.16 → 1.0.18

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 (151) hide show
  1. package/AGENTS.md +220 -5
  2. package/DOMAIN_YAML_GUIDE.md +188 -3
  3. package/FUTURE_FEATURES.md +33 -52
  4. package/QUICK_REFERENCE.md +8 -4
  5. package/bin/eva4j.js +70 -2
  6. package/config/defaults.json +1 -0
  7. package/docs/CAMUNDA_DMN_GUIDE.md +1380 -0
  8. package/docs/KAFKA_PRODUCTION_CONFIG.md +441 -0
  9. package/docs/RABBITMQ_PRODUCTION_CONFIG.md +227 -0
  10. package/docs/commands/ADD_RABBITMQ_CLIENT.md +192 -0
  11. package/docs/commands/EVALUATE_SYSTEM.md +290 -10
  12. package/docs/commands/GENERATE_RABBITMQ_EVENT.md +341 -0
  13. package/docs/commands/GENERATE_RABBITMQ_LISTENER.md +595 -0
  14. package/docs/commands/GENERATE_TEMPORAL_FLOW.md +52 -12
  15. package/docs/commands/INDEX.md +27 -3
  16. package/docs/prototype/TEMPORAL_COMMUNICATION_PATTERNS.md +731 -0
  17. package/docs/prototype/TEMPORAL_DESIGN_METHODOLOGY.md +740 -0
  18. package/docs/prototype/system/RISKS.md +277 -0
  19. package/docs/prototype/system/customers.yaml +133 -0
  20. package/docs/prototype/system/inventory.yaml +109 -0
  21. package/docs/prototype/system/notifications.yaml +131 -0
  22. package/docs/prototype/system/orders.yaml +241 -0
  23. package/docs/prototype/system/payments.yaml +256 -0
  24. package/docs/prototype/system/products.yaml +168 -0
  25. package/docs/prototype/system/system.yaml +269 -0
  26. package/examples/domain-endpoints-multi-aggregate.yaml +140 -0
  27. package/examples/domain-events.yaml +26 -0
  28. package/examples/domain-read-models.yaml +113 -0
  29. package/examples/system/customer.yaml +89 -0
  30. package/examples/system/orders.yaml +119 -0
  31. package/examples/system/product.yaml +27 -0
  32. package/examples/system/system.yaml +80 -0
  33. package/package.json +1 -1
  34. package/read-model-spec.md +664 -0
  35. package/src/agents/design-gap-analyst-temporal.agent.md +452 -0
  36. package/src/agents/design-gap-analyst.agent.md +383 -0
  37. package/src/agents/design-reviewer-temporal.agent.md +412 -0
  38. package/src/agents/design-reviewer.agent.md +34 -5
  39. package/src/agents/implement-use-cases.prompt.md +179 -0
  40. package/src/agents/ux-gap-analyst.agent.md +412 -0
  41. package/src/commands/add-rabbitmq-client.js +261 -0
  42. package/src/commands/add-temporal-client.js +22 -2
  43. package/src/commands/build.js +267 -11
  44. package/src/commands/evaluate-system.js +700 -13
  45. package/src/commands/generate-entities.js +560 -24
  46. package/src/commands/generate-http-exchange.js +3 -0
  47. package/src/commands/generate-kafka-event.js +3 -0
  48. package/src/commands/generate-kafka-listener.js +3 -0
  49. package/src/commands/generate-rabbitmq-event.js +665 -0
  50. package/src/commands/generate-rabbitmq-listener.js +205 -0
  51. package/src/commands/generate-record.js +2 -2
  52. package/src/commands/generate-resource.js +4 -1
  53. package/src/commands/generate-temporal-activity.js +970 -33
  54. package/src/commands/generate-temporal-flow.js +98 -38
  55. package/src/commands/generate-temporal-system.js +708 -0
  56. package/src/commands/generate-usecase.js +4 -1
  57. package/src/skills/build-system-yaml/SKILL.md +343 -2
  58. package/src/skills/build-system-yaml/references/domain-yaml-spec.md +253 -26
  59. package/src/skills/build-system-yaml/references/module-spec.md +90 -9
  60. package/src/skills/build-system-yaml/references/system-yaml-spec.md +36 -0
  61. package/src/skills/build-temporal-system/SKILL.md +752 -0
  62. package/src/skills/build-temporal-system/references/temporal-communication-patterns.md +167 -0
  63. package/src/skills/build-temporal-system/references/temporal-domain-yaml-spec.md +449 -0
  64. package/src/skills/build-temporal-system/references/temporal-module-spec.md +353 -0
  65. package/src/skills/build-temporal-system/references/temporal-system-yaml-spec.md +326 -0
  66. package/src/skills/implement-use-case/SKILL.md +350 -0
  67. package/src/skills/implement-use-case/references/use-case-patterns.md +980 -0
  68. package/src/skills/requirements-elicitation/SKILL.md +228 -0
  69. package/src/skills/requirements-elicitation/references/interview-framework.md +260 -0
  70. package/src/skills/requirements-elicitation/references/output-templates.md +368 -0
  71. package/src/utils/bounded-context-diagram.js +844 -0
  72. package/src/utils/config-manager.js +4 -2
  73. package/src/utils/domain-validator.js +495 -17
  74. package/src/utils/naming.js +20 -0
  75. package/src/utils/system-validator.js +169 -11
  76. package/src/utils/system-yaml-parser.js +318 -0
  77. package/src/utils/temporal-validator.js +497 -0
  78. package/src/utils/validator.js +3 -1
  79. package/src/utils/yaml-to-entity.js +281 -9
  80. package/templates/aggregate/AggregateRepository.java.ejs +4 -0
  81. package/templates/aggregate/AggregateRepositoryImpl.java.ejs +8 -0
  82. package/templates/aggregate/AggregateRoot.java.ejs +38 -4
  83. package/templates/aggregate/DomainEventHandler.java.ejs +116 -22
  84. package/templates/aggregate/JpaAggregateRoot.java.ejs +4 -4
  85. package/templates/aggregate/JpaEntity.java.ejs +2 -2
  86. package/templates/base/docker/rabbitmq-services.yaml.ejs +12 -0
  87. package/templates/base/resources/parameters/develop/kafka.yaml.ejs +5 -0
  88. package/templates/base/resources/parameters/develop/rabbitmq.yaml.ejs +15 -0
  89. package/templates/base/resources/parameters/develop/temporal.yaml.ejs +0 -3
  90. package/templates/base/resources/parameters/local/kafka.yaml.ejs +5 -0
  91. package/templates/base/resources/parameters/local/rabbitmq.yaml.ejs +15 -0
  92. package/templates/base/resources/parameters/local/temporal.yaml.ejs +0 -3
  93. package/templates/base/resources/parameters/production/kafka.yaml.ejs +39 -8
  94. package/templates/base/resources/parameters/production/rabbitmq.yaml.ejs +32 -0
  95. package/templates/base/resources/parameters/production/temporal.yaml.ejs +0 -3
  96. package/templates/base/resources/parameters/test/kafka.yaml.ejs +12 -6
  97. package/templates/base/resources/parameters/test/rabbitmq.yaml.ejs +15 -0
  98. package/templates/base/resources/parameters/test/temporal.yaml.ejs +0 -3
  99. package/templates/base/root/AGENTS.md.ejs +1 -1
  100. package/templates/crud/DeleteCommandHandler.java.ejs +19 -1
  101. package/templates/crud/EndpointsController.java.ejs +1 -1
  102. package/templates/crud/ScaffoldCommand.java.ejs +5 -2
  103. package/templates/crud/ScaffoldCommandHandler.java.ejs +3 -1
  104. package/templates/crud/ScaffoldQuery.java.ejs +5 -2
  105. package/templates/crud/ScaffoldQueryHandler.java.ejs +3 -1
  106. package/templates/crud/SubEntityRemoveCommand.java.ejs +1 -1
  107. package/templates/crud/UpdateCommandHandler.java.ejs +53 -2
  108. package/templates/evaluate/report.html.ejs +1447 -90
  109. package/templates/kafka-event/KafkaConfigBean.java.ejs +1 -1
  110. package/templates/kafka-event/KafkaMessageBroker.java.ejs +3 -3
  111. package/templates/ports/PortAclMapper.java.ejs +35 -0
  112. package/templates/ports/PortFeignAdapter.java.ejs +7 -22
  113. package/templates/ports/PortFeignClient.java.ejs +4 -0
  114. package/templates/ports/PortResponseDto.java.ejs +1 -1
  115. package/templates/rabbitmq-event/RabbitConfigBean.java.ejs +33 -0
  116. package/templates/rabbitmq-event/RabbitConfigExchange.java.ejs +12 -0
  117. package/templates/rabbitmq-event/RabbitMessageBroker.java.ejs +35 -0
  118. package/templates/rabbitmq-event/RabbitMessageBrokerMethod.java.ejs +9 -0
  119. package/templates/rabbitmq-listener/RabbitConfigConsumerBean.java.ejs +33 -0
  120. package/templates/rabbitmq-listener/RabbitConfigConsumerExchange.java.ejs +12 -0
  121. package/templates/rabbitmq-listener/RabbitListenerClass.java.ejs +82 -0
  122. package/templates/rabbitmq-listener/RabbitListenerSimple.java.ejs +56 -0
  123. package/templates/read-model/ReadModelDomain.java.ejs +46 -0
  124. package/templates/read-model/ReadModelJpa.java.ejs +58 -0
  125. package/templates/read-model/ReadModelJpaRepository.java.ejs +13 -0
  126. package/templates/read-model/ReadModelKafkaListener.java.ejs +64 -0
  127. package/templates/read-model/ReadModelRabbitListener.java.ejs +71 -0
  128. package/templates/read-model/ReadModelRepository.java.ejs +42 -0
  129. package/templates/read-model/ReadModelRepositoryImpl.java.ejs +85 -0
  130. package/templates/read-model/ReadModelSyncHandler.java.ejs +54 -0
  131. package/templates/shared/configurations/kafkaConfig/KafkaConfig.java.ejs +18 -4
  132. package/templates/shared/configurations/rabbitmqConfig/RabbitMQConfig.java.ejs +100 -0
  133. package/templates/shared/configurations/temporalConfig/TemporalConfig.java.ejs +2 -64
  134. package/templates/shared/configurations/temporalConfig/TemporalWorkerFactoryLifecycle.java.ejs +41 -0
  135. package/templates/temporal-activity/ActivityImpl.java.ejs +68 -2
  136. package/templates/temporal-activity/ActivityInput.java.ejs +14 -0
  137. package/templates/temporal-activity/ActivityInterface.java.ejs +7 -1
  138. package/templates/temporal-activity/ActivityOutput.java.ejs +14 -0
  139. package/templates/temporal-activity/NestedType.java.ejs +12 -0
  140. package/templates/temporal-activity/SharedActivityInput.java.ejs +14 -0
  141. package/templates/temporal-activity/SharedActivityInterface.java.ejs +15 -0
  142. package/templates/temporal-activity/SharedActivityOutput.java.ejs +14 -0
  143. package/templates/temporal-activity/SharedNestedType.java.ejs +12 -0
  144. package/templates/temporal-flow/ModuleHeavyActivity.java.ejs +6 -0
  145. package/templates/temporal-flow/ModuleLightActivity.java.ejs +6 -0
  146. package/templates/temporal-flow/ModuleTemporalWorkerConfig.java.ejs +58 -0
  147. package/templates/temporal-flow/WorkFlowImpl.java.ejs +172 -12
  148. package/templates/temporal-flow/WorkFlowInput.java.ejs +11 -0
  149. package/templates/temporal-flow/WorkFlowInterface.java.ejs +5 -4
  150. package/templates/temporal-flow/WorkFlowService.java.ejs +42 -12
  151. package/COMMAND_EVALUATION.md +0 -911
@@ -0,0 +1,752 @@
1
+ ---
2
+ name: build-temporal-system
3
+ description: 'Build or update a Temporal-based system with eva4j. Use when designing a system architecture that uses Temporal as the orchestration engine for cross-module communication instead of Kafka/RabbitMQ. Invoke this skill when the user mentions Temporal workflows, sagas, durable orchestration, activity-based communication between modules, or wants to design a system where Temporal replaces both async messaging and sync HTTP calls between internal modules. USE FOR: Temporal system architecture design, designing cross-module workflows and sagas, defining activities per module, building system.yaml with orchestration section, generating domain YAMLs with activities/workflows/notifies, C4 diagrams for Temporal systems. DO NOT USE FOR: Kafka/RabbitMQ-based systems (use build-system-yaml instead), single-module projects without cross-module communication, Temporal worker implementation details.'
4
+ argument-hint: 'Describe the system or modules that need Temporal orchestration (e.g., e-commerce with orders, payments, inventory, and notifications orchestrated by Temporal)'
5
+ ---
6
+
7
+ # Build Temporal System
8
+
9
+ You play two simultaneous roles:
10
+
11
+ 1. **Software Architect** expert in DDD, hexagonal architecture, and Temporal workflow orchestration. You decide how to structure the system into modules, what patterns to apply, and how bounded contexts communicate via Temporal activities and workflows.
12
+
13
+ 2. **Business domain expert** — the domain is defined by the user in the chat. You reason as someone who deeply understands the business rules, processes, and constraints: you know which operations make sense, which flows are mandatory, which invariants must never be violated, and how actors interact with the system.
14
+
15
+ > **Clarity principle:** when you detect ambiguities that could affect design decisions, **ask the user** before continuing. Never more than 3–5 questions at a time. Only genuinely functional questions.
16
+
17
+ ## Project discovery
18
+
19
+ Before generating anything, read these project files for context:
20
+ - `system/system.yaml` — if it exists, the project already has architecture defined; read it first
21
+ - `package.json` or project configuration for name, groupId, versions
22
+ - [AGENTS.md](/AGENTS.md) — eva4j patterns and conventions
23
+
24
+ ## Language of generated files
25
+
26
+ > **ABSOLUTE RULE — ALWAYS IN ENGLISH:**
27
+ > All content in `.yaml` and `.md` files must be in English: module names, descriptions, comments, titles, invariants, narrative text. The conversation can be in any language; the files, always in English.
28
+
29
+ ## When to use this skill
30
+
31
+ - Design the initial architecture of a new system using Temporal
32
+ - Add modules to an existing Temporal-based project
33
+ - Define cross-module workflows (sagas, orchestrated processes)
34
+ - Define activities that modules expose for inter-module communication
35
+ - Define single-module internal workflows (retries, timeouts, scheduling)
36
+ - Review or refactor module structure in a Temporal system
37
+ - Generate C4 diagrams for Temporal systems
38
+
39
+ ---
40
+
41
+ ## Core Architecture: Temporal as Orchestration Engine
42
+
43
+ Temporal replaces **both** Kafka (async messaging) and Feign (sync HTTP) for inter-module communication. The key changes from a broker-based system:
44
+
45
+ | Concept | Kafka/RabbitMQ System | Temporal System |
46
+ |---------|----------------------|-----------------|
47
+ | Cross-module communication | Events (async) + Feign (sync) | Remote Activities + Child Workflows |
48
+ | Data synchronization | Read Models (local projections) | On-demand reads via Activities |
49
+ | Saga / compensation | Manual event choreography | Durable Saga with `compensation:` |
50
+ | Fire-and-forget | Publish event + consumer group | `type: async` activity (Async.function) |
51
+ | Retry with backoff | Consumer retry config | Activity `retryPolicy:` |
52
+ | Timeout handling | TTL + dead letter queue | `Workflow.await()` + timeout |
53
+
54
+ ### Key Principles
55
+
56
+ 1. **No Read Models** — data from other modules is fetched on-demand via Remote Activities of type read (`GetCustomerById`, `GetProductsByIds`). No local projections needed.
57
+ 2. **No listeners/consumers** — modules don't subscribe to events. Workflows invoke activities directly.
58
+ 3. **No Feign/HTTP between modules** — `ports:` is only for **external** services (payment gateways, email providers, third-party APIs).
59
+ 4. **Events use `notifies:`** — Domain Events reference the workflow they trigger, not a topic.
60
+ 5. **Activities = module capabilities** — each module declares what it can do. Workflows compose these capabilities.
61
+ 6. **Activities are workflow-only** — handlers, use cases, and REST controllers NEVER invoke activities directly. If a handler needs cross-module data, it emits a Domain Event → triggers a workflow → workflow invokes the required activities. Even local activities are invoked from single-module workflows in `domain.yaml`, not from handlers.
62
+
63
+ ---
64
+
65
+ ## Workflow — complete step sequence
66
+
67
+ All generated files go inside the `system/` directory at the project root. **NEVER** place files at the project root level.
68
+
69
+ | Step | Generated file (inside `system/` dir) | Reference |
70
+ |------|----------------------------------------|-----------||
71
+ | 1 | _(information gathering)_ | This file |
72
+ | 2–5 | `system/system.yaml` | This file + `references/temporal-system-yaml-spec.md` |
73
+ | 6 | `system/system.md` | `references/temporal-module-spec.md` (system.md section) |
74
+ | 6.5 | `system/c4-context.mmd` + `system/c4-container.mmd` | This file (C4 section) |
75
+ | 7 | `system/{module}.yaml` (one per module) | `references/temporal-domain-yaml-spec.md` |
76
+ | 8 | `system/{module}.md` (one per module) | `references/temporal-module-spec.md` |
77
+ | 9a | `AGENTS.md` (project root — rewrite) | This file (Step 9) |
78
+ | 9b | `system/VALIDATION_FLOWS.md` | This file (Step 9) |
79
+ | 9c | `system/USER_FLOWS.md` | This file (Step 9) |
80
+
81
+ Execute **all** steps in order before returning control to the user.
82
+
83
+ ---
84
+
85
+ ## Step 1 — Gather information
86
+
87
+ If the user didn't provide all the data, **ask** before generating:
88
+
89
+ 0. **Business context** — What is the domain? Actors, key processes, important rules.
90
+ 1. **List of modules** with their responsibility (plural, kebab-case)
91
+ 2. **Endpoints REST** per module (method + path + use case)
92
+ 3. **Cross-module flows**: What business events trigger multi-module processes? Which modules participate?
93
+ 4. **Internal module flows**: Retries, timeouts, scheduling, verification flows?
94
+ 5. **External services**: Payment gateways, email providers, third-party APIs?
95
+ 6. **Temporal configuration**: Namespace, target address?
96
+
97
+ > If `system/system.yaml` already exists, read it and ask only about changes.
98
+
99
+ Apply the functional role: suggest necessary modules not mentioned, propose coherent workflows, anticipate invariants. Confirm before adding unsolicited elements.
100
+
101
+ ### Decision Matrix: Workflow vs Domain Event
102
+
103
+ For each business event, ask: **Does something MUST happen in ANOTHER module when this occurs?**
104
+
105
+ | Answer | Result |
106
+ |--------|--------|
107
+ | YES — multi-step process, needs consistency | **Cross-module Workflow** (in system.yaml) |
108
+ | YES — single effect in one other module | **Simple Workflow** with 1 step (in system.yaml) |
109
+ | NO — internal module process needing durability | **Single-module Workflow** (in domain.yaml) |
110
+ | NO — nothing external reacts | **Domain Event internal** (no `notifies:`) |
111
+
112
+ > **⚠️ CRITICAL:** If a handler needs data from another module (e.g., cart handler needs product prices), do NOT invoke the activity directly from the handler. Instead, design a workflow that orchestrates the read activity (e.g., `GetProductsByIds`) and passes the result to subsequent steps. Activities are ONLY invoked from workflows.
113
+
114
+ ### Decision: Activity Type
115
+
116
+ | Question | Type |
117
+ |----------|------|
118
+ | Only reads data from this module? | **Read** (`GetXById`, `GetXsByIds`) |
119
+ | Modifies data and can be undone? | **Write** + `compensation:` |
120
+ | Modifies data irreversibly? | **Write** without compensation |
121
+ | Is the reverse of another activity? | **Compensation** (referenced in `compensation:`) |
122
+ | Is a non-critical side effect? | **Reactor** (invoked as `type: async`) |
123
+ | Is an internal module operation? | **Local** (invoked by module's own workflows) |
124
+
125
+ ---
126
+
127
+ ## Step 2 — Structure of system.yaml
128
+
129
+ Read `references/temporal-system-yaml-spec.md` for the complete structure, naming conventions, structural restrictions, and useCase patterns.
130
+
131
+ **Key structure:**
132
+
133
+ ```yaml
134
+ system:
135
+ name: project-name
136
+ groupId: com.example
137
+ javaVersion: 21
138
+ springBootVersion: 3.5.5
139
+ database: postgresql
140
+
141
+ orchestration:
142
+ enabled: true
143
+ engine: temporal
144
+ temporal:
145
+ target: localhost:7233
146
+ namespace: project-name
147
+
148
+ modules:
149
+ - name: orders
150
+ description: "Order lifecycle management"
151
+ exposes:
152
+ - method: POST
153
+ path: /orders
154
+ useCase: CreateOrder
155
+
156
+ workflows:
157
+ - name: PlaceOrderWorkflow
158
+ trigger:
159
+ module: orders
160
+ on: create
161
+ taskQueue: ORDER_WORKFLOW_QUEUE
162
+ saga: true
163
+ steps:
164
+ - activity: ReserveStock
165
+ target: inventory
166
+ type: sync
167
+ input: [orderId, items]
168
+ compensation: ReleaseStock
169
+ timeout: 10s
170
+ ```
171
+
172
+ ---
173
+
174
+ ## Step 3 — Mandatory rules (summary)
175
+
176
+ | Element | Convention | Example |
177
+ |---------|-----------|---------|
178
+ | Modules | plural, kebab-case | `orders`, `product-catalog` |
179
+ | Workflows | PascalCase + `Workflow` | `PlaceOrderWorkflow` |
180
+ | Activities | PascalCase, verb+noun | `ReserveStock`, `GetCustomerById` |
181
+ | Task Queues | SCREAMING_SNAKE + suffix | `ORDER_WORKFLOW_QUEUE` |
182
+ | Events | PascalCase + past + `Event` | `OrderPlacedEvent` |
183
+ | useCases | PascalCase, verb+noun | `CreateOrder`, `ConfirmOrder` |
184
+
185
+ **Critical restrictions:**
186
+ - Cross-module workflows go in `system.yaml`, single-module workflows go in `{domain}.yaml`
187
+ - Activities declare what the module **can do**, workflows compose them
188
+ - `ports:` only for **external** services (non-Temporal)
189
+ - No `listeners:`, no `readModels:`, no `messaging:` section
190
+ - Events use `notifies:` to reference workflows, not topics
191
+ - All activities accessed ONLY their own module's data
192
+ - Activities are invoked ONLY from workflows (`system.yaml` or `domain.yaml`). Handlers and use cases do NOT have access to activity interfaces
193
+ - Compensation must be explicitly declared for reversible steps in sagas
194
+
195
+ ---
196
+
197
+ ## Step 4 — Validation checklist
198
+
199
+ Before proposing the `system.yaml`, verify:
200
+
201
+ - [ ] Modules in plural kebab-case
202
+ - [ ] `orchestration:` section with `engine: temporal`
203
+ - [ ] No `messaging:` section (Temporal replaces it)
204
+ - [ ] No `integrations:` section (Temporal replaces async and sync)
205
+ - [ ] Each workflow has `trigger:` with `module:` and `on:`
206
+ - [ ] Each workflow step has `activity:`, `target:`, `type:`, `input:`
207
+ - [ ] Saga workflows have `saga: true` and steps with `compensation:` where needed
208
+ - [ ] Activities with `type: async` for non-critical steps (fire-and-forget)
209
+ - [ ] Activities with `type: sync` for steps that need results
210
+ - [ ] Task queues follow module-prefixed naming
211
+ - [ ] No workflows that only sync data — use on-demand reads instead
212
+ - [ ] No handler or use case directly invokes an activity — all activity calls go through workflows
213
+ - [ ] All in English
214
+ - [ ] File in `system/system.yaml`
215
+
216
+ ---
217
+
218
+ ## Step 5 — Present and continue
219
+
220
+ > **CRITICAL PATH RULE:** ALL generated files live inside the `system/` directory at the project root.
221
+ > NEVER create `system.yaml` at the project root. The correct path is ALWAYS `system/system.yaml`.
222
+ > Same for module files: `system/{module}.yaml`, `system/{module}.md`, `system/system.md`, etc.
223
+
224
+ 1. Create the `system/` directory at the project root if it doesn't exist
225
+ 2. Save the file as `system/system.yaml` (INSIDE the `system/` directory, NOT at the project root)
226
+ 3. Show the complete YAML
227
+ 4. Explain non-obvious decisions
228
+ 5. Mention warnings (coupling, diffuse responsibilities)
229
+ 6. Proceed immediately to steps 6 → 6.5 → 7 → 8
230
+
231
+ ---
232
+
233
+ ## Step 6 — Create system.md
234
+
235
+ Read `references/temporal-module-spec.md` (section "system.md structure") for the mandatory structure.
236
+
237
+ Save as `system/system.md` (inside the `system/` directory). The `system/system.md` is the **narrative technical specification** of the system. One `##` section per module with: detailed role, use cases, endpoints, activities exposed, workflows triggered.
238
+
239
+ ---
240
+
241
+ ## Step 6.5 — C4 Diagrams (Context + Container)
242
+
243
+ Immediately after `system.md`, generate **two Mermaid files** with C4 diagrams:
244
+
245
+ ### `system/c4-context.mmd` — Context Diagram
246
+
247
+ Shows the system as a **single box** surrounded by actors and external systems.
248
+
249
+ ```mermaid
250
+ C4Context
251
+ title System Context diagram for {System Name}
252
+
253
+ Person(user, "User", "Primary user who interacts with the system")
254
+
255
+ System(system, "{System Name}", "Core platform that manages {domain}")
256
+
257
+ System_Ext(paymentGw, "Payment Gateway", "Processes payments")
258
+
259
+ Rel(user, system, "Places orders", "HTTPS")
260
+ Rel(system, paymentGw, "Processes payments", "HTTPS")
261
+ ```
262
+
263
+ **Rules:**
264
+ - System is **one node** — don't decompose into modules here
265
+ - `System_Ext()` only for truly external services (from `ports:`)
266
+ - Derive actors from who consumes `exposes[]`
267
+
268
+ ### `system/c4-container.mmd` — Container Diagram
269
+
270
+ Decomposes the system into containers. Key difference from broker-based: **Temporal Server replaces the Message Broker**.
271
+
272
+ ```mermaid
273
+ C4Container
274
+ title Container diagram for {System Name}
275
+
276
+ Person(user, "User", "Primary user of the system")
277
+
278
+ System_Boundary(boundary, "{System Name}") {
279
+ Container(orders, "orders", "Spring Boot Module", "Order lifecycle management")
280
+ Container(payments, "payments", "Spring Boot Module", "Payment processing")
281
+
282
+ ContainerDb(db, "Database", "PostgreSQL", "Stores all module data")
283
+ Container(temporal, "Temporal Server", "Temporal", "Durable workflow orchestration")
284
+ }
285
+
286
+ System_Ext(paymentGw, "Payment Gateway", "External payment processing")
287
+
288
+ Rel(user, orders, "Places orders", "REST/HTTPS")
289
+
290
+ Rel(orders, temporal, "Starts", "PlaceOrderWorkflow")
291
+ Rel(temporal, payments, "Invokes", "ProcessOrderPayment")
292
+ Rel(temporal, orders, "Invokes", "ConfirmOrder")
293
+
294
+ Rel(orders, db, "Reads/Writes", "JDBC")
295
+ Rel(payments, db, "Reads/Writes", "JDBC")
296
+
297
+ Rel(payments, paymentGw, "Charges", "HTTPS")
298
+ ```
299
+
300
+ **Rules for Temporal Container diagram:**
301
+ - `Container(temporal, "Temporal Server", "Temporal", "Durable workflow orchestration")` — always inside the boundary
302
+ - Workflow arrows: `module → temporal` with "Starts" + workflow name
303
+ - Activity arrows: `temporal → module` with "Invokes" + activity name
304
+ - Direct arrows between modules are **forbidden** — all communication flows through Temporal
305
+ - `ports:` (external services) are direct arrows from module to `System_Ext()`
306
+ - No `ContainerQueue` — Temporal replaces the message broker
307
+
308
+ ---
309
+
310
+ ## Step 7 — Create domain.yaml per module
311
+
312
+ Read `references/temporal-domain-yaml-spec.md` for the complete specification.
313
+
314
+ For each module in `modules:`, generate `system/{module-name}.yaml` (**inside the `system/` directory**, e.g., `system/orders.yaml`, `system/payments.yaml`) with: aggregates, entities, valueObjects, enums (with transitions if applicable), events (with `notifies:` if applicable), activities, single-module workflows, endpoints, and ports (only for external services).
315
+
316
+ ### Endpoints in multi-aggregate modules
317
+
318
+ If the module has **2 or more aggregates** (e.g., `Product` + `Category`), the `endpoints:` section must use `basePath: ""` (empty string) and **absolute** paths per operation:
319
+
320
+ ```yaml
321
+ # Module with 2+ aggregates → empty basePath
322
+ endpoints:
323
+ basePath: ""
324
+ versions:
325
+ - version: v1
326
+ operations:
327
+ - useCase: CreateProduct
328
+ method: POST
329
+ path: /products
330
+ - useCase: CreateCategory
331
+ method: POST
332
+ path: /categories
333
+ ```
334
+
335
+ If the module has **a single aggregate**, use `basePath: /resource` with relative paths (e.g., `/`, `/{id}`).
336
+
337
+ **NEVER use `basePath: /`** (with slash) — it produces a trailing slash in `@RequestMapping`. Use `basePath: ""` (empty).
338
+
339
+ ### Key differences from broker-based domain.yaml
340
+
341
+ | Section | Broker-based | Temporal-based |
342
+ |---------|-------------|----------------|
343
+ | `events:` | `triggers:` / `lifecycle:` + `topic:` | `triggers:` / `lifecycle:` + `notifies:` (no topic) |
344
+ | `listeners:` | Present — Kafka consumers | **ABSENT** — Temporal replaces this |
345
+ | `readModels:` | Present — local projections | **ABSENT** — on-demand reads via activities |
346
+ | `ports:` | Internal + external HTTP calls | **Only external** services (non-Temporal) |
347
+ | `activities:` | Not present | **NEW** — module capabilities |
348
+ | `workflows:` | Not present | **NEW** — single-module internal flows |
349
+
350
+ ### Activities section in domain.yaml
351
+
352
+ Each module declares its capabilities as activities:
353
+
354
+ ```yaml
355
+ activities:
356
+ - name: GetCustomerById
357
+ type: light # light (<30s) | heavy (up to 2min)
358
+ description: "Gets a customer by ID"
359
+ input:
360
+ - name: customerId
361
+ type: String
362
+ output:
363
+ - name: customerId
364
+ type: String
365
+ - name: firstName
366
+ type: String
367
+ - name: email
368
+ type: String
369
+ timeout: 5s
370
+
371
+ - name: ReserveStock
372
+ type: light
373
+ description: "Reserves stock for an order"
374
+ input:
375
+ - name: orderId
376
+ type: String
377
+ - name: items
378
+ type: List<OrderItemDetail>
379
+ output:
380
+ - name: success
381
+ type: Boolean
382
+ externalTypes:
383
+ - name: OrderItemDetail
384
+ module: orders
385
+ timeout: 10s
386
+ compensation: ReleaseStock
387
+ ```
388
+
389
+ ### Workflows section in domain.yaml (single-module only)
390
+
391
+ ```yaml
392
+ workflows:
393
+ - name: ExpireOrderWorkflow
394
+ description: "Cancels order if payment not received within timeout"
395
+ trigger:
396
+ on: orderCreated
397
+ taskQueue: ORDER_WORKFLOW_QUEUE
398
+ steps:
399
+ - wait: paymentCompleted
400
+ timeout: 30m
401
+ - activity: CancelExpiredOrder
402
+ timeout: 5s
403
+ ```
404
+
405
+ ### Events with `notifies:`
406
+
407
+ ```yaml
408
+ events:
409
+ - name: OrderPlacedEvent
410
+ lifecycle: create
411
+ fields:
412
+ - name: orderId
413
+ type: String
414
+ notifies:
415
+ - workflow: PlaceOrderWorkflow # cross-module workflow in system.yaml
416
+
417
+ - name: CustomerUpdatedEvent
418
+ lifecycle: update
419
+ fields:
420
+ - name: customerId
421
+ type: String
422
+ # NO notifies → Domain Event internal (no cross-module effect)
423
+ ```
424
+
425
+ ---
426
+
427
+ ## Step 8 — Create technical specification per module
428
+
429
+ Read `references/temporal-module-spec.md` for the mandatory structure.
430
+
431
+ For each module, generate `system/{module-name}.md` (**inside the `system/` directory**, e.g., `system/orders.md`, `system/payments.md`) with: module role, invariants, state machine, interaction diagram, sequence diagram, use cases, endpoints, activities exposed, and workflows.
432
+
433
+ ### Key differences in module specs for Temporal
434
+
435
+ - **Activities Exposed** section replaces "Emitted Events" and "Ports"
436
+ - **Workflows Triggered** section describes what workflows each event triggers
437
+ - **Interaction diagrams** show workflow invocations instead of event flows
438
+ - **Sequence diagrams** show activity invocations through Temporal
439
+
440
+ ---
441
+
442
+ ## Anti-patterns to avoid
443
+
444
+ ### Do NOT create data-sync workflows
445
+
446
+ ```yaml
447
+ # ❌ DON'T — workflow that only syncs data
448
+ - name: CustomerUpdatedWorkflow
449
+ steps:
450
+ - activity: SyncCustomerReadModel
451
+
452
+ # ✅ DO — on-demand read in the workflow that needs the data
453
+ # PlaceOrderWorkflow → GetCustomerById → customers
454
+ ```
455
+
456
+ ### Do NOT make activities do cross-module lookups
457
+
458
+ ```yaml
459
+ # ❌ DON'T — activity internally queries another module's DB
460
+ activities:
461
+ - name: NotifyOrderPlaced
462
+ input: [orderId, customerId]
463
+ # Internally: fetch customer data → HIDDEN COUPLING
464
+
465
+ # ✅ DO — workflow assembles data and passes it
466
+ activities:
467
+ - name: NotifyOrderPlaced
468
+ input: [orderId, customerEmail, customerName, totalAmount]
469
+ ```
470
+
471
+ ### Do NOT put cross-module orchestration in domain.yaml
472
+
473
+ ```yaml
474
+ # ❌ DON'T — saga in module YAML
475
+ # orders.yaml
476
+ saga:
477
+ workflow: PlaceOrderWorkflow
478
+
479
+ # ✅ DO — cross-module orchestration in system.yaml
480
+ # The domain.yaml only declares the event with notifies:
481
+ ```
482
+
483
+ ### Do NOT use `notifies:` for events without cross-module effects
484
+
485
+ ```yaml
486
+ # ❌ DON'T
487
+ events:
488
+ - name: CustomerUpdatedEvent
489
+ notifies:
490
+ - workflow: CustomerUpdatedWorkflow # only syncs data
491
+
492
+ # ✅ DO — Domain Event internal
493
+ events:
494
+ - name: CustomerUpdatedEvent
495
+ # NO notifies
496
+ ```
497
+
498
+ ### Do NOT forget `compensation:` in saga activities
499
+
500
+ ```yaml
501
+ # ❌ DON'T — no compensation in saga
502
+ steps:
503
+ - activity: ReserveStock # what if payment fails?
504
+
505
+ # ✅ DO
506
+ steps:
507
+ - activity: ReserveStock
508
+ compensation: ReleaseStock
509
+ ```
510
+
511
+ ### Do NOT invoke activities directly from handlers or use cases
512
+
513
+ Activities are Temporal constructs — they can ONLY be invoked from within a workflow execution context. Handlers and use cases interact with their own module's repository and domain entities, and trigger workflows via Domain Events. They never call activity interfaces.
514
+
515
+ ```java
516
+ // ❌ DON'T — handler injecting an activity to get cross-module data
517
+ public class AddToCartCommandHandler {
518
+ private final ProductActivity productActivity; // ❌ WRONG
519
+
520
+ public void handle(AddToCartCommand cmd) {
521
+ // ❌ Activity invoked outside a workflow — will fail at runtime
522
+ var product = productActivity.GetProductById(cmd.productId());
523
+ cart.addItem(product.name(), product.price());
524
+ repository.save(cart);
525
+ }
526
+ }
527
+
528
+ // ✅ DO — handler persists + emits event → workflow orchestrates activities
529
+ public class AddToCartCommandHandler {
530
+ public void handle(AddToCartCommand cmd) {
531
+ cart.addItem(cmd.productId(), cmd.quantity());
532
+ repository.save(cart); // Domain Event triggers AddToCartWorkflow
533
+ }
534
+ }
535
+
536
+ // ✅ Workflow invokes the activity through Temporal
537
+ public class AddToCartWorkflowImpl implements AddToCartWorkflow {
538
+ private final ProductActivity productActivity; // ✅ Temporal stub
539
+
540
+ public void execute(String cartId, String productId) {
541
+ var product = productActivity.GetProductById(productId); // ✅ CORRECT
542
+ var enrichment = cartActivity.EnrichCartItem(cartId, product);
543
+ }
544
+ }
545
+ ```
546
+
547
+ **Rule:** If a handler needs data from another module, design a workflow that reads the data via an activity and then acts on it. The handler's job is to persist domain state and emit events that trigger workflows.
548
+
549
+ ---
550
+
551
+ ## Step 9 — Post-design artifacts
552
+
553
+ Immediately after completing Step 8, generate three final artifacts that contextualize the newly designed system.
554
+
555
+ ### Step 9a — Rewrite AGENTS.md (project-specific)
556
+
557
+ Rewrite the `AGENTS.md` file at the **project root** with content specific to the designed system.
558
+
559
+ **Process:**
560
+
561
+ 1. Read the current `AGENTS.md` as a base template
562
+ 2. Analyze `system/system.yaml` and all `system/{module}.yaml` to detect which features are used:
563
+ - Temporal orchestration (always true for this skill)
564
+ - `activities:` section with types (light/heavy, compensation)
565
+ - `workflows:` section (single-module internal workflows)
566
+ - Events with `notifies:` (cross-module workflow triggers)
567
+ - `ports:` (external services only — not internal HTTP)
568
+ - `hasSoftDelete` on any entity
569
+ - `audit.trackUser` on any entity
570
+ - Value Objects with `methods:`
571
+ - Enums with `transitions:` and `initialValue`
572
+ - Field flags: `readOnly`, `hidden`, `defaultValue`, `validations`, `reference`
573
+ 3. **Prune** sections about unused features:
574
+
575
+ | Condition | Section to remove |
576
+ |---|---|
577
+ | Temporal system (always) | Kafka/RabbitMQ messaging sections, `listeners:`, `readModels:` |
578
+ | No `ports:` for external services | Ports/Feign subsections |
579
+ | No `hasSoftDelete` | Soft delete section and checklist items |
580
+ | No `audit.trackUser` | UserContextFilter/UserContextHolder/AuditorAwareImpl infrastructure (keep basic audit if `audit.enabled`) |
581
+ | No VO `methods:` | "Value Objects with Methods" subsection |
582
+ | No enum `transitions:` | "Enums with Lifecycle" subsection |
583
+
584
+ 4. **Add Temporal-specific content** (always):
585
+ - Activities section: light/heavy types, compensation pattern, input/output
586
+ - Workflows section: cross-module (system.yaml) vs single-module (domain.yaml)
587
+ - `notifies:` pattern in events (replaces `topic:`)
588
+ - Activity as collaboration mechanism (replaces events/listeners)
589
+ 5. **Specialize** remaining content:
590
+ - Replace generic examples (`User`, `Order`) with actual project entities/modules
591
+ - Update `eva` command examples with real module names
592
+ - Update `domain.yaml` example with actual project structure
593
+ - Reduce checklist to only relevant items for this project
594
+ 6. Add a **project context header** at the top:
595
+
596
+ ```markdown
597
+ # AI Agent Guide — {System Name}
598
+
599
+ ## Project Overview
600
+ - **System:** {name} — {brief description from system.yaml}
601
+ - **Modules:** {list of modules with 1-line descriptions}
602
+ - **Orchestration:** Temporal ({namespace}, {target address})
603
+ - **Database:** {database type}
604
+ - **Java:** {javaVersion} / **Spring Boot:** {springBootVersion}
605
+ ```
606
+
607
+ 7. **Always keep** (universal): DDD principles, hexagonal architecture, mapper rules, DTO rules, data flow diagrams (Command write / Query read), testing patterns
608
+ 8. Write **everything in English**
609
+ 9. **Limit: ≤ 1000 lines** — prune aggressively, compress examples, avoid redundancy
610
+
611
+ ---
612
+
613
+ ### Step 9b — Create system/VALIDATION_FLOWS.md
614
+
615
+ Generate `system/VALIDATION_FLOWS.md` with technical validation flows for the system. All information is derived from `system.yaml` and the `{module}.yaml` files.
616
+
617
+ **Mandatory structure:**
618
+
619
+ ```markdown
620
+ # Validation Flows — {System Name}
621
+
622
+ ## Prerequisites
623
+ - Services: {required infrastructure — DB, Temporal Server, external services}
624
+ - Temporal: namespace={namespace}, target={address}
625
+ - Startup order: {if relevant}
626
+ - Base URLs: {per module if different}
627
+
628
+ ## 1. Module Validation
629
+
630
+ ### 1.1 {Module Name}
631
+
632
+ #### CRUD Operations
633
+ | # | Operation | Endpoint | Payload/Params | Expected Result | Validates |
634
+ |---|-----------|----------|----------------|-----------------|-----------||
635
+ | 1 | Create | POST /x | {key fields} | 201 + entity | {invariant} |
636
+ | 2 | Get by ID | GET /x/{id} | — | 200 + entity | — |
637
+ | 3 | List | GET /x | — | 200 + page | — |
638
+ | 4 | Update | PUT /x/{id} | {fields} | 200 + updated | — |
639
+ | 5 | Delete | DELETE /x/{id} | — | 204 | — |
640
+
641
+ #### State Transitions (if module has enum transitions)
642
+ | # | Transition | Endpoint | Precondition | Expected | Event / Workflow Triggered |
643
+ |---|-----------|----------|--------------|----------|----------------------------|
644
+ | 1 | DRAFT→PUBLISHED | PUT /x/{id}/publish | exists in DRAFT | 200, status=PUBLISHED | XPublishedEvent → PlaceXWorkflow |
645
+
646
+ #### Business Rules
647
+ | # | Rule | How to Trigger | Expected Error |
648
+ |---|------|----------------|----------------|
649
+
650
+ (repeat per module)
651
+
652
+ ## 2. Workflow Validation
653
+
654
+ ### 2.1 {WorkflowName}
655
+ **Trigger:** {event} from {module}
656
+ **Saga:** {yes/no}
657
+ **Task Queue:** {QUEUE_NAME}
658
+ **Steps:**
659
+ 1. Activity: {ActivityName} → {target module} — expected: {result}
660
+ 2. Activity: {ActivityName} → {target module} — expected: {result}
661
+ **Compensation (if saga fails at step N):**
662
+ - Step N-1: {CompensationActivity} reverses {what}
663
+ **Verify:**
664
+ - {expected final state in each affected module}
665
+
666
+ (repeat per cross-module workflow)
667
+
668
+ ## 3. On-Demand Read Validation (if read activities exist)
669
+ ### 3.1 {ReadActivityName}: {caller workflow} → {target module}
670
+ | Input | Expected Output | Error Case |
671
+ |---|---|---|
672
+ | valid ID | entity data returned | 404 → workflow handles gracefully |
673
+
674
+ ## 4. External Service Calls (if ports exist)
675
+ ### 4.1 {PortName}: {module} → {external service}
676
+ | Method | Expected | Fallback |
677
+ |---|---|---|
678
+
679
+ ## 5. Error & Edge Cases
680
+ | # | Scenario | Steps | Expected Error |
681
+ |---|----------|-------|----------------|
682
+ | 1 | Create with missing required field | POST /x without {field} | 400 + validation message |
683
+ | 2 | Invalid state transition | PUT /x/{id}/action when invalid state | 400/409 + business error |
684
+ | 3 | Saga compensation on failure | Trigger workflow, fail at step N | Previous steps compensated |
685
+ | 4 | Activity timeout | Simulate slow activity | Temporal retries per retryPolicy |
686
+ ```
687
+
688
+ **Rules:**
689
+ - Each flow must be concrete: real paths, real event names, real workflow/activity names from the project
690
+ - Include suggested JSON payloads where useful
691
+ - Omit entire sections if not applicable (e.g., no ports → omit section 4)
692
+ - Everything in English
693
+
694
+ ---
695
+
696
+ ### Step 9c — Create system/USER_FLOWS.md
697
+
698
+ Generate `system/USER_FLOWS.md` with end-to-end flows from the user’s perspective.
699
+
700
+ **Mandatory structure:**
701
+
702
+ ```markdown
703
+ # User Flows — {System Name}
704
+
705
+ ## Actors
706
+ | Actor | Description | Modules Interacted |
707
+ |-------|-------------|--------------------|
708
+ | {Actor 1} | {role description} | {module list} |
709
+
710
+ ## Flow 1: {Business Process Name}
711
+ **Actor:** {who}
712
+ **Goal:** {what they want to achieve}
713
+ **Preconditions:** {initial state}
714
+
715
+ ### Happy Path
716
+ | Step | User Action | System Response | Behind the Scenes |
717
+ |------|-------------|-----------------|-------------------|
718
+ | 1 | {does X} | {sees Y} | {endpoint called, workflow started, activities invoked} |
719
+ | 2 | {does Z} | {sees W} | {activity completes, state changes} |
720
+
721
+ ### Alternative Paths
722
+ | Condition | At Step | What Happens |
723
+ |-----------|---------|---------- ---|
724
+ | {condition} | {N} | {alternative outcome} |
725
+
726
+ ### Error Paths
727
+ | Error | At Step | User Sees |
728
+ |-------|---------|----------|
729
+ | {error} | {N} | {error message/behavior, saga rollback visible effect} |
730
+
731
+ (repeat per major business flow)
732
+ ```
733
+
734
+ **Rules:**
735
+ - Derive actors from who consumes the `exposes[]` endpoints (same source as C4 Context `Person()` nodes)
736
+ - Each flow is a **complete business scenario** crossing modules where applicable
737
+ - "Behind the Scenes" column references **workflows and activities** instead of events and topics
738
+ - Saga compensation reflected as **user-observable rollback behavior** (e.g., "Payment reversed, stock released")
739
+ - Include at least one flow per major use case path through the system
740
+ - Focus on user-observable behavior, not internal implementation
741
+ - Everything in English
742
+
743
+ ---
744
+
745
+ ## Refinement cycle
746
+
747
+ After delivering v1, if the user requests adjustments:
748
+ - Apply the **minimum change** necessary
749
+ - Revalidate the checklist from Step 4
750
+ - Update `system.md`, `c4-context.mmd`, `c4-container.mmd`, `{module}.yaml` and `{module}.md` affected
751
+ - Update `AGENTS.md`, `VALIDATION_FLOWS.md` and `USER_FLOWS.md` if affected by the change
752
+ - Deliver only the explained diff