@ronaldjdevfs/forge 1.3.3 → 1.3.6

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 (31) hide show
  1. package/README.md +18 -10
  2. package/package.json +1 -1
  3. package/skills/forge/SKILL.md +13 -2
  4. package/skills/forge/command/forge.md +22 -22
  5. package/skills/forge/reference/assay.md +10 -10
  6. package/skills/forge/reference/cast.md +43 -0
  7. package/skills/forge/reference/chain.md +3 -3
  8. package/skills/forge/reference/evolutionary-architecture.md +2 -2
  9. package/skills/forge/reference/inspect.md +3 -3
  10. package/skills/forge/reference/patterns.md +60 -1
  11. package/skills/forge/reference/principles.md +2 -0
  12. package/skills/forge/reference/quench.md +3 -3
  13. package/skills/forge/reference/reforge.md +30 -8
  14. package/skills/forge/reference/relocate.md +25 -3
  15. package/skills/forge/scripts/armorer.mjs +21 -0
  16. package/skills/forge/scripts/detect.mjs +188 -0
  17. package/skills/forge/scripts/forgeSmith.mjs +85 -0
  18. package/skills/forge/scripts/inspect.mjs +4 -0
  19. package/skills/forge/scripts/registry/rules.mjs +25 -0
  20. package/skills/forge/scripts/rename.mjs +9 -0
  21. package/skills/forge/scripts/update.mjs +1 -1
  22. package/skills/forge/templates/feature/controller.ts.md +13 -5
  23. package/skills/forge/templates/feature/di.ts.md +33 -0
  24. package/skills/forge/templates/feature/mapper.ts.md +5 -0
  25. package/skills/forge/templates/feature/repository-impl.ts.md +6 -1
  26. package/skills/forge/templates/feature/routes.ts.md +5 -0
  27. package/skills/forge/templates/feature/schema.ts.md +4 -0
  28. package/skills/forge/templates/feature/test.ts.md +68 -0
  29. package/skills/forge/templates/feature/use-case.ts.md +5 -0
  30. package/skills/forge/tests/core.test.mjs +3 -2
  31. package/src/cli.js +21 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <img src="favicon.svg" alt="Forge Logo" width="100" height="100">
2
2
 
3
- > **v1.3.2** — Domain Subdirectory Structure & Port Support
3
+ > **v1.3.6** — Multi-Agent Path Resolution Fix
4
4
 
5
5
  ## Forge — Backend Architecture Operating System
6
6
 
@@ -29,10 +29,10 @@ Los proyectos backend degeneran en código acoplado porque la infraestructura t
29
29
  |-----------|---------|-------------|
30
30
  | **Proyecto nuevo** | `forge` | Inicializa platform/features/shared/infra, detecta stack, crea `ARCHITECTURE.md` |
31
31
  | **Crear un nuevo dominio** | `cast` | Genera un feature completo desde cero (verifica platform/shared/infra primero) |
32
- | **Auditar arquitectura** | `inspect` | Evaluación completa 110pts → 0-100 con ownership, platform y grafo |
32
+ | **Auditar arquitectura** | `inspect` | Evaluación completa 180pts → 0-100 con ownership, platform, grafo e import conventions |
33
33
  | **Migrar código legacy** | `relocate` | Traslada código a platform/, shared/, infra/ o features/ |
34
34
  | **Refactorizar** | `reforge` | Reestructura features o componentes multi-capa |
35
- | **Validar reglas** | `quench` | Verifica 9 reglas arquitectónicas (R1-R9) |
35
+ | **Validar reglas** | `quench` | Verifica 12 reglas arquitectónicas (R1-R12) |
36
36
  | **Endurecer DI** | `temper` | Aplica inyección por constructor, elimina service locators |
37
37
  | **Analizar dependencias** | `chain` | Grafo multi-capa (platform, features, shared, infra), orden topológico, ciclos |
38
38
  | **Documentar** | `inscribe` | Genera/actualiza `ARCHITECTURE.md` con métricas, ownership y violaciones |
@@ -72,16 +72,20 @@ src/features/<name>/
72
72
 
73
73
  ### `inspect` — Auditoría arquitectónica
74
74
 
75
- Evalúa 6 categorías contra un máximo de 110 puntos (normalizado a 0-100):
75
+ Evalúa 10 categorías contra un máximo de 180 puntos (normalizado a 0-100):
76
76
 
77
77
  | Categoría | Puntos | Qué mide |
78
78
  |-----------|--------|----------|
79
- | Structure | 20 | Organización de platform, features, shared, infra |
80
- | Layers | 20 | Aislamiento entre capas, imports prohibidos |
79
+ | Structure | 30 | Organización de platform, features, shared, infra |
80
+ | Layers | 25 | Aislamiento entre capas, imports prohibidos |
81
+ | Decorators | 20 | Decoradores @injectable()/@inject() en use cases, controllers, repos |
81
82
  | Ownership | 20 | Huérfanos, duplicados, mal ubicados |
82
83
  | Platform | 15 | Completitud del backbone técnico (config, server, logger, di, etc.) |
83
84
  | Dependencies | 15 | Dirección de dependencias, ciclos, edges inválidos |
84
85
  | Graph | 20 | Salud del grafo arquitectónico, risk score |
86
+ | Custom Rules | 5 | Reglas personalizadas desde `.forge/rules.json` |
87
+ | Naming | 10 | Convenciones de nomenclatura PascalCase/kebab |
88
+ | Import Conventions | 20 | R10-R12: bare specifiers, extensión .ts, bootstrap.di.js |
85
89
 
86
90
  **Resultado**: Score 0-100 con grado A-F y severidades por cada violación.
87
91
 
@@ -116,6 +120,10 @@ Ejecuta 9 reglas arquitectónicas (R1-R9) con severidad:
116
120
  | R7 | `infra → feature` (prohibido) | WARNING |
117
121
  | R8 | Cross-feature direct imports | ERROR |
118
122
  | R9 | Ciclos de dependencia | ERROR |
123
+ | R10 | Bare specifiers en imports locales | ERROR |
124
+ | R11 | Extensión `.ts` en imports (debe ser `.js`) | ERROR |
125
+ | R12 | Import a `bootstrap.di.js` (no existe) | CRITICAL |
126
+ | R12b | `registerSingleton` con model() de Mongoose | CRITICAL |
119
127
 
120
128
  ### `temper` — Endurecimiento de DI
121
129
 
@@ -311,8 +319,8 @@ Ver `reference/patterns.md` para el detalle completo.
311
319
  - **4 dominios arquitectónicos**: Platform (backbone), Features (negocio), Shared (código puro), Infra (implementaciones)
312
320
  - **Architecture graph como fuente de verdad**: 6 tipos de nodo (platform, feature, shared, infra, domain, adapter), 9 reglas (R1-R9), risk score y dependency health
313
321
  - **Ownership automático**: Detección de huérfanos, duplicados, componentes mal ubicados y sugerencias de reubicación
314
- - **Scoring arquitectónico**: 110 puntos en 6 categorías, normalizado a 0-100 con grado A-F
315
- - **5 perfiles tecnológicos predefinidos**: Express + MongoDB, Express + PostgreSQL, Express + Prisma, Fastify + Prisma, NestJS + Prisma
322
+ - **Scoring arquitectónico**: 180 puntos en 10 categorías, normalizado a 0-100 con grado A-F
323
+ - **10 perfiles tecnológicos predefinidos**: Express + MongoDB, Express + PostgreSQL, Express + Prisma, Express + Drizzle, Fastify + MongoDB, Fastify + PostgreSQL, Fastify + Prisma, NestJS + MongoDB, NestJS + PostgreSQL, NestJS + Prisma
316
324
  - **Boot sequence obligatoria**: 9 pasos que garantizan contexto completo antes de cualquier acción
317
325
  - **Documentación automática**: `ARCHITECTURE.md` vivo que se actualiza tras cada operación
318
326
  - **Sin dependencias runtime**: Solo Node ≥ 18, todo corre con scripts ESM propios
@@ -358,7 +366,7 @@ Donde vive toda la inteligencia arquitectónica:
358
366
  | `scripts/profile.mjs` | Matchea stack contra perfiles conocidos o sintetiza uno genérico |
359
367
  | `scripts/graph.mjs` | Grafo completo: 6 tipos de nodo, 4 capas, 9 reglas (R1-R9), risk score, dependency health |
360
368
  | `scripts/chain.mjs` | Grafo multi-capa (platform, features, shared, infra) con orden topológico |
361
- | `scripts/detect.mjs` | Validación de reglas R1-R9 con inline ignores y `--fix` |
369
+ | `scripts/detect.mjs` | Validación de reglas R1-R12 con inline ignores, `--fix` e import conventions |
362
370
  | `scripts/inspect.mjs` | Orquesta auditoría completa con reporte coloreado |
363
371
  | `scripts/architecture.mjs` | Genera/actualiza `ARCHITECTURE.md` vivo |
364
372
  | `scripts/bootstrap.mjs` | Inicializa platform/shared/infra según perfil (interno) |
@@ -385,7 +393,7 @@ Donde vive toda la inteligencia arquitectónica:
385
393
  | `reference/assay.md` | Documentación del comando assay |
386
394
  | `reference/hooks.md` | Documentación del sistema de hooks |
387
395
  | `profiles/` | 10 perfiles tecnológicos detallados |
388
- | `templates/feature/` | 17 templates TypeScript para features |
396
+ | `templates/feature/` | 19 templates TypeScript para features |
389
397
  | `templates/platform/` | 6 templates para componentes de platform |
390
398
  | `templates/shared/` | 4 templates para shared (errors, contracts, types, utils) |
391
399
  | `templates/infra/` | 4 templates para infra (prisma, mongodb, redis, mail) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ronaldjdevfs/forge",
3
- "version": "1.3.3",
3
+ "version": "1.3.6",
4
4
  "description": "Forge — Architecture Operating System for backend systems. Arquitectura Hexagonal, DDD pragmático y vertical slices.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -75,7 +75,7 @@ En esencia:
75
75
  ANTES de cualquier acción, Forge DEBE ejecutar `forge-boot.mjs` con la profundidad adecuada al comando:
76
76
 
77
77
  ```bash
78
- boot=$(node .opencode/skills/forge/scripts/forge-boot.mjs --depth <depth> --json 2>/dev/null)
78
+ boot=$(node {{AGENT_PATH}}/scripts/forge-boot.mjs --depth <depth> --json 2>/dev/null)
79
79
  ```
80
80
 
81
81
  La profundidad (`--depth`) depende del comando (ver Execution Flow):
@@ -150,6 +150,17 @@ El boot usa caché de `.forge/cache/`. Si los archivos `src/` no cambiaron, los
150
150
  - Si `ARCHITECTURE.md` está desactualizado (fecha de auditoría > 7 días), sugerir `forge inscribe`.
151
151
  - Todos los resultados se muestran con severidades: `[CRITICAL]`, `[ERROR]`, `[WARNING]`, `[INFO]`, `[SUGGESTION]`.
152
152
 
153
+ ### ⚠️ Regla de Platform: Sin lógica de dominio
154
+
155
+ Cuando `reforge` o `relocate` operen sobre `src/platform/`, verificar que los archivos movidos/creados no contengan lógica de dominio:
156
+
157
+ - **No** mover entidades, value objects, casos de uso, mappers de dominio, schemas de entidades, repositorios de dominio a `platform/`
158
+ - **No** crear archivos con sufijos `.entity.ts`, `.uc.ts`, `.mapper.ts`, `.repository.ts` (domain), `.port.ts` dentro de `platform/`
159
+ - **No** importar desde `features/` dentro de `platform/` (viola R2)
160
+ - Si un componente tiene imports hacia `domain/` o `features/`, pertenece a un feature, no a platform
161
+
162
+ Platform solo acepta: config, database, http, server, logger, cache, security, events, scheduler, observability, di.
163
+
153
164
  ### Inline Ignores
154
165
 
155
166
  Forge soporta comentarios inline para excepcionar violaciones línea por línea:
@@ -182,7 +193,7 @@ El agente DEBE leer este archivo al inicio de cada interacción y actualizarlo a
182
193
  Forge incluye tests unitarios con `node:test` (sin dependencias externas).
183
194
 
184
195
  ```bash
185
- node --test .opencode/skills/forge/tests/core.test.mjs
196
+ node --test {{AGENT_PATH}}/tests/core.test.mjs
186
197
  ```
187
198
 
188
199
  | Módulo | Tests | Descripción |
@@ -30,13 +30,13 @@ Si el subcomando NO tiene flags en $ARGUMENTS y tiene flags disponibles (ver tab
30
30
  Inicializa el proyecto arquitectónicamente. Ejecuta context + bootstrap + profile + armorer + graph + chain + inscribe.
31
31
 
32
32
  ```
33
- node .opencode/skills/forge/scripts/context.mjs
34
- node .opencode/skills/forge/scripts/bootstrap.mjs
35
- node .opencode/skills/forge/scripts/profile.mjs
36
- node .opencode/skills/forge/scripts/armorer.mjs
37
- node .opencode/skills/forge/scripts/graph.mjs
38
- node .opencode/skills/forge/scripts/chain.mjs
39
- node .opencode/skills/forge/scripts/architecture.mjs
33
+ node {{AGENT_PATH}}/scripts/context.mjs
34
+ node {{AGENT_PATH}}/scripts/bootstrap.mjs
35
+ node {{AGENT_PATH}}/scripts/profile.mjs
36
+ node {{AGENT_PATH}}/scripts/armorer.mjs
37
+ node {{AGENT_PATH}}/scripts/graph.mjs
38
+ node {{AGENT_PATH}}/scripts/chain.mjs
39
+ node {{AGENT_PATH}}/scripts/architecture.mjs
40
40
  ```
41
41
 
42
42
  ### cast
@@ -52,7 +52,7 @@ Migra un feature existente. Puede targetizar platform/, shared/, infra/ o featur
52
52
  Genera ARCHITECTURE.md con grafo arquitectónico, ownership y platform.
53
53
 
54
54
  ```
55
- node .opencode/skills/forge/scripts/architecture.mjs
55
+ node {{AGENT_PATH}}/scripts/architecture.mjs
56
56
  ```
57
57
 
58
58
  ### graph
@@ -60,13 +60,13 @@ node .opencode/skills/forge/scripts/architecture.mjs
60
60
  Construye el grafo arquitectónico del proyecto (4 capas: platform, feature, shared, infra) con reglas R1-R9.
61
61
 
62
62
  ```
63
- node .opencode/skills/forge/scripts/graph.mjs
63
+ node {{AGENT_PATH}}/scripts/graph.mjs
64
64
  ```
65
65
 
66
66
  Para salida JSON:
67
67
 
68
68
  ```
69
- node .opencode/skills/forge/scripts/graph.mjs --json
69
+ node {{AGENT_PATH}}/scripts/graph.mjs --json
70
70
  ```
71
71
 
72
72
  ### smelt
@@ -78,7 +78,7 @@ Extrae código reutilizable a shared/ (solo código puro, sin dependencias infra
78
78
  Inicializa platform, shared e infra layers (uso interno, se ejecuta automáticamente).
79
79
 
80
80
  ```
81
- node .opencode/skills/forge/scripts/bootstrap.mjs
81
+ node {{AGENT_PATH}}/scripts/bootstrap.mjs
82
82
  ```
83
83
 
84
84
  ## Evaluate
@@ -88,13 +88,13 @@ node .opencode/skills/forge/scripts/bootstrap.mjs
88
88
  Audita la conformidad arquitectónica completa. 6 categorías: structure(20), layers(20), ownership(20), platform(15), dependencies(15), graph(20).
89
89
 
90
90
  ```
91
- node .opencode/skills/forge/scripts/inspect.mjs
91
+ node {{AGENT_PATH}}/scripts/inspect.mjs
92
92
  ```
93
93
 
94
94
  Para salida JSON:
95
95
 
96
96
  ```
97
- node .opencode/skills/forge/scripts/inspect.mjs --json
97
+ node {{AGENT_PATH}}/scripts/inspect.mjs --json
98
98
  ```
99
99
 
100
100
  ### assay
@@ -102,16 +102,16 @@ node .opencode/skills/forge/scripts/inspect.mjs --json
102
102
  Ensayo arquitectónico multi-persona. Interpretación cualitativa del audit desde 5 perspectivas (Bezos, Fowler, Hacker, PM, Arquitecta Senior).
103
103
 
104
104
  ```
105
- node .opencode/skills/forge/scripts/assay.mjs
105
+ node {{AGENT_PATH}}/scripts/assay.mjs
106
106
  ```
107
107
 
108
108
  Filtros:
109
109
 
110
110
  ```
111
- node .opencode/skills/forge/scripts/assay.mjs --persona=bezos
112
- node .opencode/skills/forge/scripts/assay.mjs --json
113
- node .opencode/skills/forge/scripts/assay.mjs --save
114
- node .opencode/skills/forge/scripts/assay.mjs history
111
+ node {{AGENT_PATH}}/scripts/assay.mjs --persona=bezos
112
+ node {{AGENT_PATH}}/scripts/assay.mjs --json
113
+ node {{AGENT_PATH}}/scripts/assay.mjs --save
114
+ node {{AGENT_PATH}}/scripts/assay.mjs history
115
115
  ```
116
116
 
117
117
  ### quench
@@ -119,7 +119,7 @@ node .opencode/skills/forge/scripts/assay.mjs history
119
119
  Valida reglas arquitectónicas R1-R9.
120
120
 
121
121
  ```
122
- node .opencode/skills/forge/scripts/detect.mjs
122
+ node {{AGENT_PATH}}/scripts/detect.mjs
123
123
  ```
124
124
 
125
125
  ### chain
@@ -127,13 +127,13 @@ node .opencode/skills/forge/scripts/detect.mjs
127
127
  Orden topológico de dependencias multi-capa (platform, features, shared, infra).
128
128
 
129
129
  ```
130
- node .opencode/skills/forge/scripts/chain.mjs
130
+ node {{AGENT_PATH}}/scripts/chain.mjs
131
131
  ```
132
132
 
133
133
  Para salida JSON:
134
134
 
135
135
  ```
136
- node .opencode/skills/forge/scripts/chain.mjs --json
136
+ node {{AGENT_PATH}}/scripts/chain.mjs --json
137
137
  ```
138
138
 
139
139
  ### armorer
@@ -141,7 +141,7 @@ node .opencode/skills/forge/scripts/chain.mjs --json
141
141
  Reporte de ownership: huérfanos, duplicados, componentes mal ubicados.
142
142
 
143
143
  ```
144
- node .opencode/skills/forge/scripts/armorer.mjs
144
+ node {{AGENT_PATH}}/scripts/armorer.mjs
145
145
  ```
146
146
 
147
147
  ## Refine
@@ -23,26 +23,26 @@ Genera un **ensayo arquitectónico multi-persona** que evalúa el estado actual
23
23
 
24
24
  ```bash
25
25
  # Ensayo completo con todas las personas
26
- node .opencode/skills/forge/scripts/assay.mjs
26
+ node {{AGENT_PATH}}/scripts/assay.mjs
27
27
 
28
28
  # Solo la opinión de una persona
29
- node .opencode/skills/forge/scripts/assay.mjs --persona=bezos
30
- node .opencode/skills/forge/scripts/assay.mjs --persona=fowler
31
- node .opencode/skills/forge/scripts/assay.mjs --persona=hacker
32
- node .opencode/skills/forge/scripts/assay.mjs --persona=pm
33
- node .opencode/skills/forge/scripts/assay.mjs --persona=senior
29
+ node {{AGENT_PATH}}/scripts/assay.mjs --persona=bezos
30
+ node {{AGENT_PATH}}/scripts/assay.mjs --persona=fowler
31
+ node {{AGENT_PATH}}/scripts/assay.mjs --persona=hacker
32
+ node {{AGENT_PATH}}/scripts/assay.mjs --persona=pm
33
+ node {{AGENT_PATH}}/scripts/assay.mjs --persona=senior
34
34
 
35
35
  # Salida JSON (para consumo por herramientas)
36
- node .opencode/skills/forge/scripts/assay.mjs --json
36
+ node {{AGENT_PATH}}/scripts/assay.mjs --json
37
37
 
38
38
  # Persistir ensayo en .forge/assay/
39
- node .opencode/skills/forge/scripts/assay.mjs --save
39
+ node {{AGENT_PATH}}/scripts/assay.mjs --save
40
40
 
41
41
  # Ver historial de ensayos
42
- node .opencode/skills/forge/scripts/assay.mjs history
42
+ node {{AGENT_PATH}}/scripts/assay.mjs history
43
43
 
44
44
  # Leer un ensayo previo
45
- node .opencode/skills/forge/scripts/assay.mjs read assay-2026-06-25T00-00-00.md
45
+ node {{AGENT_PATH}}/scripts/assay.mjs read assay-2026-06-25T00-00-00.md
46
46
  ```
47
47
 
48
48
  ## Formato de salida
@@ -143,6 +143,49 @@ Usar el perfil detectado para determinar:
143
143
  - Convenciones de imports (rutas relativas vs alias)
144
144
  - Componentes de platform a usar (config, logger, http, database)
145
145
 
146
+ ## ⚠️ Post-Cast: Entity Discovery
147
+
148
+ Antes de crear `<Name>.entity.ts`, verificar si la entidad ya existe como entidad compartida:
149
+
150
+ 1. **Buscar en `src/platform/domain/entities/<Name>.ts`** — si existe, NO crear entidad local
151
+ 2. **Si es compartida**: usar `@/domain/entities/<Name>.js` en vez de path relativo en todos los templates
152
+ 3. **Verificar también** `src/shared/contracts/` por interfaces/DTOs existentes
153
+
154
+ Regla: si la entidad vive fuera del feature, todos los imports deben usar path alias `@/domain/`, no `../../`.
155
+
156
+ ## ⚠️ Post-Cast: DI Wiring
157
+
158
+ Después de crear los archivos del feature, generar `di.ts` siguiendo el template `templates/feature/di.ts.md`:
159
+
160
+ 1. **Feature con DI propia**: crear `src/features/<name>/di.ts` usando el template
161
+ 2. **Feature SIN DI propia**: si ya existe `src/platform/setting/dependencies/<name>.di.js`, los controllers deben importar desde allí en vez de `bootstrap.di.js`
162
+ 3. **Controllers**: asegurar que el import en el controller apunte a `@/setting/dependencies/<name>.di.js` o `./di.js`, NUNCA a `bootstrap.di.js`
163
+ 4. **Mongoose model()**: si el schema exporta `export default model()` (objeto, no clase), el DI debe usar `container.register(..., { useValue: ... })`, NO `registerSingleton`
164
+
165
+ ## ⚠️ Post-Cast: Tests
166
+
167
+ Después del scaffold, generar tests unitarios para cada use case siguiendo `templates/feature/test.ts.md`:
168
+
169
+ 1. Crear `src/features/<name>/__tests__/Create<Name>.test.ts`
170
+ 2. Usar `node:test` (sin dependencias externas)
171
+ 3. Convenciones de test:
172
+ - Extension `.js` en imports (no `.ts`)
173
+ - `as const` para literales de union types: `status: "activo" as const`
174
+ - `result!` (non-null assertion) cuando execute() retorna `T | null`
175
+ - `(result as any)._id` si `_id` no existe en el tipo de dominio
176
+
177
+ ## ⚠️ Post-Cast: Import Validation Checklist
178
+
179
+ Antes de dar por terminado el feature, verificar CADA archivo generado:
180
+
181
+ - [ ] Todos los imports locales usan prefijo `./` o `../` — sin bare specifiers (`import X from "domain/..."` ❌)
182
+ - [ ] Todos los imports tienen extensión `.js` — sin extensión `.ts`
183
+ - [ ] Entidades compartidas usan `@/domain/` — sin paths relativos rotos
184
+ - [ ] Controllers importan desde `di.ts` o `@/setting/dependencies/` — no desde `bootstrap.di.js`
185
+ - [ ] Nombres de método del controller coinciden con los de la ruta (ej: `createHandler` en controller → `controller.createHandler` en routes)
186
+ - [ ] DI usa `register({ useValue })` para modelos Mongoose — no `registerSingleton`
187
+ - [ ] Tests: `.js` extension, `as const`, `!`, `as any` para _id
188
+
146
189
  ## Post-creación
147
190
 
148
191
  - `forge quench` — verificar que no hay violaciones
@@ -54,13 +54,13 @@ container.registerSingleton<ICreditRepository>(
54
54
 
55
55
  ```bash
56
56
  # Grafo de dependencias entre features (API legacy)
57
- node .opencode/skills/forge/scripts/chain.mjs
57
+ node {{AGENT_PATH}}/scripts/chain.mjs
58
58
 
59
59
  # Grafo arquitectónico completo (nodos, edges, violaciones)
60
- node .opencode/skills/forge/scripts/graph.mjs
60
+ node {{AGENT_PATH}}/scripts/graph.mjs
61
61
 
62
62
  # ARCHITECTURE.md con grafo incluido
63
- node .opencode/skills/forge/scripts/architecture.mjs
63
+ node {{AGENT_PATH}}/scripts/architecture.mjs
64
64
  ```
65
65
 
66
66
  `chain.mjs` ahora es un wrapper sobre `graph.mjs`. Produce el mismo formato de salida para compatibilidad (nodos, edges, features, orden topológico). El nuevo `graph.mjs` amplía el análisis a todos los tipos de nodo (core, feature, domain, infra, adapter) y detecta violaciones de reglas arquitectónicas (R1-R6).
@@ -85,10 +85,10 @@ jobs:
85
85
  runs-on: ubuntu-latest
86
86
  steps:
87
87
  - uses: actions/checkout@v4
88
- - run: node .opencode/skills/forge/scripts/detect.mjs
88
+ - run: node {{AGENT_PATH}}/scripts/detect.mjs
89
89
  env:
90
90
  FORGE_STRICT: "true"
91
- - run: node .opencode/skills/forge/scripts/chain.mjs --json
91
+ - run: node {{AGENT_PATH}}/scripts/chain.mjs --json
92
92
  ```
93
93
 
94
94
  ---
@@ -52,9 +52,9 @@ Inspecciona la conformidad arquitectónica del proyecto.
52
52
  ## Ejecución
53
53
 
54
54
  ```bash
55
- node .opencode/skills/forge/scripts/inspect.mjs
56
- node .opencode/skills/forge/scripts/inspect.mjs --json
57
- node .opencode/skills/forge/scripts/detect.mjs --severity ERROR
55
+ node {{AGENT_PATH}}/scripts/inspect.mjs
56
+ node {{AGENT_PATH}}/scripts/inspect.mjs --json
57
+ node {{AGENT_PATH}}/scripts/detect.mjs --severity ERROR
58
58
 
59
59
  ## Ver también
60
60
 
@@ -150,11 +150,70 @@ REST prefiere `/api/v1/resources`. GraphQL schema en `adapters/in/graphql/` dent
150
150
 
151
151
  ---
152
152
 
153
+ ## Import Conventions (OBLIGATORIO)
154
+
155
+ Todo import generado por Forge debe cumplir estas reglas. Violaciones = ERROR en forge quench:
156
+
157
+ ### 1. Prefijo relativo obligatorio
158
+ Los imports locales SIEMPRE deben usar prefijo `./` o `../`. Prohibido el bare specifier:
159
+ ```ts
160
+ // ✅ Correcto
161
+ import { X } from "./foo.js";
162
+ import { Y } from "../../bar.js";
163
+
164
+ // ❌ Incorrecto (bare specifier — se resuelve contra node_modules)
165
+ import { X } from "domain/entities/Task.js";
166
+ import { Y } from "domain/repositories/IRepo.js";
167
+ ```
168
+
169
+ ### 2. Extensión .js obligatoria
170
+ Con `moduleResolution: "nodenext"`, todos los imports locales requieren extensión `.js`:
171
+ ```ts
172
+ // ✅ Correcto
173
+ import { X } from "./foo.js";
174
+
175
+ // ❌ Incorrecto
176
+ import { X } from "./foo.ts";
177
+ import { X } from "./foo";
178
+ ```
179
+
180
+ ### 3. Path alias para cross-layer
181
+ Usar path alias `@/` para cruzar capas, no paths relativos largos:
182
+ | Capa | Alias | Ejemplo |
183
+ |------|-------|---------|
184
+ | Platform → cualquiera | `@/platform/` | `@/platform/config/App.config.js` |
185
+ | Shared → cualquiera | `@/shared/` | `@/shared/errors/NotFoundError.js` |
186
+ | Infra → cualquiera | `@/infra/` | `@/infra/mongodb/Mongo.config.js` |
187
+ | **Entities compartidas** | **`@/domain/`** | **`@/domain/entities/Task.js`** |
188
+
189
+ ```ts
190
+ // ✅ Correcto — path alias para entidad compartida
191
+ import { Task } from "@/domain/entities/Task.js";
192
+
193
+ // ❌ Incorrecto — path relativo largo que no resuelve
194
+ import { Task } from "../../../../domain/entities/Task.js";
195
+ ```
196
+
197
+ ### 4. Entity Discovery — compartida vs local
198
+ - Si la entidad vive en `src/features/<feature>/domain/entities/` → import relativo (`../../domain/entities/`)
199
+ - Si la entidad vive en `src/platform/domain/entities/` → path alias (`@/domain/entities/`)
200
+ - Verificar existencia ANTES de generar el import
201
+
202
+ ### 5. Controllers y DI
203
+ - Controllers importan desde `./di.js` (feature con DI propia) o `@/setting/dependencies/<name>.di.js` (feature sin DI propia)
204
+ - Prohibido importar desde `bootstrap.di.js` — ese archivo no existe en la arquitectura actual
205
+
206
+ ### 6. Tests
207
+ - Todos los imports con extensión `.js` (nunca `.ts`)
208
+ - Usar `as const` para literales de union types
209
+ - Usar `result!` para valores posiblemente null
210
+ - Usar `(result as any)._id` si `_id` no está en el tipo
211
+
153
212
  ## Export Conventions
154
213
 
155
214
  - Cada directorio expone un `index.ts` barrel con named exports
156
215
  - Usar `export * from "./<Name>.<artifact>.js"` en barrels
157
216
  - Preferir `export function` / `export class` sobre `export default`
158
217
  - Imports relativos dentro del mismo feature (`../../domain/`)
159
- - Path alias para cross-layer: `@/platform/`, `@/shared/`, `@/infra/`
218
+ - Path alias para cross-layer: `@/platform/`, `@/shared/`, `@/infra/`, `@/domain/`
160
219
  - Extension `.js` en imports (ESM compat): `import { X } from "./foo.js"`
@@ -28,6 +28,8 @@
28
28
 
29
29
  12. **Cuatro dominios arquitectónicos con ownership estricto** — Todo backend se modela en cuatro capas: Platform (backbone técnico), Features (negocio), Shared (código puro reutilizable) e Infrastructure (implementaciones concretas). Cada componente tiene un único propietario arquitectónico. Los huérfanos, duplicados y componentes mal ubicados se detectan automáticamente. Las reglas de dependencia entre capas son obligatorias: `feature → platform → infra`, `feature → shared`, `adapter → infra`. Cualquier violación es una degradación arquitectónica.
30
30
 
31
+ **⚠️ Platform es exclusivamente backbone técnico.** Nunca debe contener entidades de dominio, casos de uso, mappers, repositorios de dominio, schemas de entidades, DTOs de negocio ni ninguna lógica con reglas de negocio. Si un archivo en `platform/` tiene sufijos `.entity.ts`, `.uc.ts`, `.mapper.ts`, `.port.ts` o importa desde `features/`, está mal ubicado. Esa lógica pertenece a `src/features/<name>/`. Violar esto introduce acoplamiento `platform → feature` (R2) y contamina el backbone técnico con lógica de dominio (R13).
32
+
31
33
  13. **Errores tipados en el dominio** — Los errores de dominio son clases explícitas, no `throw Error()` genéricos. Viven en `shared/errors/` si son transversales o en `domain/` del feature si son específicos. Los adapters HTTP traducen errores de dominio a códigos HTTP. La capa de aplicación nunca sabe qué códigos HTTP existen. Ver `reference/errors.md`.
32
34
 
33
35
  14. **Tests como ciudadanos de primera clase** — El dominio y los casos de uso se testean con unit tests sin infraestructura (mocks en las interfaces). Los adapters se testean con integration tests contra infraestructura real. La pirámide de tests es 70% unit / 20% integration / 10% e2e. Sin coverage de use cases no hay aprobación arquitectónica. Ver `reference/testing-patterns.md`.
@@ -64,13 +64,13 @@ El grafo se construye automáticamente con `scripts/graph.mjs` y las violaciones
64
64
 
65
65
  ```bash
66
66
  # Validación completa
67
- node .opencode/skills/forge/scripts/detect.mjs
67
+ node {{AGENT_PATH}}/scripts/detect.mjs
68
68
 
69
69
  # Solo errores y críticos
70
- node .opencode/skills/forge/scripts/detect.mjs --severity ERROR
70
+ node {{AGENT_PATH}}/scripts/detect.mjs --severity ERROR
71
71
 
72
72
  # Solo un tipo específico
73
- node .opencode/skills/forge/scripts/detect.mjs --type layers
73
+ node {{AGENT_PATH}}/scripts/detect.mjs --type layers
74
74
 
75
75
  ## Ver también
76
76
 
@@ -23,10 +23,10 @@ Renombra un único archivo según las convenciones de `reference/patterns.md` y
23
23
  ### Flujo
24
24
 
25
25
  1. Identificar la ruta del archivo (relativa a la raíz del proyecto)
26
- 2. Ejecutar `node .opencode/skills/forge/scripts/rename.mjs --detect --file <path>` para detectar violación
26
+ 2. Ejecutar `node {{AGENT_PATH}}/scripts/rename.mjs --detect --file <path>` para detectar violación
27
27
  3. Si el archivo ya cumple naming, informar y terminar
28
28
  4. Mostrar preview del cambio al usuario
29
- 5. Ejecutar `node .opencode/skills/forge/scripts/rename.mjs --file <path>` que:
29
+ 5. Ejecutar `node {{AGENT_PATH}}/scripts/rename.mjs --file <path>` que:
30
30
  - Renombra físicamente el archivo
31
31
  - Escanea todos los `.ts`/`.js` del proyecto
32
32
  - Actualiza imports que referencian el path antiguo (relativos y absolutos)
@@ -57,9 +57,9 @@ $ forge reforge src/features/users/domain/userEntity.ts
57
57
  1. Ejecutar `forge inspect` para obtener estado actual
58
58
  2. Identificar violaciones en el grafo arquitectónico
59
59
  3. Identificar ownership problemático (huérfanos, duplicados, mal ubicados)
60
- 4. **Detectar naming violations**: Ejecutar `node .opencode/skills/forge/scripts/rename.mjs --detect --json`
60
+ 4. **Detectar naming violations**: Ejecutar `node {{AGENT_PATH}}/scripts/rename.mjs --detect --json`
61
61
  5. Si hay naming violations, preguntar al usuario: "¿Corregir naming conventions automáticamente?"
62
- - Si acepta, ejecutar `node .opencode/skills/forge/scripts/rename.mjs --all`
62
+ - Si acepta, ejecutar `node {{AGENT_PATH}}/scripts/rename.mjs --all`
63
63
  6. Decidir las acciones correctivas en orden:
64
64
  - Violaciones CRITICAL primero (R1, R2, R5, R6)
65
65
  - Violaciones ERROR después (R3, R4, R8, R9)
@@ -67,9 +67,15 @@ $ forge reforge src/features/users/domain/userEntity.ts
67
67
  - Naming violations (si no se corrigieron en paso 5)
68
68
  - Warnings
69
69
  7. Ejecutar cambios en el feature o componente
70
- 8. Verificar con `forge rollback verify` si el score empeora, restaurar
71
- 9. Ejecutar `forge quench` para verificar
72
- 10. Actualizar `ARCHITECTURE.md`
70
+ 8. **Eliminar estructura legacy** después de migrar/refactorizar, limpiar todo el código fuente legacy que ya no tenga referencias activas:
71
+ - Archivos originales en ubicaciones legacy (`src/domain/`, `src/application/`, `src/adapters/`, etc.)
72
+ - Barrel files (`index.ts`) que exportaban exclusivamente código legacy
73
+ - Directorios vacíos que quedaron huérfanos tras la migración
74
+ - No dejar imports rotos ni archivos sin dueño
75
+ 9. Verificar con `forge rollback verify` — si el score empeora, restaurar
76
+ 10. Ejecutar `forge quench` para verificar 0 violaciones
77
+ 11. Ejecutar `forge armorer` — confirmar ownership saludable (0 huérfanos, 0 duplicados)
78
+ 12. Actualizar `ARCHITECTURE.md`
73
79
 
74
80
  ### Flags
75
81
 
@@ -88,11 +94,27 @@ forge rollback list
88
94
  forge rollback restore <id>
89
95
  ```
90
96
 
97
+ ## ⚠️ Regla crítica: Platform solo acepta backbone técnico
98
+
99
+ **Platform NO debe contener lógica de dominio.** Al refactorizar hacia `src/platform/`, verificar que el componente sea exclusivamente técnico:
100
+
101
+ | ✅ Permitido en Platform | ❌ Prohibido en Platform |
102
+ |---|---|
103
+ | config, server, logger, DI | Entidades de dominio |
104
+ | http, middleware, router | Casos de uso |
105
+ | cache, security, events | Repositorios (domain) |
106
+ | database, scheduler, observability | Mappers de dominio |
107
+ | Conexiones, clientes de infra | Schemas de entidades |
108
+ | Tokens de DI, contenedores | DTOs de negocio |
109
+ | Health checks, métricas | Lógica de reglas de negocio |
110
+
111
+ Si durante la refactorización un componente tiene lógica de dominio (entidades, `if/switch` con reglas de negocio, casos de uso), **debe ir a `src/features/<name>/`**, no a `platform/`. Violar esto introduce acoplamiento `platform → feature` (R2).
112
+
91
113
  ## Refactorización multi-capa
92
114
 
93
115
  Reforge ahora considera las cuatro capas arquitectónicas:
94
116
 
95
- - **Platform**: Mover componentes técnicos sueltos a `src/platform/`
117
+ - **Platform**: Mover componentes técnicos sueltos a `src/platform/` (nunca lógica de dominio)
96
118
  - **Features**: Reestructurar features con violaciones
97
119
  - **Shared**: Extraer código duplicado a `src/shared/`
98
120
  - **Infra**: Organizar implementaciones concretas en `src/infra/`
@@ -25,10 +25,16 @@ También puede migrar componentes legacy a los layers Platform, Shared o Infrast
25
25
  3. Crear la estructura target según el layer
26
26
  4. Migrar archivos manteniendo la lógica intacta
27
27
  5. Actualizar imports
28
- 6. Eliminar estructura legacy
28
+ 6. **Eliminar estructura legacy por completo** — no dejar archivos huérfanos, barrel files (index.ts) vacíos, ni directorios legacy sin contenido. Verificar:
29
+ - `src/application/use-cases/<name>/` queda vacío y se elimina
30
+ - `src/adapters/in/http/controllers/` sin archivos del feature migrado
31
+ - `src/domain/entities/`, `src/domain/repositories/` sin duplicados
32
+ - `src/setting/dependencies/` sin `.di.ts` del feature migrado
33
+ - Barrel files (`index.ts`) que solo exportaban código legacy se eliminan
29
34
  7. Verificar con `forge rollback verify` — si el score empeora, restaurar con `forge rollback restore <backup-id>`
30
- 8. Ejecutar `forge quench` para verificar
31
- 9. Actualizar `ARCHITECTURE.md`
35
+ 8. Ejecutar `forge quench` para verificar 0 violaciones
36
+ 9. Ejecutar `forge armorer` — confirmar que no hay huérfanos ni duplicados del código legacy
37
+ 10. Actualizar `ARCHITECTURE.md`
32
38
 
33
39
  ## Rollback
34
40
 
@@ -41,6 +47,22 @@ forge rollback restore <id> # restaurar
41
47
 
42
48
  El backup se almacena en `.forge/backups/<target>--<timestamp>/` y preserva la estructura original completa.
43
49
 
50
+ ## ⚠️ Regla crítica: No insertar lógica de dominio en Platform
51
+
52
+ Al migrar componentes legacy, **nunca colocar lógica de dominio en `src/platform/`**. Platform es exclusivamente backbone técnico.
53
+
54
+ | Tipo de componente | Layer correcto |
55
+ |---|---|
56
+ | Configuración de framework, servidor, logger, DI | `src/platform/` |
57
+ | Middleware HTTP, routers, guards, interceptors | `src/platform/http/` |
58
+ | Conexiones a BD, clientes Redis, mail | `src/infra/` |
59
+ | Código utilitario puro (sin lógica de negocio) | `src/shared/` |
60
+ | **Entidades, value objects, reglas de dominio** | **`src/features/<name>/domain/`** |
61
+ | **Casos de uso, servicios de aplicación** | **`src/features/<name>/application/`** |
62
+ | **Controladores, repositorios, schemas** | **`src/features/<name>/adapters/`** |
63
+
64
+ Si un archivo contiene `class`, `interface` con reglas de negocio, `if/switch` con lógica de dominio, o importa desde `features/`, pertenece a un feature, no a platform.
65
+
44
66
  ## Estrategias por layer
45
67
 
46
68
  | Layer | Desde | Hacia |
@@ -246,6 +246,27 @@ export function detectMisplaced(projectRoot = ROOT) {
246
246
  suggestion: "Envolver en un adapter dentro de features/<name>/adapters/out/",
247
247
  });
248
248
  }
249
+
250
+ // R13: Platform con lógica de dominio
251
+ if (isPlatformFile) {
252
+ const basenamePath = basename(file);
253
+ const DOMAIN_PATTERNS = /\.(entity|uc|mapper|port|repository)\.(ts|js)$/i;
254
+ if (DOMAIN_PATTERNS.test(basenamePath)) {
255
+ misplaced.push({
256
+ file: relPath,
257
+ reason: "Platform contiene artefacto de dominio — violación R13",
258
+ suggestion: "Mover a src/features/<name>/domain/ o application/ según corresponda",
259
+ });
260
+ }
261
+ const featureImportMatch = content.match(featurePattern);
262
+ if (featureImportMatch) {
263
+ misplaced.push({
264
+ file: relPath,
265
+ reason: "Platform importa de features — violación R2",
266
+ suggestion: "Platform no debe conocer lógica de negocio. Extraer interfaz a shared/contracts/ o refactorizar.",
267
+ });
268
+ }
269
+ }
249
270
  }
250
271
 
251
272
  return misplaced;