eva4j 1.0.13 → 1.0.14

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 (44) hide show
  1. package/AGENTS.md +51 -9
  2. package/DOMAIN_YAML_GUIDE.md +150 -0
  3. package/bin/eva4j.js +31 -1
  4. package/design-system.md +797 -0
  5. package/docs/commands/EVALUATE_SYSTEM.md +542 -0
  6. package/docs/commands/GENERATE_ENTITIES.md +196 -0
  7. package/docs/commands/INDEX.md +10 -1
  8. package/examples/domain-endpoints-relations.yaml +353 -0
  9. package/examples/domain-endpoints-versioned.yaml +144 -0
  10. package/examples/domain-endpoints.yaml +135 -0
  11. package/examples/system.yaml +289 -0
  12. package/package.json +1 -1
  13. package/src/commands/create.js +6 -3
  14. package/src/commands/evaluate-system.js +384 -0
  15. package/src/commands/generate-entities.js +677 -14
  16. package/src/commands/generate-kafka-event.js +59 -5
  17. package/src/commands/generate-system.js +243 -0
  18. package/src/generators/base-generator.js +9 -1
  19. package/src/utils/naming.js +3 -2
  20. package/src/utils/system-validator.js +314 -0
  21. package/src/utils/yaml-to-entity.js +31 -2
  22. package/templates/aggregate/AggregateRepository.java.ejs +5 -0
  23. package/templates/aggregate/AggregateRepositoryImpl.java.ejs +9 -0
  24. package/templates/aggregate/DomainEventHandler.java.ejs +24 -20
  25. package/templates/aggregate/JpaRepository.java.ejs +5 -0
  26. package/templates/base/root/skill-build-domain-yaml-references-generate-entities.md.ejs +1103 -0
  27. package/templates/base/root/skill-build-domain-yaml.ejs +292 -0
  28. package/templates/base/root/skill-build-system-yaml.ejs +252 -0
  29. package/templates/base/root/system.yaml.ejs +97 -0
  30. package/templates/crud/EndpointsController.java.ejs +178 -0
  31. package/templates/crud/FindByQuery.java.ejs +17 -0
  32. package/templates/crud/FindByQueryHandler.java.ejs +57 -0
  33. package/templates/crud/ScaffoldCommand.java.ejs +12 -0
  34. package/templates/crud/ScaffoldCommandHandler.java.ejs +43 -0
  35. package/templates/crud/ScaffoldQuery.java.ejs +12 -0
  36. package/templates/crud/ScaffoldQueryHandler.java.ejs +40 -0
  37. package/templates/crud/SubEntityAddCommand.java.ejs +17 -0
  38. package/templates/crud/SubEntityAddCommandHandler.java.ejs +43 -0
  39. package/templates/crud/SubEntityRemoveCommand.java.ejs +9 -0
  40. package/templates/crud/SubEntityRemoveCommandHandler.java.ejs +42 -0
  41. package/templates/crud/TransitionCommand.java.ejs +9 -0
  42. package/templates/crud/TransitionCommandHandler.java.ejs +39 -0
  43. package/templates/evaluate/report.html.ejs +971 -0
  44. package/templates/kafka-event/Event.java.ejs +7 -0
@@ -0,0 +1,797 @@
1
+ # Design: System-First Development con `system.yaml`
2
+
3
+ > **Estado:** Propuesta en evolución
4
+ > **Versión:** 0.1.0
5
+ > **Fecha:** 2026-03-09
6
+
7
+ ---
8
+
9
+ ## 📋 Tabla de Contenidos
10
+
11
+ - [Visión](#visión)
12
+ - [Motivación](#motivación)
13
+ - [Principio Central](#principio-central)
14
+ - [Los Dos Artefactos](#los-dos-artefactos)
15
+ - [Anatomía de system.yaml](#anatomía-de-systemyaml)
16
+ - [Puertos Secundarios en domain.yaml](#puertos-secundarios-en-domainyaml)
17
+ - [Relación entre los Archivos](#relación-entre-los-archivos)
18
+ - [Flujo de Trabajo](#flujo-de-trabajo)
19
+ - [Comandos Nuevos](#comandos-nuevos)
20
+ - [Validaciones de system.yaml](#validaciones-de-systemyaml)
21
+ - [Aspectos Positivos del Enfoque](#aspectos-positivos-del-enfoque)
22
+ - [Colaboración con Agentes de IA](#colaboración-con-agentes-de-ia)
23
+ - [Cómo Construir el system.yaml con un Agente de IA](#cómo-construir-el-systemyaml-con-un-agente-de-ia)
24
+ - [Preguntas Abiertas](#preguntas-abiertas)
25
+
26
+ ---
27
+
28
+ ## Visión
29
+
30
+ > Construir sistemas backend robustos, con calidad de arquitectura enterprise, en una fracción del tiempo tradicional — iterando a la velocidad del negocio, no del código.
31
+
32
+ El objetivo final de este enfoque es habilitar un **ciclo de desarrollo acelerado por IA** donde:
33
+
34
+ - El equipo opera permanentemente en el nivel de **intención y negocio**, no en el nivel de código
35
+ - Los patrones arquitecturales correctos (hexagonal, DDD, CQRS) son **garantizados por el tooling**, no por la disciplina individual
36
+ - La IA amplifica la capacidad del equipo sin introducir inconsistencias
37
+ - Cada iteración es **quirúrgica y predecible**: cambiar una regla de negocio no requiere arqueología de código
38
+
39
+ ### El ciclo fundamental
40
+
41
+ ```
42
+ ┌─────────────────────────────────────────────────────────────┐
43
+ │ │
44
+ │ INTENCIÓN ESPECIFICACIÓN CÓDIGO │
45
+ │ (negocio) → (YAML) → (Java) │
46
+ │ ↑ │
47
+ │ │ revisión humana │
48
+ │ │ (diff de YAML, │
49
+ │ │ no de código) │
50
+ │ │
51
+ │ ◄────── iteración ────────────────── │
52
+ └─────────────────────────────────────────────────────────────┘
53
+ ```
54
+
55
+ ### Por qué este ciclo es cualitativamente diferente
56
+
57
+ | Enfoque | Velocidad | Consistencia | Revisión humana | Iteración |
58
+ |---|---|---|---|---|
59
+ | Tradicional | Lenta | Depende del equipo | Revisión de código (costosa) | Lenta |
60
+ | AI genera código directamente | Rápida | Baja — AI improvisa patrones | Difícil — código generado es opaco | Frágil |
61
+ | **System-First + eva4j + AI** | **Muy rápida** | **Alta — patrones garantizados por el generador** | **Fácil — se revisan YAMLs, no código** | **Rápida y segura** |
62
+
63
+ La clave es que **la IA y el humano colaboran en el nivel de especificación**, no en el nivel de código. El código Java es siempre un artefacto generado, determinista y consistente. Nadie necesita revisar si el mapper excluye los campos de auditoría — eva4j siempre lo hace bien.
64
+
65
+ ### La promesa concreta
66
+
67
+ Un sistema con 5-8 módulos, con comunicación asíncrona (Kafka) y síncrona (HTTP), con arquitectura hexagonal completa y cobertura de casos de uso principales:
68
+
69
+ - **Hoy (sin este enfoque):** semanas de desarrollo + semanas de revisión arquitectural
70
+ - **Con este enfoque:** días para la especificación colaborativa + horas para la generación y validación
71
+
72
+ La ganancia no viene de generar código más rápido — viene de **eliminar las decisiones repetitivas** (¿cómo nombro este mapper?, ¿dónde va esta clase?, ¿cómo estructuro este evento?) y dejar al equipo enfocado en las decisiones que realmente importan: qué reglas de negocio son correctas, qué contratos entre módulos tienen sentido, qué comportamientos del dominio necesitan transiciones de estado.
73
+
74
+ ---
75
+
76
+ ## Motivación
77
+
78
+ Hoy en eva4j el punto de entrada es el módulo: se crea uno a uno, se diseña su `domain.yaml` de forma aislada, y la comunicación entre módulos se configura de forma imperativa e interactiva mediante comandos como `eva g kafka-event`, `eva g kafka-listener` y `eva g http-exchange`.
79
+
80
+ Esto funciona bien para módulos individuales, pero deja una brecha: **no existe ningún artefacto que describa el sistema como un todo** — qué módulos existen, cómo se comunican, y cuáles son los contratos entre ellos.
81
+
82
+ La propuesta introduce un enfoque **System-First**: el diseño comienza definiendo la arquitectura del sistema en un único archivo de alto nivel (`system.yaml`), a partir del cual se hace bootstrap de toda la estructura.
83
+
84
+ ---
85
+
86
+ ## Principio Central
87
+
88
+ > El `system.yaml` describe **qué módulos existen y cómo se comunican**.
89
+ > El `domain.yaml` describe **qué es el dominio de cada módulo y qué puertos secundarios necesita**.
90
+
91
+ Los dos archivos son independientes y evolucionan en momentos distintos, pero tienen una relación de coherencia que eva4j puede validar.
92
+
93
+ ---
94
+
95
+ ## Los Dos Artefactos
96
+
97
+ | Archivo | Nivel | Responde a | Lo define |
98
+ |---|---|---|---|
99
+ | `system.yaml` | Sistema | ¿Qué módulos existen? ¿Qué fluye entre ellos? ¿Qué exponen? | Arquitecto / diseñador del sistema |
100
+ | `domain.yaml` | Módulo | ¿Qué entidades, reglas, eventos y puertos secundarios tiene este módulo? | Desarrollador del módulo |
101
+
102
+ ---
103
+
104
+ ## Anatomía de `system.yaml`
105
+
106
+ El archivo vive en la **raíz del proyecto** y tiene tres secciones:
107
+
108
+ ```yaml
109
+ # system.yaml
110
+
111
+ system:
112
+ name: ecommerce-platform
113
+ groupId: com.acme
114
+ javaVersion: 21
115
+ springBootVersion: 3.4.1
116
+ database: postgresql
117
+
118
+ messaging:
119
+ enabled: true
120
+ broker: kafka # kafka | rabbitmq | sns-sqs (solo kafka soportado actualmente)
121
+ kafka:
122
+ bootstrapServers: localhost:9092
123
+ defaultGroupId: ecommerce-platform
124
+ topicPrefix: ecommerce # opcional — prefixa todos los topics: ecommerce.ORDER_PLACED
125
+
126
+ modules:
127
+ - name: orders
128
+ description: "Gestión del ciclo de vida de pedidos"
129
+ exposes:
130
+ - method: GET
131
+ path: /orders/{id}
132
+ useCase: GetOrder
133
+ description: "Obtener detalle de un pedido"
134
+ - method: GET
135
+ path: /orders
136
+ useCase: FindAllOrders
137
+ description: "Listar pedidos con filtros y paginación"
138
+ - method: POST
139
+ path: /orders
140
+ useCase: CreateOrder
141
+ description: "Crear nuevo pedido"
142
+ - method: PUT
143
+ path: /orders/{id}/confirm
144
+ useCase: ConfirmOrder
145
+ description: "Confirmar pedido pendiente"
146
+ - method: PUT
147
+ path: /orders/{id}/cancel
148
+ useCase: CancelOrder
149
+ description: "Cancelar pedido (PENDING o CONFIRMED)"
150
+
151
+ - name: customers
152
+ description: "Registro y gestión de clientes"
153
+ exposes:
154
+ - method: GET
155
+ path: /customers/{id}
156
+ useCase: GetCustomer
157
+ description: "Obtener cliente por ID"
158
+ - method: GET
159
+ path: /customers
160
+ useCase: FindAllCustomers
161
+ description: "Listar clientes con filtros"
162
+ - method: POST
163
+ path: /customers
164
+ useCase: CreateCustomer
165
+ description: "Registrar nuevo cliente"
166
+ - method: PUT
167
+ path: /customers/{id}
168
+ useCase: UpdateCustomer
169
+ description: "Actualizar datos del cliente"
170
+
171
+ - name: payments
172
+ description: "Procesamiento de pagos"
173
+ exposes:
174
+ - method: POST
175
+ path: /payments
176
+ useCase: CreatePayment
177
+ description: "Iniciar procesamiento de pago"
178
+ - method: GET
179
+ path: /payments/{id}
180
+ useCase: GetPayment
181
+ description: "Consultar estado de un pago"
182
+ - method: POST
183
+ path: /payments/{id}/refund
184
+ useCase: RefundPayment
185
+ description: "Solicitar reembolso"
186
+
187
+ - name: notifications
188
+ description: "Envío de notificaciones"
189
+ # Sin endpoints REST — solo consume eventos
190
+
191
+ integrations:
192
+ async:
193
+ - event: OrderPlacedEvent
194
+ producer: orders
195
+ topic: ORDER_PLACED
196
+ consumers:
197
+ - module: payments
198
+ - module: notifications
199
+
200
+ - event: OrderCancelledEvent
201
+ producer: orders
202
+ topic: ORDER_CANCELLED
203
+ consumers:
204
+ - module: payments
205
+ - module: notifications
206
+
207
+ - event: PaymentProcessedEvent
208
+ producer: payments
209
+ topic: PAYMENT_PROCESSED
210
+ consumers:
211
+ - module: orders
212
+
213
+ sync:
214
+ - caller: orders
215
+ calls: customers
216
+ port: CustomerService
217
+ using:
218
+ - GET /customers/{id}
219
+
220
+ - caller: payments
221
+ calls: orders
222
+ port: OrderService
223
+ using:
224
+ - GET /orders/{id}
225
+ ```
226
+
227
+ ### Reglas del `system.yaml`
228
+
229
+ - Solo describe **qué existe** y **qué fluye** — no sabe nada de entidades, campos ni lógica de negocio
230
+ - Los endpoints en `exposes:` usan sintaxis objeto: `method`, `path`, `useCase` (obligatorio) y `description`
231
+ - El campo `useCase` permite a `eva generate system` pre-generar la sección `endpoints:` completa en `domain.yaml`
232
+ - Los endpoints en `exposes:` sirven también para validar los `calls.using:`
233
+ - Los módulos en `consumers:` deben existir en `modules:`
234
+ - Los eventos en `consumers:` deben tener exactamente un `producer:`
235
+
236
+ ### Sección `messaging`
237
+
238
+ | Campo | Obligatorio | Descripción |
239
+ |---|---|---|
240
+ | `enabled` | sí | `true` para activar soporte de mensajería asíncrona |
241
+ | `broker` | sí | Tipo de broker: `kafka` \| `rabbitmq` \| `sns-sqs` |
242
+ | `kafka.bootstrapServers` | cuando `broker: kafka` | Host(s) del broker Kafka |
243
+ | `kafka.defaultGroupId` | no | Consumer group ID base; cada módulo añade su sufijo |
244
+ | `kafka.topicPrefix` | no | Prefijo global para todos los topics del sistema |
245
+ | `rabbitmq.host` | cuando `broker: rabbitmq` | Host del broker RabbitMQ |
246
+ | `rabbitmq.port` | no | Puerto (default `5672`) |
247
+ | `rabbitmq.virtualHost` | no | VirtualHost (default `/`) |
248
+ | `rabbitmq.exchangeType` | no | Tipo de exchange: `topic` \| `direct` \| `fanout` (default `topic`) |
249
+ | `sns-sqs.region` | cuando `broker: sns-sqs` | Región AWS |
250
+ | `sns-sqs.accountId` | cuando `broker: sns-sqs` | AWS Account ID (para construir ARNs) |
251
+ | `sns-sqs.endpointOverride` | no | URL local para desarrollo (ej. LocalStack) |
252
+
253
+ > **Nota:** solo `kafka` está soportado actualmente. Los valores `rabbitmq` y `sns-sqs` están reservados para versiones futuras y generan un warning al ejecutar `eva system validate`.
254
+
255
+ #### Ejemplo con RabbitMQ
256
+
257
+ En brokers basados en colas, el modelo de comunicación cambia: en lugar de **topics** (Kafka) se usan **exchanges + queues** (RabbitMQ) o **topics SNS + colas SQS** (AWS). La integración sigue siendo declarativa — la diferencia está en los campos de configuración y en cómo se nombran los canales en `integrations.async`.
258
+
259
+ ```yaml
260
+ # system.yaml — broker RabbitMQ
261
+
262
+ system:
263
+ name: ecommerce-platform
264
+ groupId: com.acme
265
+ javaVersion: 21
266
+ springBootVersion: 3.4.1
267
+ database: postgresql
268
+
269
+ messaging:
270
+ enabled: true
271
+ broker: rabbitmq
272
+ rabbitmq:
273
+ host: localhost
274
+ port: 5672
275
+ virtualHost: /ecommerce
276
+ exchangeType: topic # un exchange por evento (topic exchange)
277
+
278
+ modules:
279
+ - name: orders
280
+ description: "Gestión del ciclo de vida de pedidos"
281
+ exposes:
282
+ - method: POST
283
+ path: /orders
284
+ useCase: CreateOrder
285
+ description: "Crear nuevo pedido"
286
+ - method: PUT
287
+ path: /orders/{id}/confirm
288
+ useCase: ConfirmOrder
289
+ description: "Confirmar pedido pendiente"
290
+ - method: PUT
291
+ path: /orders/{id}/cancel
292
+ useCase: CancelOrder
293
+ description: "Cancelar pedido"
294
+
295
+ - name: payments
296
+ description: "Procesamiento de pagos"
297
+ exposes:
298
+ - method: POST
299
+ path: /payments
300
+ useCase: CreatePayment
301
+ description: "Iniciar procesamiento de pago"
302
+
303
+ - name: notifications
304
+ description: "Envío de notificaciones"
305
+ # Sin endpoints REST — solo consume eventos
306
+
307
+ integrations:
308
+ async:
309
+ - event: OrderPlacedEvent
310
+ producer: orders
311
+ exchange: orders.events # exchange RabbitMQ
312
+ routingKey: order.placed # routing key del mensaje
313
+ consumers:
314
+ - module: payments
315
+ queue: payments.order.placed # cola dedicada por consumidor
316
+ - module: notifications
317
+ queue: notifications.order.placed
318
+
319
+ - event: PaymentProcessedEvent
320
+ producer: payments
321
+ exchange: payments.events
322
+ routingKey: payment.processed
323
+ consumers:
324
+ - module: orders
325
+ queue: orders.payment.processed
326
+
327
+ sync:
328
+ - caller: orders
329
+ calls: customers
330
+ port: CustomerService
331
+ using:
332
+ - GET /customers/{id}
333
+ ```
334
+
335
+ **Diferencias clave respecto a Kafka:**
336
+
337
+ | Concepto | Kafka | RabbitMQ |
338
+ |---|---|---|
339
+ | Canal de publicación | `topic` | `exchange` + `routingKey` |
340
+ | Canal de consumo | `topic` (compartido) | `queue` (exclusiva por consumidor) |
341
+ | Retención de mensajes | Log persistente (configurable) | Hasta que el consumidor los acepta |
342
+ | Fan-out | Un topic, múltiples consumer groups | Un exchange, múltiples queues binding |
343
+ | Replay | Sí (offset reset) | No (requiere DLQ + republicación) |
344
+
345
+ #### Ejemplo con SNS/SQS
346
+
347
+ ```yaml
348
+ # system.yaml — broker SNS/SQS (AWS)
349
+
350
+ messaging:
351
+ enabled: true
352
+ broker: sns-sqs
353
+ sns-sqs:
354
+ region: us-east-1
355
+ accountId: "123456789012"
356
+ endpointOverride: http://localhost:4566 # LocalStack para desarrollo local
357
+
358
+ integrations:
359
+ async:
360
+ - event: OrderPlacedEvent
361
+ producer: orders
362
+ topic: arn:aws:sns:us-east-1:123456789012:OrderPlaced # ARN del topic SNS
363
+ consumers:
364
+ - module: payments
365
+ queue: arn:aws:sqs:us-east-1:123456789012:payments-order-placed
366
+ - module: notifications
367
+ queue: arn:aws:sqs:us-east-1:123456789012:notifications-order-placed
368
+ ```
369
+
370
+ ---
371
+
372
+ ## Puertos Secundarios en `domain.yaml`
373
+
374
+ Los **puertos secundarios** son interfaces del dominio que representan dependencias hacia otros módulos. Al ser propiedad del dominio en arquitectura hexagonal, se declaran en `domain.yaml` bajo la sección `ports:`:
375
+
376
+ ```yaml
377
+ # orders/domain.yaml (fragmento)
378
+ aggregates:
379
+ - name: Order
380
+ entities: [...]
381
+ events:
382
+ - name: OrderPlacedEvent
383
+ fields:
384
+ - name: orderId
385
+ type: String
386
+ - name: customerId
387
+ type: String
388
+ kafka: true
389
+
390
+ ports: # puertos secundarios del módulo
391
+ - name: CustomerService
392
+ target: customers # módulo destino — validado contra system.yaml modules:
393
+ methods:
394
+ - name: findCustomerById
395
+ http: GET /customers/{id}
396
+ response:
397
+ - name: id
398
+ type: String
399
+ - name: fullName
400
+ type: String
401
+ - name: email
402
+ type: String
403
+ ```
404
+
405
+ ### Por qué `ports:` pertenece al dominio
406
+
407
+ En arquitectura hexagonal, la **interfaz del puerto secundario es propiedad del dominio** — el dominio define qué necesita, la infraestructura decide cómo obtenerlo (Feign, RestTemplate, stub). Declararlos en `domain.yaml` es semánticamente correcto y consistente con el precedente establecido por `reference:` en los campos.
408
+
409
+ ### Lo que `eva g entities` genera a partir de `ports:`
410
+
411
+ - **Interfaz del puerto** en `domain/repositories/` → `CustomerService.java`
412
+ - **DTO de respuesta local** en `application/dtos/` → `CustomerDto.java`
413
+ - **Implementación Feign** en `infrastructure/adapters/` → `CustomerServiceFeignAdapter.java`
414
+
415
+ ### Validación cruzada
416
+
417
+ > `ports[].target` en `domain.yaml` **debe existir** en `system.yaml → modules`.
418
+ > `eva system validate` detecta referencias rotas entre módulos.
419
+
420
+ ---
421
+
422
+ ## Relación entre los Archivos
423
+
424
+ ### Dependencias de datos
425
+
426
+ ```
427
+ system.yaml
428
+
429
+ └─── genera bootstrap de ──► domain.yaml (esqueleto con endpoints: pre-generado)
430
+
431
+
432
+ domain.yaml (events[] + ports[])
433
+
434
+ └─── genera código de ──────► eva g entities <module>
435
+ → entidades, repos, mappers, kafka events, feign clients
436
+ ```
437
+
438
+ ### Dependencia dura validable
439
+
440
+ > `ports[].target` en `domain.yaml` **debe existir** en `system.yaml → modules`.
441
+ > `eva system validate` detecta referencias rotas entre módulos.
442
+
443
+ ---
444
+
445
+ ## Flujo de Trabajo
446
+
447
+ ```
448
+ ┌─────────────────────────────────────────────────────────────────────────┐
449
+ │ 1. DISEÑO ARQUITECTURAL │
450
+ │ │
451
+ │ [Definir/editar system.yaml] │
452
+ │ eva system validate → detecta inconsistencias en el grafo │
453
+ └──────────────────────────────────────┬──────────────────────────────────┘
454
+
455
+
456
+ ┌─────────────────────────────────────────────────────────────────────────┐
457
+ │ 2. BOOTSTRAP │
458
+ │ │
459
+ │ eva generate system │
460
+ │ → proyecto base (build.gradle, Application.java, shared/) │
461
+ │ → módulo vacío por cada entrada en modules: │
462
+ │ → domain.yaml esqueleto con endpoints: pre-generado (del system.yaml) │
463
+ │ │
464
+ │ (re-ejecutable) agrega módulos nuevos declarados en system.yaml │
465
+ │ que aún no existen en el proyecto │
466
+ └──────────────────────────────────────┬──────────────────────────────────┘
467
+
468
+
469
+ ┌─────────────────────────────────────────────────────────────────────────┐
470
+ │ 3. MODELADO DE DOMINIO (por módulo, de forma independiente) │
471
+ │ │
472
+ │ [Editar orders/domain.yaml] → aggregates + events + ports: │
473
+ │ [Editar payments/domain.yaml] → aggregates + events + ports: │
474
+ │ [Editar customers/domain.yaml] → aggregates + events │
475
+ └──────────────────────────────────────┬──────────────────────────────────┘
476
+
477
+
478
+ ┌─────────────────────────────────────────────────────────────────────────┐
479
+ │ 4. GENERACIÓN DE CÓDIGO │
480
+ │ │
481
+ │ eva g entities orders → entidades, repos, mappers, │
482
+ │ kafka events, feign clients (ports:) │
483
+ │ eva g entities payments │
484
+ │ eva g entities customers │
485
+ │ eva system diagram → diagrama Mermaid del sistema │
486
+ └─────────────────────────────────────────────────────────────────────────┘
487
+ ```
488
+
489
+ ---
490
+
491
+ ## Comandos Nuevos
492
+
493
+ | Comando | Descripción |
494
+ |---|---|
495
+ | `eva system validate` | Valida coherencia del `system.yaml` (referencias rotas, ciclos, eventos sin consumidor, `ports[].target` inexistentes) |
496
+ | `eva generate system` | Bootstrap completo: proyecto + módulos + `domain.yaml` esqueleto con `endpoints:` pre-generado |
497
+ | `eva system diagram` | Genera diagrama Mermaid del grafo de módulos y comunicaciones |
498
+
499
+ ### Relación con comandos existentes
500
+
501
+ Los comandos actuales (`eva g kafka-event`, `eva g kafka-listener`, `eva g http-exchange`) seguirían funcionando para casos puntuales. El comando `eva g entities <module>` ahora también genera el código de infraestructura derivado de `ports:` (feign clients) y `events[]` (kafka producers/consumers), sin prompts interactivos.
502
+
503
+ ---
504
+
505
+ ## Validaciones de `system.yaml`
506
+
507
+ `eva system validate` detectaría los siguientes problemas:
508
+
509
+ | Tipo | Ejemplo |
510
+ |---|---|
511
+ | Módulo inexistente en consumidor | `consumers[].module: inventario` pero `inventario` no está en `modules:` |
512
+ | Evento consumido sin productor | `consumes` un `StockUpdatedEvent` que ningún módulo publica |
513
+ | Endpoint referenciado no expuesto | `calls.using: GET /customers/profile` pero `customers` no lo declara en `exposes:` |
514
+ | Dependencia circular síncrona | `orders` llama a `payments` y `payments` llama a `orders` |
515
+ | Puerto con módulo inexistente | `domain.yaml → ports[].target: inventario` pero `inventario` no está en `system.yaml → modules:` |
516
+ | Evento sin consumidores | Un evento publicado que nadie consume (advertencia, no error) |
517
+
518
+ ---
519
+
520
+ ## Aspectos Positivos del Enfoque
521
+
522
+ ### 1. Diseño antes de código
523
+ El equipo puede definir y discutir la arquitectura del sistema completo en un solo archivo de texto antes de escribir una sola línea de código Java. El `system.yaml` es legible por cualquier miembro del equipo, incluso sin conocimiento técnico profundo.
524
+
525
+ ### 2. Single source of truth arquitectural
526
+ Toda la topología del sistema — qué módulos existen, qué publican, qué consumen, a quién llaman — vive en un único lugar. Elimina la necesidad de diagramas de arquitectura que quedan desactualizados.
527
+
528
+ ### 3. Eliminación de prompts interactivos
529
+ Los comandos actuales (`eva g kafka-event`, `eva g kafka-listener`, `eva g http-exchange`) requieren responder preguntas cada vez que se ejecutan. Con `domain.yaml → events[]` y `ports:`, `eva g entities <module>` genera todo (kafka producers, listeners, feign clients) de una vez, sin interacción, reproducible y apto para CI/CD.
530
+
531
+ ### 4. Contratos explícitos entre módulos
532
+ Los `events[]` en `domain.yaml` del productor definen el contrato completo del evento. Los `ports:` en `domain.yaml` del consumidor declaran explícitamente qué campos del servicio remoto necesita. Esto hace visibles las dependencias de datos entre módulos y reduce el acoplamiento implícito.
533
+
534
+ ### 5. Detección temprana de inconsistencias
535
+ `eva system validate` detecta problemas de arquitectura (referencias rotas, dependencias circulares, contratos mal definidos) antes de generar código y antes de desplegar, cuando el costo de corregirlos es mínimo.
536
+
537
+ ### 6. Escalabilidad del proceso
538
+ El mismo flujo funciona para un sistema con 3 módulos o con 30. El `system.yaml` crece linealmente y sigue siendo el mapa del sistema.
539
+
540
+ ### 7. Separación de responsabilidades clara
541
+ Cada archivo tiene una responsabilidad única y bien definida:
542
+ - `system.yaml` → **qué existe** (arquitectura — módulos y comunicación)
543
+ - `domain.yaml` → **qué es y qué necesita** (negocio + puertos secundarios)
544
+
545
+ Un cambio de dominio no toca `system.yaml`. Un cambio de arquitectura no toca `domain.yaml`. Las responsabilidades no se mezclan.
546
+
547
+ ### 8. Diseño iterativo del sistema
548
+ El `system.yaml` no es solo un artefacto de arranque — **evoluciona con el proyecto**. Es normal que durante el desarrollo emerjan nuevos módulos, endpoints o integraciones que no se vieron inicialmente. Cada iteración sobre `system.yaml` sigue el mismo ciclo ligero: editar → `eva system validate` → actualizar `domain.yaml` afectado → `eva g entities`. El costo de cambiar la arquitectura permanece bajo porque la revisión ocurre en YAML, no en código.
549
+
550
+ ### 9. Diagrama siempre actualizado
551
+ `eva system diagram` genera un diagrama Mermaid directamente desde `system.yaml`, garantizando que la documentación visual del sistema nunca queda desactualizada respecto al código.
552
+
553
+ ### 10. Preparación natural para microservicios
554
+ El comando `eva detach <module>` (ya existente) se vuelve más potente porque el `system.yaml` ya documenta exactamente qué contratos expone el módulo y con quién se comunica — toda la información necesaria para extraerlo como servicio independiente.
555
+
556
+ ---
557
+
558
+ ## Colaboración con Agentes de IA
559
+
560
+ ### El problema actual con AI + generación de código
561
+
562
+ Un agente de IA hoy necesita responder preguntas como: ¿qué hace este módulo?, ¿con quién se comunica?, ¿qué eventos publica o consume?, ¿qué ya existe en el sistema? Sin `system.yaml`, el agente tiene que **inferir** todo eso leyendo código, archivos de configuración dispersos y documentación posiblemente desactualizada. El contexto es ruidoso, incompleto y costoso en tokens.
563
+
564
+ ### Los YAMLs como contexto perfecto para un agente
565
+
566
+ Los dos archivos juntos son **densos en significado y mínimos en ruido**. Un agente puede leerlos y tener comprensión completa de un módulo en ~100 líneas de YAML, en lugar de miles de líneas de Java:
567
+
568
+ ```
569
+ system.yaml → "qué soy dentro del sistema y con quién hablo"
570
+ domain.yaml → "qué reglas de negocio tengo y qué necesito de otros módulos"
571
+ ```
572
+
573
+ ### División natural de trabajo humano-agente
574
+
575
+ El enfoque habilita una colaboración por capas donde el humano opera en el nivel de **intención** y el agente en el nivel de **estructura y detalle**:
576
+
577
+ | Humano | Agente de IA |
578
+ |---|---|
579
+ | Define `system.yaml` (visión arquitectural) | Valida coherencia del grafo, detecta dependencias circulares, sugiere módulos faltantes |
580
+ | Revisa y aprueba | Genera `domain.yaml` de cada módulo (entidades, campos, relaciones, enums, eventos) |
581
+ | Refina `domain.yaml` (ajusta reglas de negocio y puertos) | Completa `domain.yaml` con `ports:` y ajusta `events[]` |
582
+ | Revisa y aprueba | Ejecuta `eva g entities` por módulo — código completo listo para compilar |
583
+
584
+ ### Instrucciones precisas y verificables para el agente
585
+
586
+ Con el enfoque YAML-first el agente no infiere — **ejecuta sobre especificación explícita**:
587
+
588
+ - El `system.yaml` le dice el **contrato** que debe respetar
589
+ - El `AGENTS.md` le dice los **patrones** que debe seguir
590
+ - El `domain.yaml` le dice **exactamente qué generar**
591
+
592
+ El resultado es predecible, revisable y consistente entre iteraciones.
593
+
594
+ ### Iteración quirúrgica sin regenerar todo
595
+
596
+ El modelo YAML como fuente de verdad hace que cada cambio sea mínimo y rastreable:
597
+
598
+ ```
599
+ Cambio de negocio: editar domain.yaml → eva g entities orders
600
+ Nuevo evento: editar system.yaml → eva system validate
601
+ editar domain.yaml → eva g entities orders payments
602
+ Nuevo módulo: editar system.yaml → eva system validate
603
+ eva generate system → genera el módulo nuevo
604
+ diseñar domain.yaml → eva g entities <nuevo-modulo>
605
+ Nuevo endpoint: editar system.yaml (exposes:) → eva system validate
606
+ editar domain.yaml (endpoints:) → eva g entities orders
607
+ Nueva feature completa: agente recibe domain.yaml actual + descripción del cambio
608
+ propone domain.yaml actualizado (diff mínimo)
609
+ humano aprueba → eva g entities
610
+ ```
611
+
612
+ Cada iteración tiene un **artefacto de revisión claro** (el YAML diff) antes de que se toque una línea de código Java.
613
+
614
+ ### Los YAMLs como sistema de conocimiento del proyecto
615
+
616
+ Combinados, los cuatro archivos forman el contexto completo para cualquier agente que se incorpore al proyecto:
617
+
618
+ ```
619
+ AGENTS.md → "cómo se hace en eva4j" (patrones globales)
620
+ system.yaml → "qué existe en este proyecto" (topología del sistema)
621
+ domain.yaml → "qué es este módulo y cómo habla" (negocio + puertos)
622
+ ```
623
+
624
+ Un agente que recibe estos tres archivos tiene todo lo que necesita para contribuir al proyecto **sin sesión de onboarding**.
625
+
626
+ ### Generación en cascada desde una sola sesión
627
+
628
+ El flujo completo puede ejecutarse colaborativamente en una sola conversación con un agente, donde el YAML actúa como checkpoint de revisión humana entre cada paso — no es generación ciega de código, sino colaboración estructurada con puntos de control explícitos:
629
+
630
+ ```
631
+ 1. Humano describe el negocio en lenguaje natural
632
+ 2. Agente propone system.yaml
633
+ 3. Humano refina system.yaml → eva system validate
634
+ 4. Agente genera domain.yaml de cada módulo (entities + events + ports)
635
+ 5. Humano revisa y ajusta
636
+ 6. eva g entities por módulo → código completo generado
637
+ 7. Sistema funcionando
638
+ ```
639
+
640
+ ---
641
+
642
+ ## Cómo Construir el system.yaml con un Agente de IA
643
+
644
+ ### Qué debe saber el agente antes de empezar
645
+
646
+ Para que el agente proponga un `system.yaml` correcto y coherente, necesita recibir en el prompt inicial:
647
+
648
+ | Información | Por qué es necesaria |
649
+ |---|---|
650
+ | Descripción del negocio en lenguaje natural | Para inferir bounded contexts y responsabilidades de cada módulo |
651
+ | Lista de módulos identificados (opcional) | Para no inventar módulos — si ya hay claridad, evita iteraciones innecesarias |
652
+ | Flujos de negocio principales | Para determinar qué comunicación es async (Kafka) y qué es sync (HTTP) |
653
+ | `SYSTEM_YAML_GUIDE.md` adjunto | Para respetar la sintaxis exacta y las reglas de validación |
654
+ | Metadata del proyecto (groupId, Java version) | Para completar la sección `system:` correctamente |
655
+
656
+ ### Prompt inicial recomendado
657
+
658
+ ```
659
+ Eres un arquitecto de software experto en DDD y arquitectura hexagonal.
660
+ Tu tarea es construir el system.yaml para un proyecto eva4j.
661
+
662
+ Sistema: [descripción del negocio en 2-5 oraciones]
663
+
664
+ Módulos identificados:
665
+ - [módulo 1]: [responsabilidad]
666
+ - [módulo 2]: [responsabilidad]
667
+ - ...
668
+
669
+ Flujos principales:
670
+ - [flujo 1]: cuando [evento de negocio], [módulo A] notifica a [módulo B] y [módulo C]
671
+ - [flujo 2]: para [operación], [módulo X] necesita datos de [módulo Y]
672
+
673
+ Metadata:
674
+ - groupId: com.acme
675
+ - javaVersion: 21
676
+ - springBootVersion: 3.4.1
677
+ - database: postgresql
678
+
679
+ Adjunto: SYSTEM_YAML_GUIDE.md con la sintaxis completa y restricciones.
680
+
681
+ Genera el system.yaml completo respetando:
682
+ 1. Sección system: con la metadata del proyecto
683
+ 2. Sección modules: con los endpoints REST que expone cada módulo
684
+ 3. Sección integrations.async: eventos Kafka con producer y consumers
685
+ 4. Sección integrations.sync: llamadas HTTP entre módulos
686
+ 5. Eventos nombrados en pasado (OrderPlacedEvent, no PlaceOrder)
687
+ 6. Sin dependencias circulares síncronas
688
+ ```
689
+
690
+ ### Ciclo de refinamiento
691
+
692
+ ```
693
+ ┌──────────────────────────────────────────────────────────────────┐
694
+ │ 1. CONTEXTO │
695
+ │ Humano provee: descripción + módulos + flujos │
696
+ │ + SYSTEM_YAML_GUIDE.md adjunto │
697
+ └──────────────────────────────┬───────────────────────────────────┘
698
+
699
+
700
+ ┌──────────────────────────────────────────────────────────────────┐
701
+ │ 2. PROPUESTA │
702
+ │ Agente genera system.yaml v1 │
703
+ │ - Infiere módulos y responsabilidades │
704
+ │ - Define endpoints REST por módulo │
705
+ │ - Deduce integración async (Kafka) vs sync (HTTP) │
706
+ │ - Nombra eventos en pasado, modules en kebab-case │
707
+ └──────────────────────────────┬───────────────────────────────────┘
708
+
709
+
710
+ ┌──────────────────────────────────────────────────────────────────┐
711
+ │ 3. VALIDACIÓN AUTOMÁTICA │
712
+ │ eva system validate │
713
+ │ - Módulos referenciados inexistentes │
714
+ │ - Dependencias circulares síncronas │
715
+ │ - Eventos sin consumidores │
716
+ │ - Endpoints llamados no declarados en exposes: │
717
+ └──────────────────────────────┬───────────────────────────────────┘
718
+
719
+
720
+ ┌──────────────────────────────────────────────────────────────────┐
721
+ │ 4. REVISIÓN HUMANA │
722
+ │ Feedback específico al agente: │
723
+ │ - "El módulo X debería también exponer PUT /x/{id}/cancel" │
724
+ │ - "El evento Y debería consumirlo también el módulo Z" │
725
+ │ - "La llamada de A a B debería ser async, no sync" │
726
+ └──────────────────────────────┬───────────────────────────────────┘
727
+
728
+
729
+ ┌──────────────────────────────────────────────────────────────────┐
730
+ │ 5. REFINAMIENTO │
731
+ │ Agente aplica cambios mínimos → system.yaml v2 │
732
+ │ Iterar pasos 3-5 hasta aprobación │
733
+ └──────────────────────────────┬───────────────────────────────────┘
734
+
735
+
736
+ ┌──────────────────────────────────────────────────────────────────┐
737
+ │ 6. BOOTSTRAP │
738
+ │ eva generate system → proyecto + módulos + domain.yaml │
739
+ │ (con endpoints: pre-generados) │
740
+ └──────────────────────────────────────────────────────────────────┘
741
+ ```
742
+
743
+ ### Preguntas clave para guiar al agente
744
+
745
+ Cuando el agente propone el `system.yaml`, estas preguntas ayudan a refinar el diseño:
746
+
747
+ | Pregunta | Intención |
748
+ |---|---|
749
+ | "¿Qué módulo es responsable de X?" | Clarifica bounded contexts y evita duplicación de responsabilidad |
750
+ | "¿Este flujo debería ser async o sync?" | Define el estilo de integración según tolerancia a latencia y acoplamiento |
751
+ | "¿Quién es el productor natural de este evento?" | Define el ownership del evento en el dominio |
752
+ | "¿Qué endpoints necesita el frontend?" | Completa la sección `exposes:` de cada módulo |
753
+ | "¿Hay eventos que nadie consume todavía?" | Detecta gaps en el diseño antes de generar código |
754
+ | "¿Alguna llamada sync puede volverse async?" | Reduce acoplamiento temporal entre módulos |
755
+
756
+ ### Criterios de calidad del system.yaml generado
757
+
758
+ Antes de aprobar el `system.yaml` propuesto por el agente, verificar:
759
+
760
+ - ✅ Cada módulo tiene **una sola responsabilidad** claramente identificable
761
+ - ✅ Los eventos están nombrados en **tiempo pasado** (`OrderPlacedEvent`, no `PlaceOrderEvent`)
762
+ - ✅ Los nombres de módulos usan **kebab-case** (`order-management`, no `OrderManagement`)
763
+ - ✅ **Sin dependencias circulares síncronas** (A llama a B y B llama a A)
764
+ - ✅ Módulos de solo lectura (reporting, notificaciones) son **consumidores**, nunca callers síncronos
765
+ - ✅ Los eventos contienen **datos mínimos necesarios** — el consumidor pide más si necesita
766
+ - ✅ Los endpoints en `exposes:` cubren **todas las operaciones** del módulo, no solo las que otros módulos usan
767
+ - ✅ `eva system validate` **no reporta errores** (solo advertencias aceptables)
768
+
769
+ ### Por qué el agente necesita el SYSTEM_YAML_GUIDE.md
770
+
771
+ Sin una referencia técnica precisa, el agente puede generar YAML semánticamente válido pero estructuralmente incorrecto para eva4j — por ejemplo: usar `consumes:` en `system.yaml` (que no existe en ese nivel), invertir la dirección de `sync.caller/calls`, o nombrar los eventos sin sufijo `Event`. El `SYSTEM_YAML_GUIDE.md` actúa como **gramática contractual** que el agente debe respetar, equivalente al rol que AGENTS.md cumple para la generación de código Java.
772
+
773
+ ---
774
+
775
+ ## Preguntas Abiertas
776
+
777
+ 1. ~~**¿`system.yaml` como fuente de verdad permanente o solo bootstrap inicial?**~~
778
+ ~~¿Los `domain.yaml` son siempre derivados del `system.yaml` (un cambio en uno requiere actualizar el otro), o el `system.yaml` solo se usa para el arranque inicial y después cada módulo evoluciona libremente?~~
779
+ **Resuelto:** el `system.yaml` es un artefacto **iterativo** que evoluciona con el proyecto. Es normal que emerjan nuevos módulos, endpoints o integraciones no previstos inicialmente. Cada cambio sigue el mismo ciclo: editar → `eva system validate` → actualizar `domain.yaml` afectado → `eva g entities`. `eva generate system` es re-ejecutable: agrega módulos nuevos que aún no existen y **siempre sobreescribe el `domain.yaml`** de todos los módulos con el esqueleto actualizado desde `system.yaml` (los módulos ya existentes no se recrean, solo se regenera su `domain.yaml`).
780
+
781
+ 2. ~~**¿Cómo manejar eventos cuyos campos no están definidos en `system.yaml`?**~~
782
+ ~~El `system.yaml` no conoce los campos de los eventos (ese es territorio del dominio). ¿El `integration.yaml → consumes[].fields` es suficiente como contrato, o hace falta un schema compartido?~~
783
+ **Resuelto:** los campos del evento se declaran en `domain.yaml → events[].fields` del módulo productor. El consumidor los conoce al leer el `domain.yaml` del productor. No hace falta un schema compartido separado.
784
+
785
+ 3. **¿Soporte para múltiples entornos en `system.yaml`?**
786
+ Los `baseUrl` de los `calls:` son distintos por entorno. ¿Se resuelve con variables de entorno, o el `system.yaml` puede tener secciones por entorno?
787
+
788
+ 4. **¿Qué pasa con módulos que no están en `system.yaml` pero ya existen?**
789
+ Para proyectos existentes, ¿hay un comando `eva system scan` que genere el `system.yaml` a partir de la estructura actual?
790
+
791
+ 5. ~~**Granularidad de `exposes:`**~~
792
+ ~~¿Los endpoints en `exposes:` solo son documentales, o en el futuro podrían incluir request/response bodies para generar también los DTOs del controller?~~
793
+ **Resuelto:** sintaxis objeto obligatoria con `method`, `path`, `useCase` y `description`. El campo `useCase` permite a `eva generate system` pre-generar la sección `endpoints:` completa en `domain.yaml`; el desarrollador solo rellena `aggregates:`.
794
+
795
+ ---
796
+
797
+ *Este documento es un artefacto de diseño vivo. Las ideas aquí plasmadas están sujetas a revisión y refinamiento.*