eva4j 1.0.14 → 1.0.16

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 (139) hide show
  1. package/.agents/skills/skill-creator/LICENSE.txt +202 -0
  2. package/.agents/skills/skill-creator/SKILL.md +485 -0
  3. package/.agents/skills/skill-creator/agents/analyzer.md +274 -0
  4. package/.agents/skills/skill-creator/agents/comparator.md +202 -0
  5. package/.agents/skills/skill-creator/agents/grader.md +223 -0
  6. package/.agents/skills/skill-creator/assets/eval_review.html +146 -0
  7. package/.agents/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  8. package/.agents/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  9. package/.agents/skills/skill-creator/references/schemas.md +430 -0
  10. package/.agents/skills/skill-creator/scripts/__init__.py +0 -0
  11. package/.agents/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  12. package/.agents/skills/skill-creator/scripts/generate_report.py +326 -0
  13. package/.agents/skills/skill-creator/scripts/improve_description.py +247 -0
  14. package/.agents/skills/skill-creator/scripts/package_skill.py +136 -0
  15. package/.agents/skills/skill-creator/scripts/quick_validate.py +103 -0
  16. package/.agents/skills/skill-creator/scripts/run_eval.py +310 -0
  17. package/.agents/skills/skill-creator/scripts/run_loop.py +328 -0
  18. package/.agents/skills/skill-creator/scripts/utils.py +47 -0
  19. package/AGENTS.md +268 -6
  20. package/COMMAND_EVALUATION.md +15 -16
  21. package/DOMAIN_YAML_GUIDE.md +430 -14
  22. package/FUTURE_FEATURES.md +1627 -1168
  23. package/README.md +461 -13
  24. package/bin/eva4j.js +32 -14
  25. package/config/defaults.json +1 -0
  26. package/docs/commands/EVALUATE_SYSTEM.md +746 -261
  27. package/docs/commands/EXPORT_DIAGRAM.md +153 -0
  28. package/docs/commands/GENERATE_ENTITIES.md +599 -6
  29. package/docs/commands/INDEX.md +7 -0
  30. package/examples/domain-events.yaml +166 -20
  31. package/examples/domain-listeners.yaml +212 -0
  32. package/examples/domain-one-to-many.yaml +1 -0
  33. package/examples/domain-one-to-one.yaml +1 -0
  34. package/examples/domain-ports.yaml +414 -0
  35. package/examples/domain-soft-delete.yaml +47 -44
  36. package/examples/system/notification.yaml +147 -0
  37. package/examples/system/product.yaml +185 -0
  38. package/examples/system/system.yaml +112 -0
  39. package/examples/system-report.html +971 -0
  40. package/examples/system.yaml +46 -3
  41. package/package.json +2 -1
  42. package/src/agents/design-reviewer.agent.md +163 -0
  43. package/src/commands/build.js +714 -0
  44. package/src/commands/create.js +1 -0
  45. package/src/commands/detach.js +149 -108
  46. package/src/commands/evaluate-system.js +234 -8
  47. package/src/commands/export-diagram.js +522 -0
  48. package/src/commands/generate-entities.js +685 -66
  49. package/src/commands/generate-http-exchange.js +2 -0
  50. package/src/commands/generate-kafka-event.js +43 -10
  51. package/src/generators/base-generator.js +18 -6
  52. package/src/generators/postman-generator.js +188 -0
  53. package/src/generators/shared-generator.js +12 -2
  54. package/src/skills/build-system-yaml/SKILL.md +323 -0
  55. package/src/skills/build-system-yaml/references/domain-yaml-spec.md +410 -0
  56. package/src/skills/build-system-yaml/references/module-spec.md +367 -0
  57. package/src/skills/build-system-yaml/references/system-yaml-spec.md +178 -0
  58. package/src/utils/config-manager.js +54 -0
  59. package/src/utils/context-builder.js +1 -0
  60. package/src/utils/domain-diagram.js +192 -0
  61. package/src/utils/domain-validator.js +1020 -0
  62. package/src/utils/fake-data.js +376 -0
  63. package/src/utils/system-validator.js +319 -199
  64. package/src/utils/yaml-to-entity.js +272 -7
  65. package/templates/aggregate/AggregateMapper.java.ejs +3 -2
  66. package/templates/aggregate/AggregateRepository.java.ejs +3 -2
  67. package/templates/aggregate/AggregateRepositoryImpl.java.ejs +6 -5
  68. package/templates/aggregate/AggregateRoot.java.ejs +60 -2
  69. package/templates/aggregate/DomainEventHandler.java.ejs +4 -1
  70. package/templates/aggregate/DomainEventRecord.java.ejs +24 -8
  71. package/templates/aggregate/DomainEventSnapshot.java.ejs +46 -0
  72. package/templates/aggregate/JpaAggregateRoot.java.ejs +6 -0
  73. package/templates/base/docker/Dockerfile.ejs +21 -0
  74. package/templates/base/gradle/build.gradle.ejs +3 -2
  75. package/templates/base/root/AGENTS.md.ejs +306 -45
  76. package/templates/crud/ApplicationMapper.java.ejs +4 -0
  77. package/templates/crud/Controller.java.ejs +4 -4
  78. package/templates/crud/CreateCommand.java.ejs +4 -0
  79. package/templates/crud/CreateCommandHandler.java.ejs +3 -6
  80. package/templates/crud/CreateItemDto.java.ejs +4 -0
  81. package/templates/crud/CreateValueObjectDto.java.ejs +4 -0
  82. package/templates/crud/DeleteCommandHandler.java.ejs +12 -6
  83. package/templates/crud/EndpointsController.java.ejs +6 -6
  84. package/templates/crud/FindByQuery.java.ejs +1 -1
  85. package/templates/crud/FindByQueryHandler.java.ejs +3 -9
  86. package/templates/crud/GetQueryHandler.java.ejs +2 -5
  87. package/templates/crud/ListQuery.java.ejs +1 -1
  88. package/templates/crud/ListQueryHandler.java.ejs +8 -14
  89. package/templates/crud/ScaffoldCommandHandler.java.ejs +2 -4
  90. package/templates/crud/ScaffoldQuery.java.ejs +3 -2
  91. package/templates/crud/ScaffoldQueryHandler.java.ejs +5 -6
  92. package/templates/crud/SubEntityAddCommand.java.ejs +4 -0
  93. package/templates/crud/SubEntityAddCommandHandler.java.ejs +2 -6
  94. package/templates/crud/SubEntityRemoveCommandHandler.java.ejs +2 -7
  95. package/templates/crud/TransitionCommandHandler.java.ejs +2 -6
  96. package/templates/crud/UpdateCommand.java.ejs +4 -0
  97. package/templates/crud/UpdateCommandHandler.java.ejs +2 -5
  98. package/templates/evaluate/report.html.ejs +394 -2
  99. package/templates/kafka-event/DomainEventHandlerMethod.ejs +3 -1
  100. package/templates/kafka-event/Event.java.ejs +9 -0
  101. package/templates/kafka-listener/KafkaController.java.ejs +1 -1
  102. package/templates/kafka-listener/KafkaListenerClass.java.ejs +1 -1
  103. package/templates/kafka-listener/ListenerClass.java.ejs +65 -0
  104. package/templates/kafka-listener/ListenerCommand.java.ejs +31 -0
  105. package/templates/kafka-listener/ListenerCommandHandler.java.ejs +25 -0
  106. package/templates/kafka-listener/ListenerIntegrationEvent.java.ejs +37 -0
  107. package/templates/kafka-listener/ListenerMethod.java.ejs +1 -1
  108. package/templates/kafka-listener/ListenerNestedType.java.ejs +28 -0
  109. package/templates/mock/MockEvent.java.ejs +10 -0
  110. package/templates/mock/MockMessageBrokerImpl.java.ejs +35 -0
  111. package/templates/mock/MockMessageBrokerImplMethod.java.ejs +6 -0
  112. package/templates/mock/SpringEventListener.java.ejs +61 -0
  113. package/templates/ports/PortDomainModel.java.ejs +35 -0
  114. package/templates/ports/PortFeignAdapter.java.ejs +67 -0
  115. package/templates/ports/PortFeignClient.java.ejs +45 -0
  116. package/templates/ports/PortFeignConfig.java.ejs +24 -0
  117. package/templates/ports/PortInterface.java.ejs +45 -0
  118. package/templates/ports/PortNestedType.java.ejs +28 -0
  119. package/templates/ports/PortRequestDto.java.ejs +30 -0
  120. package/templates/ports/PortResponseDto.java.ejs +28 -0
  121. package/templates/postman/Collection.json.ejs +1 -1
  122. package/templates/postman/UnifiedCollection.json.ejs +185 -0
  123. package/templates/shared/annotations/LogAfter.java.ejs +2 -0
  124. package/templates/shared/annotations/LogBefore.java.ejs +2 -0
  125. package/templates/shared/annotations/LogExceptions.java.ejs +2 -0
  126. package/templates/shared/annotations/LogLevel.java.ejs +8 -0
  127. package/templates/shared/annotations/LogTimer.java.ejs +1 -0
  128. package/templates/shared/annotations/Loggable.java.ejs +17 -0
  129. package/templates/shared/configurations/eventPublicationConfig/EventPublicationSchemaConfig.java.ejs +109 -0
  130. package/templates/shared/configurations/loggerConfig/HandlerLogs.java.ejs +120 -32
  131. package/templates/shared/errorMessage/ErrorResponse.java.ejs +23 -0
  132. package/templates/shared/handlerException/HandlerExceptions.java.ejs +99 -79
  133. package/src/commands/generate-system.js +0 -243
  134. package/templates/base/root/skill-build-domain-yaml-references-generate-entities.md.ejs +0 -1103
  135. package/templates/base/root/skill-build-domain-yaml.ejs +0 -292
  136. package/templates/base/root/skill-build-system-yaml.ejs +0 -252
  137. package/templates/shared/errorMessage/ErrorMessage.java.ejs +0 -5
  138. package/templates/shared/errorMessage/FullErrorMessage.java.ejs +0 -9
  139. package/templates/shared/errorMessage/ShortErrorMessage.java.ejs +0 -6
@@ -0,0 +1,410 @@
1
+ # domain.yaml por módulo — Especificación completa
2
+
3
+ Referencia técnica para construir `system/{module}.yaml` — el modelo de dominio de cada módulo. Este archivo es el input para `eva g entities <module>`.
4
+
5
+ ---
6
+
7
+ ## Rol de experto por módulo
8
+
9
+ Al construir cada `system/{module}.yaml`, activa el rol de experto en el dominio específico:
10
+
11
+ - **`orders`** → ciclos de vida, estados, invariantes, relaciones con items, totales calculados
12
+ - **`payments`** → métodos de pago, reintentos, estados terminales, doble cobro
13
+ - **`inventory`** → stock disponible vs. reservado, movimientos, reposición
14
+ - **`notifications`** → canales, plantillas, idempotencia, reintentos
15
+
16
+ Propón campos necesarios no mencionados, Value Objects expresivos, invariantes implícitas, transiciones de estado realistas. Si necesitas reglas de negocio específicas de la empresa, pregunta.
17
+
18
+ ---
19
+
20
+ ## Restricciones absolutas
21
+
22
+ 1. ❌ **No `@ManyToOne`/`@OneToMany` entre agregados** — referencias cross-aggregate son IDs con `reference:`
23
+ 2. ❌ **No campos de auditoría en `fields:`** (`createdAt`, `updatedAt`, `createdBy`, `updatedBy`) — `audit.enabled: true` los genera
24
+ 3. ❌ **No `defaultValue` en campos no `readOnly`**
25
+ 4. ❌ **No `transitions` sin `initialValue`** en el enum
26
+ 5. ❌ **No inventar módulos en `reference.module`** — solo los de `system/system.yaml`
27
+ 6. ❌ **No duplicar en `endpoints:`** lo de `system.yaml → exposes:`
28
+ 7. ❌ **`endpoints:` NUNCA es lista plana** — siempre `{ basePath, versions: [{ version, operations }] }`
29
+ 8. ❌ **No inventar eventos** — deben coincidir con `integrations.async[]` donde `producer` es este módulo
30
+ 9. ❌ **No inventar listeners** — deben coincidir con `integrations.async[].consumers[]` donde `module` es este módulo
31
+ 10. ❌ **No inventar ports** — deben coincidir con `integrations.sync[]` donde `caller` es este módulo
32
+ 11. ❌ **Todo en inglés**
33
+ 12. ❌ **No transiciones sin evidencia de activación** — toda transición activada por `ports:` o scheduler necesita un domain event con `triggers`
34
+ 13. ❌ **No reutilizar `service:` en `ports[]` entre módulos** — nombres propios del bounded context
35
+
36
+ ---
37
+
38
+ ## Inferencia desde system.yaml
39
+
40
+ | Fuente en system.yaml | Destino en domain.yaml |
41
+ |---|---|
42
+ | `modules[x].exposes[]` | `endpoints:` con `basePath` + `versions[].operations[]` |
43
+ | `integrations.async[]` donde `producer = módulo` | `events:` |
44
+ | `integrations.async[].consumers[]` donde `module = módulo` | `listeners:` (con `useCase`) |
45
+ | `integrations.sync[]` donde `caller = módulo` | `ports:` (con `service`, `http`) |
46
+
47
+ ### Formato correcto de endpoints
48
+
49
+ ```yaml
50
+ # ❌ NUNCA — lista plana (el generador la ignora)
51
+ endpoints:
52
+ - method: POST
53
+ path: /orders
54
+ useCase: CreateOrder
55
+
56
+ # ✅ SIEMPRE — objeto con basePath + versions
57
+ endpoints:
58
+ basePath: /orders
59
+ versions:
60
+ - version: v1
61
+ operations:
62
+ - useCase: CreateOrder
63
+ method: POST
64
+ path: /
65
+ - useCase: GetOrder
66
+ method: GET
67
+ path: /{id}
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Estructura completa del module.yaml
73
+
74
+ ```yaml
75
+ aggregates:
76
+ - name: Order # PascalCase
77
+ entities:
78
+ - name: order # camelCase — entidad raíz
79
+ isRoot: true
80
+ tableName: orders # snake_case
81
+ hasSoftDelete: false
82
+ audit:
83
+ enabled: true # adds createdAt, updatedAt
84
+ trackUser: false # adds createdBy, updatedBy
85
+ fields:
86
+ - name: id
87
+ type: String
88
+ - name: orderNumber
89
+ type: String
90
+ validations:
91
+ - type: NotBlank
92
+ message: "Order number is required"
93
+ - name: totalAmount
94
+ type: BigDecimal
95
+ readOnly: true
96
+ defaultValue: "0.00"
97
+ - name: status
98
+ type: OrderStatus
99
+ readOnly: true
100
+ - name: processingToken
101
+ type: String
102
+ hidden: true
103
+ - name: customerId
104
+ type: String
105
+ reference:
106
+ aggregate: Customer
107
+ module: customers
108
+ relationships:
109
+ - type: OneToMany
110
+ target: OrderItem
111
+ mappedBy: order
112
+ cascade: [PERSIST, MERGE, REMOVE]
113
+ fetch: LAZY
114
+
115
+ - name: orderItem # entidad secundaria
116
+ tableName: order_items
117
+ fields:
118
+ - name: id
119
+ type: String
120
+ - name: productId
121
+ type: String
122
+ - name: quantity
123
+ type: Integer
124
+ validations:
125
+ - type: Min
126
+ value: 1
127
+ - name: unitPrice
128
+ type: BigDecimal
129
+
130
+ valueObjects:
131
+ - name: ShippingAddress
132
+ fields:
133
+ - name: street
134
+ type: String
135
+ - name: city
136
+ type: String
137
+ - name: zipCode
138
+ type: String
139
+ methods:
140
+ - name: format
141
+ returnType: String
142
+ parameters: []
143
+ body: "return street + \", \" + city + \" \" + zipCode;"
144
+
145
+ enums:
146
+ - name: OrderStatus
147
+ initialValue: PENDING
148
+ transitions:
149
+ - from: PENDING
150
+ to: CONFIRMED
151
+ method: confirm
152
+ - from: CONFIRMED
153
+ to: SHIPPED
154
+ method: ship
155
+ - from: [PENDING, CONFIRMED]
156
+ to: CANCELLED
157
+ method: cancel
158
+ guard: "this.status == OrderStatus.DELIVERED"
159
+ values: [PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED]
160
+
161
+ events:
162
+ - name: OrderPlacedEvent
163
+ topic: ORDER_PLACED
164
+ triggers:
165
+ - confirm
166
+ fields:
167
+ - name: customerId
168
+ type: String
169
+ - name: confirmedAt
170
+ type: LocalDateTime
171
+ - name: OrderCancelledEvent
172
+ topic: ORDER_CANCELLED
173
+ triggers:
174
+ - cancel
175
+ fields:
176
+ - name: reason
177
+ type: String
178
+
179
+ endpoints:
180
+ basePath: /orders
181
+ versions:
182
+ - version: v1
183
+ operations:
184
+ - useCase: GetOrder
185
+ method: GET
186
+ path: /{id}
187
+ - useCase: FindAllOrders
188
+ method: GET
189
+ path: /
190
+ - useCase: CreateOrder
191
+ method: POST
192
+ path: /
193
+ - useCase: ConfirmOrder
194
+ method: PUT
195
+ path: /{id}/confirm
196
+
197
+ listeners:
198
+ - event: PaymentApprovedEvent
199
+ producer: payments
200
+ topic: PAYMENT_APPROVED
201
+ useCase: ConfirmOrder
202
+ fields:
203
+ - name: orderId
204
+ type: String
205
+ - name: approvedAt
206
+ type: LocalDateTime
207
+ - name: paymentDetails
208
+ type: PaymentDetails
209
+ nestedTypes:
210
+ - name: paymentDetails
211
+ fields:
212
+ - name: paymentId
213
+ type: String
214
+ - name: amount
215
+ type: BigDecimal
216
+
217
+ ports:
218
+ - name: findCustomerById
219
+ service: OrderCustomerService
220
+ target: customers
221
+ baseUrl: http://localhost:8080
222
+ http: GET /customers/{id}
223
+ fields:
224
+ - name: id
225
+ type: String
226
+ - name: email
227
+ type: String
228
+ ```
229
+
230
+ ---
231
+
232
+ ## Visibilidad de campos
233
+
234
+ | Configuración | Business constructor | CreateDto | ResponseDto |
235
+ |---|---|---|---|
236
+ | Normal | ✅ | ✅ | ✅ |
237
+ | `readOnly: true` | ❌ | ❌ | ✅ |
238
+ | `readOnly` + `defaultValue` | ⚡ asignado con default | ❌ | ✅ |
239
+ | `hidden: true` | ✅ | ✅ | ❌ |
240
+ | Ambos flags | ❌ | ❌ | ❌ |
241
+
242
+ ---
243
+
244
+ ## Tipos de datos soportados
245
+
246
+ | YAML | Java |
247
+ |---|---|
248
+ | `String` | String |
249
+ | `Integer` | Integer |
250
+ | `Long` | Long |
251
+ | `BigDecimal` | BigDecimal |
252
+ | `Boolean` | Boolean |
253
+ | `LocalDate` | LocalDate |
254
+ | `LocalDateTime` | LocalDateTime |
255
+ | `LocalTime` | LocalTime |
256
+ | `Instant` | Instant |
257
+ | `UUID` | UUID |
258
+
259
+ ---
260
+
261
+ ## Relaciones
262
+
263
+ - ✅ `OneToMany`/`OneToOne` entre entidades del **mismo agregado** → declarar solo en raíz
264
+ - ✅ El generador infiere el lado inverso (`ManyToOne`) — **no declararlo en la secundaria**
265
+ - ✅ Referencia cross-aggregate → `reference:` en campo ID, nunca `relationships:`
266
+ - `mappedBy` debe coincidir con el nombre del campo inverso
267
+
268
+ ---
269
+
270
+ ## Validaciones JSR-303
271
+
272
+ Declarar en `fields[].validations` — se aplican **únicamente** en Command y CreateDto.
273
+
274
+ ```yaml
275
+ validations:
276
+ - type: NotBlank
277
+ message: "Required"
278
+ - type: Email
279
+ message: "Invalid email"
280
+ - type: Size
281
+ min: 3
282
+ max: 50
283
+ - type: Min
284
+ value: 1
285
+ - type: Positive
286
+ ```
287
+
288
+ Anotaciones: `NotNull`, `NotBlank`, `NotEmpty`, `Email`, `Size`, `Min`, `Max`, `Pattern`, `Digits`, `Positive`, `PositiveOrZero`, `Negative`, `Past`, `Future`, `AssertTrue`, `AssertFalse`.
289
+
290
+ ---
291
+
292
+ ## Proyecciones locales (read models)
293
+
294
+ Agregados sincronizados por listeners Kafka. Señales:
295
+ - Campos coinciden con `listeners[].fields`
296
+ - useCase: `Register*InLocalCatalog`, `Sync*`, `Update*FromEvent`
297
+ - Sin endpoints de escritura
298
+ - Existe para evitar llamadas síncronas en tiempo real
299
+
300
+ **Auditoría:** `audit.enabled: true`, `trackUser: false` (cambios vienen de eventos, no de usuarios).
301
+
302
+ ```yaml
303
+ - name: BikeCatalog
304
+ entities:
305
+ - name: bikeCatalogEntry
306
+ isRoot: true
307
+ tableName: bike_catalog_entries
308
+ audit:
309
+ enabled: true
310
+ trackUser: false
311
+ fields:
312
+ - name: id
313
+ type: String
314
+ - name: isAvailable
315
+ type: Boolean
316
+ readOnly: true
317
+ defaultValue: true
318
+ ```
319
+
320
+ ---
321
+
322
+ ## Clasificación de campos readOnly
323
+
324
+ Antes de declarar `events:`, clasifica cada campo `readOnly`:
325
+
326
+ | Categoría | Cuándo se asigna | Debe aparecer en... |
327
+ |---|---|---|
328
+ | Constante del sistema | Constructor con `defaultValue` | Ningún evento |
329
+ | Estado de máquina | Cada transición (enum) | Ningún campo explícito |
330
+ | Timestamp de transición | Una transición específica | El evento de **esa** transición |
331
+ | Dato calculado | Al ejecutar transición | El evento de esa transición |
332
+ | Acumulador | Múltiples operaciones | Eventos de cada operación |
333
+
334
+ **Protocolo para cada campo `readOnly` sin `defaultValue` y sin enum con `transitions`:**
335
+ 1. ¿En qué transición se asigna?
336
+ 2. ¿Esa transición tiene evento con triggers? → Sí: agregar al `fields[]`; No: crear evento + triggers
337
+ 3. Si se asigna en múltiples transiciones: incluir en el evento principal
338
+
339
+ > Transición que asigna campos `readOnly` sin evento asociado = **brecha de diseño**.
340
+
341
+ ---
342
+
343
+ ## Análisis de activación de transiciones
344
+
345
+ Para cada método en `transitions[]`, clasificar:
346
+
347
+ | Quién activa | Mecanismo correcto |
348
+ |---|---|
349
+ | Endpoint HTTP | `endpoints:` con useCase semántico |
350
+ | Listener Kafka | `listeners:` con useCase semántico |
351
+ | Respuesta exitosa de port | Domain event + `triggers: [método]` |
352
+ | Respuesta error de port | Domain event + `triggers: [método]` |
353
+ | Scheduler / proceso interno | Domain event + `triggers: [método]` |
354
+
355
+ **Patrón port con dos ramas:**
356
+ ```yaml
357
+ events:
358
+ - name: NotificationSentEvent
359
+ triggers: [markAsSent]
360
+ fields:
361
+ - name: sentAt
362
+ type: LocalDateTime
363
+ - name: NotificationFailedEvent
364
+ triggers: [markAsFailed]
365
+ fields: []
366
+ ```
367
+
368
+ ---
369
+
370
+ ## Trazabilidad de enums *Type
371
+
372
+ Enums con nombre `*Type` representan clasificaciones. Cada valor debe ser trazable a:
373
+
374
+ | Origen | Traza semántica |
375
+ |---|---|
376
+ | Listener (nombre evento) | Tokens del nombre del evento |
377
+ | Listener (nombre campo) | Tokens del campo |
378
+ | Endpoint (useCase) | Tokens del useCase |
379
+ | Domain event (nombre) | Tokens del evento |
380
+
381
+ Si un valor no es trazable → falta un endpoint o listener en el diseño.
382
+
383
+ ---
384
+
385
+ ## Checklist del domain.yaml por módulo
386
+
387
+ - [ ] Campo `id` en todas las entidades
388
+ - [ ] Solo una entidad `isRoot: true` por agregado
389
+ - [ ] Relaciones solo en raíz; inverso NO declarado
390
+ - [ ] Campos de auditoría NO en `fields:`
391
+ - [ ] `readOnly` con `defaultValue` si hay valor inicial
392
+ - [ ] Enums con lifecycle tienen `initialValue` + `transitions`
393
+ - [ ] Value Objects sin `id`
394
+ - [ ] Referencias cross-aggregate con `reference:`, no `relationships:`
395
+ - [ ] `events[].name` consistente con `integrations.async[]`
396
+ - [ ] `events[].topic` explícito, coincide con `integrations.async[].topic`
397
+ - [ ] `events[].triggers[]` referencia métodos existentes en `transitions[].method`
398
+ - [ ] `{entityName}Id` en `events[].fields` cuando cruza módulos via Kafka
399
+ - [ ] `endpoints:` con estructura `{ basePath, versions }` — no lista plana
400
+ - [ ] `endpoints[].path` relativos al basePath
401
+ - [ ] `listeners[]` para todos los eventos donde este módulo es consumidor
402
+ - [ ] `listeners[].useCase` coincide con `consumers[].useCase`
403
+ - [ ] `listeners[].topic` bare SCREAMING_SNAKE_CASE (sin topicPrefix)
404
+ - [ ] `ports[]` para todas las entradas sync donde `caller = este módulo`
405
+ - [ ] `ports[].baseUrl` solo en primera entrada de cada `service:`
406
+ - [ ] `nestedTypes[]` para campos de tipo objeto en listeners/ports
407
+ - [ ] Transiciones por `ports:` tienen domain event con `triggers`
408
+ - [ ] Cada enum `*Type` valor trazable a listener/endpoint/event
409
+ - [ ] Proyecciones: `audit.enabled: true`, `trackUser: false`
410
+ - [ ] Todo en inglés