@ronaldjdevfs/forge 1.3.0-beta → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/skills/forge/SKILL.md +57 -128
  4. package/skills/forge/command/forge.md +59 -14
  5. package/skills/forge/reference/adr.md +242 -0
  6. package/skills/forge/reference/anti-corruption-layer.md +340 -0
  7. package/skills/forge/reference/api-design.md +7 -0
  8. package/skills/forge/reference/api-versioning.md +354 -0
  9. package/skills/forge/reference/architectural-depth-checklist.md +311 -0
  10. package/skills/forge/reference/architecture-template.md +41 -0
  11. package/skills/forge/reference/assay.md +6 -0
  12. package/skills/forge/reference/bounded-contexts.md +311 -0
  13. package/skills/forge/reference/chain.md +6 -0
  14. package/skills/forge/reference/cohesion-checklist.md +256 -0
  15. package/skills/forge/reference/cqrs.md +286 -0
  16. package/skills/forge/reference/data-patterns.md +6 -0
  17. package/skills/forge/reference/di-strategies.md +6 -0
  18. package/skills/forge/reference/errors.md +5 -0
  19. package/skills/forge/reference/events.md +8 -0
  20. package/skills/forge/reference/evolutionary-architecture.md +300 -0
  21. package/skills/forge/reference/forge.md +7 -0
  22. package/skills/forge/reference/hooks.md +6 -0
  23. package/skills/forge/reference/idempotency.md +283 -0
  24. package/skills/forge/reference/inscribe.md +5 -0
  25. package/skills/forge/reference/inspect.md +6 -0
  26. package/skills/forge/reference/modular-monolith.md +252 -0
  27. package/skills/forge/reference/observability.md +5 -0
  28. package/skills/forge/reference/quench.md +5 -0
  29. package/skills/forge/reference/relocate.md +6 -0
  30. package/skills/forge/reference/sagas.md +359 -0
  31. package/skills/forge/reference/security-patterns.md +6 -0
  32. package/skills/forge/reference/smelt.md +6 -0
  33. package/skills/forge/reference/temper.md +6 -0
  34. package/skills/forge/reference/testing-patterns.md +6 -0
  35. package/skills/forge/reference/transactional-outbox.md +311 -0
  36. package/skills/forge/scripts/architecture.mjs +10 -5
  37. package/skills/forge/scripts/assay.mjs +2 -2
  38. package/skills/forge/scripts/chain.mjs +31 -5
  39. package/skills/forge/scripts/context.mjs +24 -4
  40. package/skills/forge/scripts/detect.mjs +39 -30
  41. package/skills/forge/scripts/forge-boot.mjs +108 -0
  42. package/skills/forge/scripts/forge-config.mjs +182 -3
  43. package/skills/forge/scripts/forge-state.mjs +1 -1
  44. package/skills/forge/scripts/forgeSentinel-lib.mjs +2 -2
  45. package/skills/forge/scripts/forgeSentinel.mjs +2 -2
  46. package/skills/forge/scripts/forgeSmith.mjs +2 -2
  47. package/skills/forge/scripts/graph.mjs +65 -9
  48. package/skills/forge/scripts/hook.mjs +2 -2
  49. package/skills/forge/scripts/inspect.mjs +56 -48
  50. package/skills/forge/scripts/parse-imports.mjs +0 -2
  51. package/skills/forge/scripts/posttool.mjs +211 -17
  52. package/skills/forge/scripts/recommendation-engine.mjs +125 -0
  53. package/skills/forge/scripts/rollback.mjs +5 -3
  54. package/skills/forge/templates/feature/acl-gateway.ts.md +52 -0
  55. package/skills/forge/templates/feature/acl-repository.ts.md +36 -0
  56. package/skills/forge/templates/feature/acl-translator.ts.md +24 -0
  57. package/skills/forge/templates/feature/cqrs-query.ts.md +40 -0
  58. package/skills/forge/templates/feature/outbox-repository.ts.md +36 -0
  59. package/skills/forge/templates/feature/saga-orchestrator.ts.md +72 -0
  60. package/skills/forge/templates/platform/outbox-relayer.ts.md +80 -0
  61. package/skills/forge/tests/core.test.mjs +288 -4
  62. package/src/cli.js +26 -13
@@ -0,0 +1,311 @@
1
+ # Architectural Depth — Checklist de Referencias
2
+
3
+ Checklist de las 10 nuevas referencias estratégicas para Forge. Cada entrada define el alcance exacto, secciones obligatorias, relaciones con referencias existentes y criterio de completitud.
4
+
5
+ ---
6
+
7
+ ## Estado actual
8
+
9
+ ```
10
+ [x] 01 — bounded-contexts.md — DDD Estratégico
11
+ [x] 02 — modular-monolith.md — Estrategia de despliegue
12
+ [x] 03 — adr.md — Registro de decisiones
13
+ [x] 04 — anti-corruption-layer.md — Integración legacy
14
+ [x] 05 — evolutionary-architecture.md — Evolución arquitectónica
15
+ [x] 06 — cqrs.md — CQRS
16
+ [x] 07 — sagas.md — Transacciones distribuidas
17
+ [x] 08 — transactional-outbox.md — Fiabilidad de eventos
18
+ [x] 09 — idempotency.md — Idempotencia
19
+ [x] 10 — api-versioning.md — Evolución de contratos
20
+ ```
21
+
22
+ ---
23
+
24
+ ## 01 — `bounded-contexts.md`
25
+
26
+ **Propósito:** Fundamentar la capa `features/` en DDD Estratégico. Sin bounded contexts, las features son sólo directorios.
27
+
28
+ **Depende de:** nada (fundacional)
29
+ **Es usado por:** `modular-monolith.md`, `anti-corruption-layer.md`, `cqrs.md`, `sagas.md`
30
+
31
+ ### Secciones obligatorias
32
+
33
+ - [ ] **Fundamentos de DDD Estratégico**: dominio, subdominio (core/supporting/generic), bounded context
34
+ - [ ] **Ubiquitous Language**: por contexto, glosario compartido, conflictos de lenguaje
35
+ - [ ] **Context Mapping**: Partnership, Shared Kernel, Customer-Supplier, Conformist, Anti-Corruption Layer, Open-Host Service, Published Language, Separate Ways
36
+ - [ ] **Identificación de bounded contexts**: heurísticas (equipo, lenguaje, modelo, base de datos)
37
+ - [ ] **Mapeo visual**: diagrama de contexts con relaciones y flujos
38
+ - [ ] **Relación con el modelo de Forge**: cómo cada feature se corresponde con (parte de) un bounded context
39
+ - [ ] **Anti-patrones**: contextos gigantes (orphan core), contextos fantasma, contextos sin lenguaje
40
+ - [ ] **Ejemplo completo**: sistema de e-commerce con 4-5 bounded contexts mapeados
41
+ - [ ] **Conexión con reglas R8 y R9**: cómo los contextos prohíben acoplamiento directo y ciclos
42
+
43
+ ### Criterio de completitud
44
+
45
+ Un lector puede tomar cualquier feature existente y determinar su bounded context, su relación con otros contexts, y si el mapeo actual viola algún patrón de integridad.
46
+
47
+ ---
48
+
49
+ ## 02 — `modular-monolith.md`
50
+
51
+ **Propósito:** Proveer un marco de decisión para elegir entre monolith modular y microservicios, alineado con el modelo de 4 capas.
52
+
53
+ **Depende de:** `bounded-contexts.md`
54
+ **Es usado por:** `relocate.md`, `reforge.md`, `cast.md`
55
+
56
+ ### Secciones obligatorias
57
+
58
+ - [ ] **Definición de modular monolith**: módulos con boundaries fuertes, mismo proceso, despliegue único
59
+ - [ ] **Espectro Monolith → Modular → Microservices**: continuo, no binario
60
+ - [ ] **Marco de decisión**: cohesión, acoplamiento, topología de equipo (Conway's Law), escalabilidad, deployment autonomy
61
+ - [ ] **Cuándo mantener monolith**: equipo pequeño, dominio cohesionado, latencia crítica, inicio incierto
62
+ - [ ] **Señales para partir**: equipo scaling, deployment bottleneck, boundaries maduros, different failure characteristics
63
+ - [ ] **Criterio de corte por capa**: qué puede vivir como servicio vs qué debe compartirse (shared, platform)
64
+ - [ ] **Integración con Forge**: cómo modelar módulos usando features existentes, qué reglas (R8) se relajan dentro del monolith
65
+ - [ ] **Transición controlada**: split de features sin reescritura (strangler fig aplicado a features)
66
+ - [ ] **Anti-patrones**: distributed monolith, premature splitting, shared database entre servicios, nano-services
67
+ - [ ] **Ejemplo**: monolith modular de SaaS facturación que eventualmente parte billing en servicio separado
68
+
69
+ ### Criterio de completitud
70
+
71
+ Un equipo puede evaluar su arquitectura actual contra el marco de decisión y obtener una recomendación accionable sobre si partir o consolidar y por dónde empezar.
72
+
73
+ ---
74
+
75
+ ## 03 — `adr.md`
76
+
77
+ **Propósito:** Capturar y preservar decisiones arquitectónicas como parte del workflow de Forge.
78
+
79
+ **Depende de:** nada
80
+ **Es usado por:** `reforge.md`, `cast.md`, `inscribe.md`, todos
81
+
82
+ ### Secciones obligatorias
83
+
84
+ - [ ] **Formato ADR estándar**: Title, Status, Context, Decision, Consequences (plantilla)
85
+ - [ ] **Variantes**: ADR simple (5 secciones), ADR extendido (con alternatives, compliance), ADR ligero (1 párrafo)
86
+ - [ ] **Estados**: Proposed → Accepted / Deprecated / Superseded / Amended
87
+ - [ ] **Integración con `inscribe`**: anexar ADRs activos en ARCHITECTURE.md
88
+ - [ ] **Integración con `assay`**: las decisiones como insumo para el ensayo multi-persona
89
+ - [ ] **Cuándo escribir un ADR**: scoping, tecnología, patrón, estándar, cambio de regla, excepción
90
+ - [ ] **ADRs como fuente de verdad**: enlazar ADRs desde reglas de detect.mjs, desde inline ignores
91
+ - [ ] **Ejemplos**: ADRs reales del modelo Forge (ej. "usar capa Shared en vez de cross-feather imports", "adoptar Prisma como ORM")
92
+ - [ ] **Tooling**: script para crear, listar, cambiar estado de ADRs
93
+ - [ ] **Anti-patrones**: ADRs que nunca se leen, ADRs sin contexto, ADRs sin consecuencia, ADRs de frameworks
94
+
95
+ ### Criterio de completitud
96
+
97
+ Un `forge inscribe` genera ARCHITECTURE.md con enlaces a ADRs activos. Un nuevo miembro del equipo puede entender las decisiones clave en 10 minutos.
98
+
99
+ ---
100
+
101
+ ## 04 — `anti-corruption-layer.md`
102
+
103
+ **Propósito:** Aislar sistemas legacy o externos sin contaminar el modelo de dominio de Forge.
104
+
105
+ **Depende de:** `bounded-contexts.md`
106
+ **Es usado por:** `relocate.md`, `reforge.md`, `cast.md`
107
+
108
+ ### Secciones obligatorias
109
+
110
+ - [ ] **Definición y propósito ACL**: traducir entre modelos, evitar corrupción del modelo de dominio
111
+ - [ ] **Estructura de una ACL**: adapters de entrada (traducen del externo al dominio), adapters de salida (traducen del dominio al externo)
112
+ - [ ] **Strangler Fig pattern**: migración incremental con ACL como fachada
113
+ - [ ] **Implementación en el modelo de Forge**: la ACL vive en `adapter/out/` de una feature y traduce entre `infra/` y el modelo de dominio
114
+ - [ ] **Mapeo de integraciones legacy**: cómo modelar sistemas externos como bounded contexts con ACL
115
+ - [ ] **Estrategias de traducción**: event-based (publicar/suscribir), service-based (llamadas sincrónicas), repository-based (datos compartidos)
116
+ - [ ] **Conexión con reglas R1 y R7**: cómo ACL permite feature → infra sin violar la regla (porque el adapter traduce)
117
+ - [ ] **Detección automática**: qué patrones en detect.mjs indican necesidad de ACL
118
+ - [ ] **Ejemplo**: feature de "Orders" migrando de legacy SQL a nuevo schema con ACL + Strangler Fig
119
+ - [ ] **Anti-patrones**: ACL que filtra sin traducir (leaky abstraction), ACL que muta el origen, ACL como pasamanos
120
+
121
+ ### Criterio de completitud
122
+
123
+ Un desarrollador puede identificar cuándo necesita una ACL, modelarla dentro del feature correspondiente, y ejecutar la migración con `relocate` sin romper el sistema existente.
124
+
125
+ ---
126
+
127
+ ## 05 — `evolutionary-architecture.md`
128
+
129
+ **Propósito:** Guiar la evolución continua de la arquitectura sin reescrituras, usando fitness functions.
130
+
131
+ **Depende de:** nada (fundacional)
132
+ **Es usado por:** `inspect.md`, `reforge.md`, `graph.md`, `quench.md`
133
+
134
+ ### Secciones obligatorias
135
+
136
+ - [ ] **Definición**: arquitectura que evoluciona incrementalmente guiada por fitness functions
137
+ - [ ] **Fitness functions**: tests automatizados que validan características arquitectónicas (acoplamiento, modularidad, performance, seguridad)
138
+ - [ ] **Tipos de fitness functions**: estáticas (lint-level), dinámicas (runtime), periódicas (benchmark), trigger-based (CI)
139
+ - [ ] **Implementación en Forge**: las reglas R1-R9 como fitness functions gobernadas por detect.mjs
140
+ - [ ] **Fitness functions custom**: cómo el usuario define sus propias funciones y se registran en registry/rules.mjs
141
+ - [ ] **Guía de cambio incremental**: smallest viable change, refactor patterns, scaffolding antes de feature completo
142
+ - [ ] **Evolución de boundaries**: cómo partir, fusionar o mover features sin reescribir
143
+ - [ ] **Integración con CI/CD**: fitness functions en pipeline, gate de deployment, alertas de regresión
144
+ - [ ] **Ejemplo**: fitness function "no feature importa infra" evolucionando a "ningún módulo importa otro módulo sin interfaz"
145
+ - [ ] **Anti-patrones**: big-bang rewrite, frozen architecture, analysis paralysis, chasing tech debt sin métrica
146
+
147
+ ### Criterio de completitud
148
+
149
+ Un equipo puede añadir fitness functions personalizadas, integrarlas en su pipeline, y medir la salud arquitectónica en cada PR sin intervención manual.
150
+
151
+ ---
152
+
153
+ ## 06 — `cqrs.md`
154
+
155
+ **Propósito:** Modelar separación de commands y queries dentro de features con demandas asimétricas.
156
+
157
+ **Depende de:** `bounded-contexts.md`
158
+ **Es usado por:** `data-patterns.md`, `events.md`, `sagas.md`, `cast.md`
159
+
160
+ ### Secciones obligatorias
161
+
162
+ - [ ] **Fundamentos**: Command (escritura, efecto secundario, validación) vs Query (lectura, proyección, sin efectos)
163
+ - [ ] **Cuándo aplicar CQRS**: modelos de lectura/escritura divergentes, escalabilidad asimétrica, equipos separados, event sourcing
164
+ - [ ] **Implementación en el modelo de Forge**: command → use-case, query → repository o query service separado
165
+ - [ ] **Read models**: proyecciones desnormalizadas, tablas de lectura, caché de queries
166
+ - [ ] **CQRS parcial (sin event sourcing)**: commands y queries separados en la aplicación, misma BD
167
+ - [ ] **CQRS completo**: read model separado (tabla, BD, cache), eventual consistency
168
+ - [ ] **Materialized views / Projections**: cómo mantener read models actualizados
169
+ - [ ] **Separación de interfaces**: ICommandBus, IQueryBus como contratos en shared/
170
+ - [ ] **Conexión con reglas**: CQRS no viola ninguna regla de Forge porque commands y queries residen dentro del mismo feature
171
+ - [ ] **Anti-patrones**: CQRS everywhere (para CRUD simple), query leak (lógica de negocio en read model), eventual consistency ignorada
172
+ - [ ] **Ejemplo**: feature "Analytics" con CQRS parcial + read model en Redis via infra/redis
173
+
174
+ ### Criterio de completitud
175
+
176
+ Un feature complejo con demands asimétricas puede modelarse con CQRS dentro de la estructura de Forge sin violar reglas y sin over-engineering.
177
+
178
+ ---
179
+
180
+ ## 07 — `sagas.md`
181
+
182
+ **Propósito:** Coordinar transacciones multi-feature sin violar la regla R8 (no acoplamiento directo entre features).
183
+
184
+ **Depende de:** `bounded-contexts.md`, `events.md`
185
+ **Es usado por:** `cast.md`, `reforge.md`, `events.md`
186
+
187
+ ### Secciones obligatorias
188
+
189
+ - [ ] **Problema**: transacciones que cruzan bounded contexts sin ACID distribuido
190
+ - [ ] **Definición de Saga**: secuencia de transacciones locales con compensación
191
+ - [ ] **Coreografía (Choreography)**: cada participante publica/escucha eventos, decisión descentralizada
192
+ - [ ] **Orquestación (Orchestration)**: coordinador central que instruye a los participantes
193
+ - [ ] **Compensación**: transacciones reversibles, acciones compensatorias, consistencia eventual
194
+ - [ ] **Manejo de fallos**: retry con backoff, dead letter queue, fallback humano, saga log
195
+ - [ ] **Implementación en el modelo de Forge**: saga orchestrator como feature independiente (ej. "checkout-saga"), saga participantes usan eventos de dominio + adapters
196
+ - [ ] **Conexión con reglas R8 y R5**: cómo las sagas coordinan features sin importarlas directamente, eventos como contrato en shared/
197
+ - [ ] **Testing de sagas**: unit (participante individual), integration (flujo completo con mock), resilience (fallos y compensaciones)
198
+ - [ ] **Anti-patrones**: saga sin compensación (irreversible), orchestrator con lógica de negocio, coreografía sin trazabilidad, timeout único
199
+ - [ ] **Ejemplo**: saga de checkout (Inventory → Payment → Shipping) con orquestación y compensación por fallo de pago
200
+
201
+ ### Criterio de completitud
202
+
203
+ Un desarrollador puede modelar un flujo multi-feature usando sagas sin violar R8, con compensaciones claras, testing cubierto y trazabilidad.
204
+
205
+ ---
206
+
207
+ ## 08 — `transactional-outbox.md`
208
+
209
+ **Propósito:** Garantizar entrega confiable de eventos sin exponer inconsistencias transaccionales.
210
+
211
+ **Depende de:** `events.md`
212
+ **Es usado por:** `sagas.md`, `cqrs.md`, `events.md`
213
+
214
+ ### Secciones obligatorias
215
+
216
+ - [ ] **Problema**: dual-write (escribir en BD + publicar evento) atómico sin 2PC
217
+ - [ ] **Patrón Outbox**: escribir evento en tabla outbox dentro de la misma transacción que la operación de negocio
218
+ - [ ] **Outbox processor (relayer)**: proceso que lee la tabla outbox y publica eventos al message broker
219
+ - [ ] **Garantías**: at-least-once delivery, exactly-once processing con idempotencia
220
+ - [ ] **Implementaciones**: poll-based (relayer periódico), log-based (CDC con Debezium), hybrid
221
+ - [ ] **Integración con el modelo de Forge**: outbox en infra/prisma o infra/mongodb, processor como script/scheduler en platform/scheduler
222
+ - [ ] **Manejo de fallos**: retry con exponential backoff, poison messages, dead letter queue, alertas de outbox stuck
223
+ - [ ] **Idempotencia en consumidores**: deduplicación por event ID, idempotency key
224
+ - [ ] **Conexión con reglas**: outbox es infra que feature escribe mediante su adapter, sin violar R1
225
+ - [ ] **Anti-patrones**: outbox sin cleanup (tabla infinita), processor sin límite de reintentos, eventos sin idempotencia
226
+ - [ ] **Ejemplo**: feature "Orders" escribe pedido + outbox event en misma transacción Prisma → processor publica a RabbitMQ → "Payments" consume
227
+
228
+ ### Criterio de completitud
229
+
230
+ Un feature que publica eventos puede implementar outbox pattern siguiendo el template de Forge, garantizando at-least-once delivery sin riesgo de inconsistencias.
231
+
232
+ ---
233
+
234
+ ## 09 — `idempotency.md`
235
+
236
+ **Propósito:** Garantizar operaciones seguras para retry en APIs, eventos y procesos asíncronos.
237
+
238
+ **Depende de:** `api-design.md`
239
+ **Es usado por:** `api-design.md`, `events.md`, `sagas.md`, `cast.md`
240
+
241
+ ### Secciones obligatorias
242
+
243
+ - [ ] **Definición**: propiedad de una operación que puede aplicarse múltiples veces sin efecto secundario adicional
244
+ - [ ] **Tipos de idempotencia**: natural (GET), por clave (idempotency key), por semántica (last-write-wins)
245
+ - [ ] **Idempotency keys en APIs**: cabecera Idempotency-Key, almacenamiento en BD/cache, deduplicación, respuesta en caché
246
+ - [ ] **Idempotencia en eventos**: event ID como clave, deduplicación en consumidor, exactly-once semantics
247
+ - [ ] **Implementación en el modelo de Forge**: middleware en platform/http, repository en infra/redis, contract en shared/contracts
248
+ - [ ] **Idempotencia en sagas**: cómo cada paso de saga debe ser idempotente para retry seguro
249
+ - [ ] **Manejo de expiración**: TTL de claves de idempotencia, cleanup, conflictos de clave
250
+ - [ ] **Testing de idempotencia**: enviar misma request N veces, verificar resultado único
251
+ - [ ] **Conexión con reglas**: idempotency middleware es platform, repositorio de claves es infra, contracts son shared
252
+ - [ ] **Anti-patrones**: idempotency sin expiración, claves generadas por el servidor, idempotencia en GET, mutex como idempotencia
253
+ - [ ] **Ejemplo**: POST /payments con Idempotency-Key, key almacenada en Redis, respuesta en caché, consumidor de eventos con deduplicación
254
+
255
+ ### Criterio de completitud
256
+
257
+ Cada API de mutación en el feature expone idempotency keys. Cada consumidor de eventos maneja deduplicación. Retry es seguro en toda la cadena.
258
+
259
+ ---
260
+
261
+ ## 10 — `api-versioning.md`
262
+
263
+ **Propósito:** Evolucionar contratos de API sin romper clientes existentes.
264
+
265
+ **Depende de:** `api-design.md`
266
+ **Es usado por:** `api-design.md`, `reforge.md`, `cast.md`
267
+
268
+ ### Secciones obligatorias
269
+
270
+ - [ ] **Estrategias de versionado**: URL path (/v1/), header (Accept: application/vnd.api+json;version=1), content negotiation, query param
271
+ - [ ] **Compatibilidad**: backward compatible (additive changes), breaking changes (removal, rename, type change, required→optional)
272
+ - [ ] **Evolución de OpenAPI**: spec versionada, changelog automático, diff entre versiones
273
+ - [ ] **Versionado en el modelo de Forge**: controllers versionados por feature (features/users/adapters/in/http/v1/, v2/), routes con prefijo
274
+ - [ ] **Deprecación**: cabeceras Sunset, Deprecation, Retirement policy, migración de clientes
275
+ - [ ] **Internal vs Public API**: versionado estricto para pública, semver para interna
276
+ - [ ] **Integration testing multi-versión**: tests que corren contra v1 y v2 simultáneamente
277
+ - [ ] **Conexión con reglas**: ningún controller versionado debe violar R0 (cero lógica de negocio). La lógica vive en use cases
278
+ - [ ] **Anti-patrones**: versionado por "fecha" sin estabilidad, mantener N versiones sin política de muerte, versionado de toda la API en vez de por endpoint
279
+ - [ ] **Ejemplo**: feature "Users" migrando de v1 a v2 con cambio de modelo, controllers separados, deprecación gradual
280
+
281
+ ### Criterio de completitud
282
+
283
+ Un feature puede evolucionar su API de forma segura, con versionado explícito, deprecación controlada, tests multi-versión, y sin tocar la lógica de negocio.
284
+
285
+ ---
286
+
287
+ ## Integración en SKILL.md
288
+
289
+ - [x] Agregar las 10 referencias a la tabla **Module Index** en SKILL.md
290
+ - [x] Agregar entradas de **Command Routing** para los nuevos temas (lenguaje natural → referencia)
291
+ - [ ] Verificar que las referencias existentes que mencionan temas ahora cubiertos (events.md → sagas + outbox, data-patterns.md → CQRS) hagan `Ver: reference/<nueva>.md`
292
+
293
+ ## Templates
294
+
295
+ - [x] Evaluar si `templates/feature/` necesita nuevos templates (saga orchestrator, outbox processor, ACL adapter, CQRS query service)
296
+ - [x] saga-orchestrator.ts.md — orchestrator con compensaciones
297
+ - [x] cqrs-query.ts.md — query service para lecturas separadas
298
+ - [x] acl-repository.ts.md — ACL que implementa repositorio de dominio
299
+ - [x] acl-translator.ts.md — traducción entre DTO externo y entidad de dominio
300
+ - [x] acl-gateway.ts.md — comunicación con sistema externo (HTTP)
301
+ - [x] outbox-repository.ts.md — repositorio de outbox integrado en UnitOfWork
302
+ - [x] outbox-relayer.ts.md — relayer en platform/scheduler
303
+ - [x] domain-event.ts.md — clase base DomainEvent con eventId para deduplicación
304
+ - [ ] Evaluar si `templates/shared/` necesita contratos de idempotencia o de eventos de integración
305
+
306
+ ## Testing
307
+
308
+ - [x] transactional-outbox pattern — 5 tests (entry lifecycle, retry policy, DLQ, required fields, pending detection)
309
+ - [x] idempotency pattern — 5 tests (UUID validation, cached response, separate keys, TTL expiry, method filtering)
310
+ - [x] anti-corruption-layer pattern — 5 tests (external→domain mapping, domain→external mapping, null handling, 404 handling, delegation order)
311
+ - [ ] Prioridad futura: ADR workflow, evolutionary architecture fitness functions
@@ -0,0 +1,41 @@
1
+ # Architecture State
2
+
3
+ - Project Name: <name>
4
+ - Framework: <detectado>
5
+ - Runtime: <detectado>
6
+ - Database: <detectado>
7
+ - ORM: <detectado>
8
+ - DI Strategy: <detectado>
9
+ - Profile: <detectado>
10
+ - Architecture: hexagonal-feature (Platform + Features + Shared + Infra)
11
+ - Last Audit: <fecha> (score: <puntaje>)
12
+
13
+ ## Platform
14
+ - platform/config/
15
+ - platform/server/
16
+ ...
17
+
18
+ ## Features
19
+ - features/users/
20
+ ...
21
+
22
+ ## Shared
23
+ - shared/errors/
24
+ ...
25
+
26
+ ## Infrastructure
27
+ - infra/prisma/
28
+ ...
29
+
30
+ ## Ownership
31
+ - Health: healthy | degraded | critical
32
+ - Score: 0-100
33
+ - Orphans: 0
34
+ - Duplicates: 0
35
+ - Misplaced: 0
36
+
37
+ ## Architecture Graph
38
+ ...
39
+
40
+ ## Dependency Health
41
+ ...
@@ -80,3 +80,9 @@ Se recomienda:
80
80
  3. Priorizar acciones basado en las recomendaciones
81
81
  4. Refactorizar con `reforge`, `temper`, o `smelt`
82
82
  5. Repetir el ciclo
83
+
84
+ ## Ver también
85
+
86
+ - `reference/inspect.md` — el reporte que alimenta el ensayo
87
+ - `reference/adr.md` — ADRs como insumo para las opiniones de cada persona
88
+ - `reference/principles.md` — principios contra los que assay contrasta las decisiones
@@ -0,0 +1,311 @@
1
+ # Bounded Contexts — DDD Estratégico
2
+
3
+ Las features de Forge se corresponden con bounded contexts. Sin esta correspondencia, `src/features/<name>/` son solo directoríos con código agrupado por nombre, no unidades con integridad de dominio.
4
+
5
+ ---
6
+
7
+ ## Fundamentos de DDD Estratégico
8
+
9
+ ### Dominio y Subdominios
10
+
11
+ El **dominio** es el área de actividad que el sistema modela. Se divide en tres tipos de **subdominio**:
12
+
13
+ | Tipo | Características | Ejemplo en e-commerce |
14
+ |---|---|---|
15
+ | **Core** | Ventaja competitiva, complejo, hecho en casa | Pricing engine, recomendaciones |
16
+ | **Supporting** | Necesario pero no diferenciador, puede externalizarse | Inventario, catálogo |
17
+ | **Generic** | Commodity, comprar o usar OSS | Auth, notificaciones, pagos |
18
+
19
+ Un **bounded context** es un límite explícito dentro del cual un modelo de dominio específico es consistente. Fuera del contexto, el mismo término puede tener significado distinto.
20
+
21
+ ```ts
22
+ // En el contexto de "Catalog", Product tiene precio, descripción, imágenes
23
+ // En el contexto de "Inventory", Product tiene SKU, stock, warehouse location
24
+ // En el contexto de "Orders", Product tiene orderLine, quantity, status
25
+ // Son tres modelos distintos para el mismo concepto del mundo real
26
+ ```
27
+
28
+ ### Ubiquitous Language
29
+
30
+ Cada bounded context tiene su propio lenguaje ubicuo, compartido por el equipo de desarrollo y los expertos de negocio.
31
+
32
+ **Reglas del lenguaje ubicuo:**
33
+ - Los nombres de clases, métodos y módulos reflejan el lenguaje del negocio, no el lenguaje técnico
34
+ - No hay traducción entre "lo que el negocio dice" y "lo que el código llama"
35
+ - Si el negocio dice "Order" → la entidad se llama `OrderEntity`, no `OrderRecord` ni `OrderDoc`
36
+ - Si el negocio dice "cancelar pedido" → el caso de uso se llama `CancelOrderUseCase`, no `OrderDeleterService`
37
+ - Las discrepancias de lenguaje entre contexts son señales de límites válidos
38
+
39
+ **Conflicto de lenguaje como herramienta:** cuando dos personas del equipo usan la misma palabra con significado distinto (ej. "cliente" significa "usuario registrado" para marketing y "cuenta corporativa" para billing), hay dos bounded contexts esperando ser descubiertos.
40
+
41
+ ---
42
+
43
+ ## Context Mapping
44
+
45
+ Cada bounded context se relaciona con otros mediante relaciones explícitas. Estos son los 8 patrones del Context Mapping:
46
+
47
+ ### Partnership
48
+
49
+ Dos contexts cooperan para entregar un flujo. Si uno falla, el otro también.
50
+
51
+ ```
52
+ [Orders] ←→ [Inventory]
53
+ ```
54
+
55
+ - Relación bidireccional
56
+ - Coordinación frecuente entre equipos
57
+ - Acoplamiento temporal tolerado
58
+ - Útil para flujos transaccionales críticos (checkout)
59
+
60
+ ### Shared Kernel
61
+
62
+ Comparten un subconjunto pequeño y estable del modelo.
63
+
64
+ ```
65
+ [Orders] ← kernel: Customer, Money → [Billing]
66
+ ```
67
+
68
+ - El kernel compartido está en `src/shared/contracts/`
69
+ - Solo datos, no lógica de negocio
70
+ - El kernel se mantiene por acuerdo entre equipos
71
+ - Cambios requieren coordinación y tests
72
+ - Si crece demasiado, es señal de que los contexts deberían fusionarse
73
+
74
+ ### Customer-Supplier
75
+
76
+ Un contexto upstream provee datos que el downstream consume. El upstream gana.
77
+
78
+ ```
79
+ [CRM] → [Marketing] (CRM dicta el contrato)
80
+ ```
81
+
82
+ - Upstream (supplier) define el contrato
83
+ - Downstream (customer) se adapta
84
+ - El downstream debe implementar una ACL si el upstream no cubre sus necesidades
85
+ - Relación unidireccional
86
+
87
+ ### Conformist
88
+
89
+ El downstream acepta el modelo del upstream sin cuestionarlo.
90
+
91
+ ```
92
+ [SAP] → [Reporting] (Reporting se adapta al modelo de SAP)
93
+ ```
94
+
95
+ - Sin traducción: el downstream usa el modelo del upstream directamente
96
+ - Útil cuando el upstream es un sistema externo commodity
97
+ - Riesgo de corrupción del modelo de dominio downstream si el upstream cambia
98
+
99
+ ### Anti-Corruption Layer (ACL)
100
+
101
+ El downstream protege su modelo con una capa de traducción.
102
+
103
+ ```
104
+ [CRM Legacy] → [ACL] → [Orders]
105
+ ```
106
+
107
+ - La ACL traduce del modelo legacy al modelo de dominio de Orders
108
+ - Ver `reference/anti-corruption-layer.md`
109
+ - Patrón obligatorio cuando se integra un sistema legacy o externo en un core domain
110
+
111
+ ### Open-Host Service
112
+
113
+ El upstream expone un protocolo/shareable al que los downstreams se suscriben.
114
+
115
+ ```
116
+ [Catalog] ── OHS (Published Language) ──→ [Search]
117
+ ──→ [Recommendations]
118
+ ──→ [Pricing]
119
+ ```
120
+
121
+ - El upstream publica un Published Language (API, eventos, contratos compartidos)
122
+ - Múltiples downstreams consumen sin coordinar entre sí
123
+ - Es la relación ideal para la capa `adapter/out/` de una feature exponiendo eventos
124
+
125
+ ### Published Language
126
+
127
+ El lenguaje compartido que el OHS usa. Puede ser:
128
+ - Contratos TypeScript en `src/shared/contracts/`
129
+ - Eventos de dominio con schema versionado
130
+ - OpenAPI spec como contrato HTTP
131
+ - Protobuf / Avro schemas
132
+
133
+ Los contratos publicados deben ser:
134
+ - Versionados (`src/shared/contracts/catalog/v1/`, `v2/`)
135
+ - Inmutables una vez publicados
136
+ - Documentados con ejemplos
137
+ - Validados con tests de compatibilidad
138
+
139
+ ### Separate Ways
140
+
141
+ Dos contexts no tienen relación. Cada uno modela su solución independientemente.
142
+
143
+ ```
144
+ [Notifications] [Analytics]
145
+ (no se hablan)
146
+ ```
147
+
148
+ - Válido cuando no hay solapamiento funcional
149
+ - Forzado por R8 (no imports directos entre features): por defecto, toda feature que no comparte contratos está en Separate Ways con las demás
150
+
151
+ ---
152
+
153
+ ## Identificación de Bounded Contexts
154
+
155
+ ### Heurísticas prácticas
156
+
157
+ | Señal | Pregunta guía |
158
+ |---|---|
159
+ | **Equipo** | ¿Otro equipo podría ser dueño de esto? |
160
+ | **Lenguaje** | ¿Usan las mismas palabras con el mismo significado? |
161
+ | **Modelo** | ¿La misma entidad tiene atributos o comportamientos distintos? |
162
+ | **Frecuencia de cambio** | ¿Una parte del sistema cambia a ritmo distinto que otra? |
163
+ | **Base de datos** | ¿Podría tener su propio schema o base de datos? |
164
+ | **Deploy** | ¿Podría deployarse independientemente? |
165
+ | **Fallo** | ¿Un fallo aquí no debería afectar a otras partes? |
166
+
167
+ ### Regla práctica de Forge
168
+
169
+ Si puedes nombrar un directorio `src/features/<name>/` y describir qué hace sin usar términos de otra feature, tienes un bounded context candidato.
170
+
171
+ Si necesitas decir "esto es parte de X pero usa el modelo de Y" o "comparte la BD con Z", el context mapping está mal definido.
172
+
173
+ ---
174
+
175
+ ## Mapeo Visual
176
+
177
+ Un diagrama de contextos muestra los bounded contexts como cajas y las relaciones como flechas etiquetadas.
178
+
179
+ ```
180
+ ┌──────────────────────────────────────────────────────┐
181
+ │ E-Commerce System │
182
+ │ │
183
+ │ ┌──────────┐ SK ┌──────────┐ OHS ┌──────────┐ │
184
+ │ │ Orders │◄────►│ Catalog ├────────►│ Search │ │
185
+ │ └────┬─────┘ └──────────┘ └──────────┘ │
186
+ │ │ │ │
187
+ │ │PS │PL │
188
+ │ ▼ ▼ │
189
+ │ ┌──────────┐ ┌──────────┐ │
190
+ │ │Inventory │ │ Pricing │ │
191
+ │ └──────────┘ └──────────┘ │
192
+ │ │ │
193
+ │ │CS │
194
+ │ ▼ │
195
+ │ ┌──────────┐ │
196
+ │ │Shipping │ │
197
+ │ └──────────┘ │
198
+ │ │
199
+ │ ┌──────────┐ SW ┌──────────┐ │
200
+ │ │ Auth │ │Analytics │ │
201
+ │ └──────────┘ └──────────┘ │
202
+ └────────────────────────────────────────────────────────┘
203
+
204
+ Leyenda:
205
+ SK = Shared Kernel
206
+ OHS = Open-Host Service (vía Published Language)
207
+ PS = Partnership
208
+ PL = Published Language (unidirectional OHS)
209
+ CS = Customer-Supplier
210
+ SW = Separate Ways
211
+ ```
212
+
213
+ ---
214
+
215
+ ## Relación con el Modelo de Forge
216
+
217
+ Cada `src/features/<name>/` mapea a (parte de) un bounded context.
218
+
219
+ | Regla | Relación con bounded contexts |
220
+ |---|---|
221
+ | **R8** (no cross-feature imports) | Enforces Separate Ways entre contexts. Si dos features necesitan comunicarse, debe ser vía Published Language (contratos en shared/) o Partnership (interfaces inyectadas). |
222
+ | **R9** (no ciclos) | Los ciclos entre contexts indican que el context mapping está mal: dos contexts que se necesitan mutuamente deberían fusionarse o introducir un tercer contexto mediador. |
223
+ | **R2** (platform → feature) | Platform es un contexto genérico que sirve a todos. No debe invertirse. |
224
+ | **R4** (shared → infra) | Shared kernel debe ser puro. Si shared necesita infra, el kernel está contaminado. |
225
+
226
+ ### La feature como bounded context implementado
227
+
228
+ ```
229
+ src/features/orders/
230
+ domain/ ← Modelo del contexto Orders
231
+ entities/
232
+ events/
233
+ repositories/ ← Puertos
234
+ application/
235
+ use-cases/ ← Flujos del contexto Orders
236
+ mappers/ ← Traducción dentro del contexto
237
+ adapters/
238
+ in/http/ ← Entrada: Open-Host Service (API REST)
239
+ out/persistence/ ← Salida: repositorio concreto
240
+ out/events/ ← Salida: eventos publicados (Published Language)
241
+ ```
242
+
243
+ ---
244
+
245
+ ## Anti-patrones
246
+
247
+ | Anti-patrón | Problema | Solución |
248
+ |---|---|---|
249
+ | **Contexto gigante (Orphan Core)** | Un solo contexto contiene todo el core domain. No hay límites. | Dividir por subdominio. Si duele partir, empezar por los flujos que cambian a ritmo distinto. |
250
+ | **Contexto fantasma** | Un bounded context declarado que no tiene modelo propio. Solo llama APIs de otros contexts. | Fusionar con el contexto que realmente tiene el modelo o eliminarlo. |
251
+ | **Contexto sin lenguaje** | El código usa nombres técnicos (UserService, DataManager, TransactionHelper). No hay rastro del lenguaje del negocio. | Hacer event storming con el equipo de negocio. Renombrar todo para reflejar el lenguaje ubícuo. |
252
+ | **Shared Kernel gigante** | Los contratos compartidos crecen sin control porque es más fácil poner algo en shared que diseñar el límite. | Forzar revisión en cada PR de shared/contracts/. Shared kernel debe ser minimalista y estable. |
253
+ | **Contexto anémico** | Un contexto que solo tiene CRUD y getters/setters. Sin reglas de negocio ni invariantes. | Preguntar: ¿qué reglas de negocio existen aquí? Si la respuesta es "ninguna", probablemente el contexto debería ser un subdominio genérico resuelto con infraestructura (CRUD framework). |
254
+
255
+ ---
256
+
257
+ ## Ejemplo Completo
258
+
259
+ Sistema de e-commerce con 4 bounded contexts:
260
+
261
+ **Catalog** (Supporting)
262
+ - Modelo: `Product`, `Category`, `Price`
263
+ - Lenguaje: producto, categoría, precio de lista, variante
264
+ - Persistencia: PostgreSQL
265
+ - Relaciones: OHS → Search (Published Language), CS → Pricing (provee precios base)
266
+
267
+ **Orders** (Core)
268
+ - Modelo: `Order`, `OrderLine`, `Payment`, `Shipment`
269
+ - Lenguaje: pedido, línea, pago, envío, cancelación, reembolso
270
+ - Persistencia: PostgreSQL (propio schema)
271
+ - Relaciones: Partnership ↔ Inventory, CS → Shipping, consume eventos de Catalog (Published Language)
272
+
273
+ **Inventory** (Supporting)
274
+ - Modelo: `Stock`, `Warehouse`, `Movement`
275
+ - Lenguaje: stock, almacén, entrada, salida, reserva
276
+ - Persistencia: PostgreSQL
277
+ - Relaciones: Partnership ↔ Orders, CS → Shipping (provee peso/volumen)
278
+
279
+ **Search** (Generic, con Elasticsearch)
280
+ - Modelo: `SearchableProduct` (read model desnormalizado de Catalog)
281
+ - Lenguaje: búsqueda, filtro, índice, relevancia
282
+ - Persistencia: Elasticsearch
283
+ - Relaciones: consume OHS de Catalog
284
+ - No tiene relaciones de salida: es puramente un contexto de lectura
285
+
286
+ ```
287
+ Decisiones arquitectónicas reflejadas:
288
+ - Catalog y Search están separados porque tienen distinta frecuencia de cambio y stack
289
+ - Orders e Inventory en Partnership porque el checkout necesita coordinación transaccional
290
+ - Catalog como OHS permite que Search, Pricing y Recommendations consuman sin acoplar
291
+ - No hay ACL porque ningún legacy está involucrado (todos los contexts son nuevos)
292
+ ```
293
+
294
+ ---
295
+
296
+ ## Conexión con Forge
297
+
298
+ | Comando | Acción |
299
+ |---|---|
300
+ | `forge cast` | Crea una nueva feature que se corresponde con un nuevo bounded context o subdomino |
301
+ | `forge inspect` | Detecta violaciones de límites entre contexts (R8, R9) |
302
+ | `forge graph` | Visualiza los bounded contexts y sus relaciones como grafo arquitectónico |
303
+ | `forge relocate` | Migra código entre contexts o extrae un contexto de un monolito legacy |
304
+ | `forge assay` | Evalúa cualitativamente la integridad de los límites entre contexts |
305
+
306
+ ## Ver también
307
+
308
+ - `reference/modular-monolith.md` — contexto como unidad del monolith
309
+ - `reference/anti-corruption-layer.md` — protección de límites entre contexts
310
+ - `reference/cqrs.md` — separación command/query dentro de un context
311
+ - `reference/sagas.md` — coordinación entre contexts