@saulwade/swl-ses 2.4.2 → 2.5.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.
- package/CLAUDE.md +194 -241
- package/README.md +600 -597
- package/agentes/_intent-spec.md +73 -73
- package/agentes/_propose-step.md +90 -90
- package/agentes/abogado-diablo-swl.md +145 -0
- package/agentes/accesibilidad-wcag-swl.md +690 -690
- package/agentes/arquitecto-swl.md +267 -267
- package/agentes/auto-evolucion-swl.md +908 -908
- package/agentes/backend-api-swl.md +1 -1
- package/agentes/backend-csharp-swl.md +420 -420
- package/agentes/backend-go-swl.md +390 -390
- package/agentes/backend-java-swl.md +281 -281
- package/agentes/backend-node-swl.md +1 -1
- package/agentes/backend-python-swl.md +1 -1
- package/agentes/backend-rust-swl.md +364 -364
- package/agentes/backend-workers-swl.md +482 -482
- package/agentes/cloud-infra-swl.md +509 -509
- package/agentes/consolidador-swl.md +541 -541
- package/agentes/datos-swl.md +1 -1
- package/agentes/depurador-swl.md +352 -352
- package/agentes/devops-ci-swl.md +400 -400
- package/agentes/disenador-ui-swl.md +569 -569
- package/agentes/documentador-swl.md +345 -345
- package/agentes/frontend-angular-swl.md +621 -621
- package/agentes/frontend-css-swl.md +716 -716
- package/agentes/frontend-react-swl.md +692 -692
- package/agentes/frontend-swl.md +496 -496
- package/agentes/frontend-tailwind-swl.md +826 -826
- package/agentes/gh-fix-ci-swl.md +6 -1
- package/agentes/implementador-swl.md +1 -1
- package/agentes/investigador-swl.md +432 -432
- package/agentes/investigador-ux-swl.md +505 -505
- package/agentes/llm-apps-swl.md +1 -1
- package/agentes/migrador-swl.md +442 -442
- package/agentes/mobile-android-swl.md +511 -511
- package/agentes/mobile-cross-swl.md +541 -541
- package/agentes/mobile-ios-swl.md +502 -502
- package/agentes/mobile-testing-swl.md +302 -302
- package/agentes/nemesis-auditor-swl.md +285 -285
- package/agentes/notificador-swl.md +1 -1
- package/agentes/observabilidad-swl.md +438 -438
- package/agentes/pagos-swl.md +310 -310
- package/agentes/perfilador-usuario-swl.md +321 -321
- package/agentes/planificador-swl.md +399 -399
- package/agentes/producto-prd-swl.md +589 -589
- package/agentes/red-team-swl.md +218 -218
- package/agentes/release-manager-swl.md +590 -590
- package/agentes/rendimiento-swl.md +713 -713
- package/agentes/resolutor-build-swl.md +10 -1
- package/agentes/revisor-angular-swl.md +278 -278
- package/agentes/revisor-codigo-swl.md +1 -1
- package/agentes/revisor-csharp-swl.md +264 -264
- package/agentes/revisor-go-swl.md +259 -259
- package/agentes/revisor-java-swl.md +257 -257
- package/agentes/revisor-kotlin-swl.md +273 -273
- package/agentes/revisor-nextjs-swl.md +281 -281
- package/agentes/revisor-php-swl.md +271 -271
- package/agentes/revisor-react-swl.md +278 -278
- package/agentes/revisor-rust-swl.md +346 -346
- package/agentes/revisor-seguridad-swl.md +399 -399
- package/agentes/revisor-swift-swl.md +268 -268
- package/agentes/revisor-typescript-swl.md +346 -346
- package/agentes/sre-swl.md +1 -1
- package/agentes/tdd-qa-swl.md +393 -393
- package/bin/lib/bot-comandos.js +1 -1
- package/bin/swl-ses.js +6 -0
- package/comandos/swl/adoptar-proyecto.md +14 -2
- package/comandos/swl/configurar-ci.md +8 -1
- package/comandos/swl/deuda-codigo.md +97 -97
- package/comandos/swl/discutir-fase.md +22 -118
- package/comandos/swl/fix.md +118 -0
- package/comandos/swl/nuevo-proyecto.md +54 -3
- package/comandos/swl/predecir.md +32 -2
- package/comandos/swl/seguridad.md +189 -0
- package/comandos/swl/status.md +5 -3
- package/habilidades/aprendizaje-continuo/SKILL.md +3 -1
- package/habilidades/discutir-fase/SKILL.md +84 -81
- package/habilidades/discutir-fase/recursos/plantilla-contexto.md +136 -0
- package/habilidades/doc-sync/SKILL.md +3 -1
- package/habilidades/doubt-driven-review/SKILL.md +15 -1
- package/habilidades/ejecutar-task-iterativo/SKILL.md +278 -278
- package/habilidades/estructura-proyecto-claude/SKILL.md +11 -2
- package/habilidades/harness-claude-code/SKILL.md +3 -1
- package/habilidades/instalar-sistema/SKILL.md +3 -1
- package/habilidades/meta-reglas-extendido/SKILL.md +92 -0
- package/habilidades/meta-reglas-extendido/recursos/analisis-previo-tareas-grandes.md +186 -0
- package/habilidades/meta-reglas-extendido/recursos/analizar-directorios-antes-de-escribir.md +235 -0
- package/habilidades/meta-reglas-extendido/recursos/api-diseno.md +413 -0
- package/habilidades/meta-reglas-extendido/recursos/arquitectura.md +491 -0
- package/habilidades/meta-reglas-extendido/recursos/arreglar-al-detectar.md +264 -0
- package/habilidades/meta-reglas-extendido/recursos/debatir-antes-de-aceptar.md +152 -0
- package/habilidades/meta-reglas-extendido/recursos/git-workflow.md +259 -0
- package/habilidades/meta-reglas-extendido/recursos/gobernanza.md +291 -0
- package/habilidades/meta-reglas-extendido/recursos/memoria-consolidada.md +263 -0
- package/habilidades/meta-reglas-extendido/recursos/seguridad-agentes.md +443 -0
- package/habilidades/meta-reglas-extendido/recursos/sesiones-paralelas.md +190 -0
- package/habilidades/meta-reglas-extendido/recursos/sin-duplicacion-reglas-globales.md +179 -0
- package/habilidades/meta-reglas-extendido/recursos/skills-estandar.md +394 -0
- package/habilidades/meta-reglas-extendido/recursos/usar-code-review-graph.md +156 -0
- package/habilidades/meta-reglas-extendido/recursos/usar-context7.md +236 -0
- package/habilidades/meta-reglas-extendido/recursos/usar-sistema-swl.md +253 -0
- package/habilidades/meta-reglas-extendido/recursos/verificar-citas-normativas.md +527 -0
- package/habilidades/meta-skills-estandar/SKILL.md +3 -1
- package/habilidades/nuevo-proyecto/SKILL.md +20 -3
- package/habilidades/php-experto/SKILL.md +10 -3
- package/habilidades/{filament-admin/SKILL.md → php-experto/recursos/filament-admin.md} +23 -39
- package/habilidades/prevencion-sobreingenieria/recursos/soluciones-nativas.md +166 -166
- package/habilidades/prevencion-sobreingenieria/recursos/variables-residuales-post-refactor.md +85 -85
- package/habilidades/proceso-debate-adversarial/recursos/personas.md +5 -4
- package/habilidades/proceso-ingenieria-requerimientos/SKILL.md +147 -0
- package/hooks/check-update.js +19 -10
- package/hooks/contexto-subagente.js +68 -68
- package/hooks/degradacion-instintos.js +1 -1
- package/hooks/extraccion-aprendizajes.js +2 -2
- package/hooks/lib/briefing.js +3 -3
- package/hooks/lib/nudge-tracker.js +1 -1
- package/hooks/lib/otlp-exporter.js +1 -1
- package/hooks/lib/webhook-dedup.js +1 -1
- package/hooks/session-briefing.js +1 -1
- package/llms.txt +6 -6
- package/manifiestos/canonical-hashes.json +989 -0
- package/manifiestos/hooks-config.json +469 -469
- package/manifiestos/invariantes-criticos.json +30 -30
- package/manifiestos/modulos.json +168 -135
- package/manifiestos/perfiles.json +0 -2
- package/manifiestos/skills-lock.json +52 -59
- package/package.json +7 -5
- package/plantillas/github-workflows/README.md +15 -1
- package/plantillas/github-workflows/swl-devsecops.yml +70 -0
- package/plugin.json +5 -5
- package/reglas/analisis-previo-tareas-grandes.md +30 -156
- package/reglas/analizar-directorios-antes-de-escribir.md +30 -211
- package/reglas/api-diseno.md +28 -398
- package/reglas/arquitectura.md +35 -456
- package/reglas/arreglar-al-detectar.md +30 -230
- package/reglas/debatir-antes-de-aceptar.md +30 -143
- package/reglas/docs.md +7 -0
- package/reglas/estilo-codigo.md +9 -0
- package/reglas/fragmentos-compartidos.md +6 -0
- package/reglas/git-workflow.md +44 -240
- package/reglas/gobernanza.md +23 -262
- package/reglas/memoria-consolidada.md +34 -228
- package/reglas/performance.md +8 -0
- package/reglas/pruebas.md +12 -0
- package/reglas/seguridad-agentes.md +37 -418
- package/reglas/seguridad.md +12 -0
- package/reglas/sesiones-paralelas.md +29 -162
- package/reglas/sin-duplicacion-reglas-globales.md +25 -166
- package/reglas/skills-estandar.md +23 -373
- package/reglas/usar-code-review-graph.md +31 -140
- package/reglas/usar-context7.md +30 -208
- package/reglas/usar-sistema-swl.md +47 -242
- package/reglas/verificar-citas-normativas.md +47 -537
- package/scripts/actualizar.js +253 -253
- package/scripts/audit-tools/auditar-relleno-inventario.js +145 -0
- package/scripts/auditar-clases-conocidas.js +106 -0
- package/scripts/bootstrap-instintos.js +2 -2
- package/scripts/canario-hooks.js +166 -0
- package/scripts/cli/configurar-ci.js +2 -1
- package/scripts/evidencia-valor.js +93 -0
- package/scripts/field-report.js +1 -1
- package/scripts/generar-comandos.js +143 -0
- package/scripts/generar-inventario.js +236 -23
- package/scripts/generar-matriz-lenguajes.js +1 -1
- package/scripts/instalador.js +15 -1
- package/scripts/lib/configurar-ci.js +10 -3
- package/scripts/lib/detectar-runtime.js +12 -3
- package/scripts/lib/diary-entry.js +3 -1
- package/scripts/lib/drift-detector.js +1 -1
- package/scripts/lib/evidencia-valor.js +189 -0
- package/scripts/lib/expandir-targets.js +71 -71
- package/scripts/lib/frontmatter-md.js +63 -0
- package/scripts/lib/parsear-opciones.js +2 -0
- package/scripts/lib/prune-componentes.js +180 -0
- package/scripts/lib/reglas-globales-conocidas.json +16 -2
- package/scripts/lib/scoring-instintos.js +2 -2
- package/scripts/lib/toml-merge.js +204 -204
- package/scripts/lib/transformadores/claude.js +1 -1
- package/scripts/lib/transformadores/codex.js +1 -1
- package/scripts/lib/transformadores/copilot.js +1 -1
- package/scripts/lib/transformadores/cursor.js +1 -1
- package/scripts/lib/transformadores/gemini.js +22 -2
- package/scripts/lib/transformadores/opencode.js +1 -1
- package/scripts/mcp-server/auth.js +105 -105
- package/scripts/mcp-server/cache.js +106 -106
- package/scripts/prune.js +102 -0
- package/scripts/publicar.js +18 -2
- package/scripts/tui/pantallas/inspect.js +175 -175
- package/scripts/tui/pantallas/uninstall-wizard.js +210 -210
- package/scripts/tui/pantallas/update-wizard.js +234 -234
- package/scripts/tui/pantallas/welcome.js +189 -189
- package/habilidades/paid-media-tracking/SKILL.md +0 -269
- package/habilidades/paid-media-tracking/recursos/auditoria-tracking.md +0 -220
- package/habilidades/paid-media-tracking/recursos/google-ads-api.md +0 -215
- package/habilidades/tracking-measurement/SKILL.md +0 -239
- package/habilidades/tracking-measurement/recursos/consent-mode.md +0 -231
- package/habilidades/tracking-measurement/recursos/gtm-datalayer.md +0 -216
- package/habilidades/tracking-measurement/recursos/meta-capi.md +0 -262
package/reglas/arquitectura.md
CHANGED
|
@@ -1,475 +1,54 @@
|
|
|
1
1
|
# Regla: Arquitectura
|
|
2
2
|
|
|
3
|
-
Las decisiones de arquitectura tienen un costo de cambio muy alto.
|
|
4
|
-
|
|
5
|
-
sistema para que sean reversibles o al menos comprensibles en el futuro.
|
|
6
|
-
|
|
7
|
-
---
|
|
3
|
+
Las decisiones de arquitectura tienen un costo de cambio muy alto. Núcleo denso de
|
|
4
|
+
cómo tomar, documentar y mantener las decisiones estructurales del sistema.
|
|
8
5
|
|
|
9
6
|
## ADRs — Architecture Decision Records
|
|
10
7
|
|
|
11
|
-
Toda decisión de
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
- Es difícil o costosa de revertir
|
|
16
|
-
- Tiene alternativas viables que fueron consideradas
|
|
17
|
-
- El equipo debatió más de 15 minutos
|
|
18
|
-
|
|
19
|
-
Formato mínimo de un ADR (`docs/adr/NNN-titulo-corto.md`):
|
|
20
|
-
```markdown
|
|
21
|
-
# ADR NNN: Título de la decisión
|
|
22
|
-
|
|
23
|
-
**Fecha**: YYYY-MM-DD
|
|
24
|
-
**Estado**: Propuesto | Aceptado | Deprecado | Reemplazado por ADR-NNN
|
|
25
|
-
|
|
26
|
-
## Contexto
|
|
27
|
-
Qué situación o problema motivó esta decisión.
|
|
28
|
-
|
|
29
|
-
## Decisión
|
|
30
|
-
Qué se decidió hacer.
|
|
31
|
-
|
|
32
|
-
## Consecuencias
|
|
33
|
-
Qué implica esta decisión — positivo, negativo, neutral.
|
|
34
|
-
|
|
35
|
-
## Alternativas consideradas
|
|
36
|
-
Qué más se evaluó y por qué se descartó.
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
Reglas de ADRs:
|
|
40
|
-
- Numerados secuencialmente, nunca reutilizar un número.
|
|
41
|
-
- Inmutables: si una decisión cambia, crear un nuevo ADR que referencia al anterior.
|
|
42
|
-
- Versionar con el código — viven en el repositorio.
|
|
43
|
-
- Revisar ADRs existentes antes de proponer arquitectura nueva.
|
|
44
|
-
|
|
45
|
-
### ADRs en estado Propuesto
|
|
46
|
-
|
|
47
|
-
Un ADR en estado `Propuesto` documenta una decisión evaluada pero **no implementada
|
|
48
|
-
todavía** — por ejemplo porque depende de factores externos (roadmap de un tercero,
|
|
49
|
-
evidencia futura que hoy no existe, señal de demanda que aún no aparece). Mantener
|
|
50
|
-
ADRs en Propuesto indefinidamente sin plan de cierre genera deuda silenciosa —
|
|
51
|
-
propuestas que "quedan ahí" y nadie revisa.
|
|
52
|
-
|
|
53
|
-
**Todo ADR en estado Propuesto DEBE incluir:**
|
|
54
|
-
|
|
55
|
-
1. **Criterios de disparo** — lista concreta de condiciones que reabren la decisión
|
|
56
|
-
(al menos una por entrada). Ejemplos: "El usuario pide X", "Anthropic publica Y",
|
|
57
|
-
"Contador supera umbral Z".
|
|
58
|
-
2. **Fecha límite de reevaluación automática** — entre 6 y 12 meses desde la fecha
|
|
59
|
-
de creación del ADR. Si ninguno de los criterios se cumple antes de la fecha,
|
|
60
|
-
el ADR se mueve a `Descartado` documentando la decisión final.
|
|
61
|
-
|
|
62
|
-
Un ADR Propuesto sin ambos elementos NO es aceptable — se rechaza en revisión.
|
|
63
|
-
|
|
64
|
-
**Índice obligatorio**: el archivo `docs/adr/README.md` (o `.planning/adrs/README.md`
|
|
65
|
-
en SWL) lista todos los ADRs con estado y fecha de reevaluación visible. Cualquier
|
|
66
|
-
persona debe poder ver en una lectura si hay ADRs vencidos sin abrir cada archivo.
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
## Análisis de repositorios externos — filtro de dominio obligatorio
|
|
71
|
-
|
|
72
|
-
Cuando se analiza un repositorio ajeno para enriquecer el sistema SWL (código en
|
|
73
|
-
`temp/`, dependencias, proyectos de referencia), **el primer paso antes de cualquier
|
|
74
|
-
análisis profundo** es aplicar el filtro de dominio:
|
|
75
|
-
|
|
76
|
-
> *¿Le sirve esto a un ingeniero de software en cualquier proyecto de software?*
|
|
77
|
-
|
|
78
|
-
Si la respuesta es **NO** porque el repositorio vive en un dominio vertical externo
|
|
79
|
-
(fintech/billing, ML Ops, data science, bio-informática, dominios regulados
|
|
80
|
-
específicos, etc.), descartar el 80-95% del contenido sin análisis profundo.
|
|
81
|
-
|
|
82
|
-
**Lo que siempre vale la pena extraer aunque el dominio sea externo:**
|
|
83
|
-
|
|
84
|
-
- Patrones de configuración de Claude Code: `.claude/settings.json`, hooks, comandos
|
|
85
|
-
- Patrones de arquitectura transversales: repository pattern, service layer, etc.
|
|
86
|
-
- Configuraciones de CI/CD, Docker, pre-commit
|
|
87
|
-
- Patrones de testing, observabilidad, auth
|
|
88
|
-
|
|
89
|
-
**Lo que se descarta sin análisis aunque esté bien escrito:**
|
|
90
|
-
|
|
91
|
-
- Lógica de negocio específica del dominio externo
|
|
92
|
-
- Integraciones con servicios verticales (Stripe fintech, servicios de ML Ops,
|
|
93
|
-
procesadores de señales médicas)
|
|
94
|
-
- Documentación de producto/handbook organizacional
|
|
95
|
-
|
|
96
|
-
**Patrón validado**: análisis de `temp/polar-main` (fintech, 86 módulos) en
|
|
97
|
-
sesión 2026-04-23 → 3% integrado (3 patrones transversales), 97% descartado sin
|
|
98
|
-
análisis profundo. Análisis de `temp/estilo-sin-ai-isms` (ecosistema auditor
|
|
99
|
-
OIC-INE) → 10% integrado. Aplicar el filtro primero ahorra horas de análisis
|
|
100
|
-
de código irrelevante.
|
|
101
|
-
|
|
102
|
-
---
|
|
103
|
-
|
|
104
|
-
## Módulos profundos — interfaz pequeña, implementación rica
|
|
8
|
+
- Toda decisión significativa (afecta >1 módulo/equipo, difícil de revertir, tuvo alternativas viables consideradas, o se debatió >15 min) se documenta como ADR en `docs/adr/NNN-titulo-corto.md` — formato mínimo (Contexto / Decisión / Consecuencias / Alternativas) en el extendido.
|
|
9
|
+
- Numerados secuencialmente, nunca reutilizar un número; inmutables (si la decisión cambia, ADR nuevo que referencia al anterior); versionados con el código; revisar ADRs existentes antes de proponer arquitectura nueva.
|
|
10
|
+
- Todo ADR en estado `Propuesto` EXIGE: criterios de disparo concretos (condiciones observables que reabren la decisión) + fecha límite de reevaluación entre 6 y 12 meses. Sin ambos, se rechaza en revisión; vencido sin disparo → `Descartado`.
|
|
11
|
+
- Índice obligatorio en `docs/adr/README.md` (o `.planning/adrs/README.md` en SWL) con estado y fecha de reevaluación visibles de una lectura.
|
|
105
12
|
|
|
106
|
-
|
|
13
|
+
## Principios de diseño
|
|
107
14
|
|
|
108
|
-
-
|
|
109
|
-
|
|
110
|
-
-
|
|
111
|
-
|
|
112
|
-
- Un módulo shallow tiene una interfaz casi tan compleja como su implementación
|
|
113
|
-
— ofrece poco valor de abstracción.
|
|
15
|
+
- **Módulos profundos** (Ousterhout): interfaz pública MÍNIMA frente a la complejidad que encapsula; exponer solo lo que el llamador NECESITA — la implementación puede ser compleja, ese es el punto.
|
|
16
|
+
- **Dependency Injection**: las dependencias se RECIBEN, no se crean dentro de la clase/función; inyectar interfaces/protocolos vía el contenedor del framework. El grafo de dependencias fluye alto nivel → bajo nivel, nunca al revés.
|
|
17
|
+
- **Sin dependencias circulares**: el grafo de módulos debe ser un DAG; ante un ciclo, extraer lo compartido a un módulo de bajo nivel del que ambos dependan. NUNCA `importlib.import_module()` para romper el ciclo en runtime.
|
|
18
|
+
- **DRY**: duplicación de conocimiento, no de texto — si un cambio obliga a cambiar dos lugares, hay duplicación. Regla de tres antes de abstraer; DRY no justifica abstracciones prematuras.
|
|
114
19
|
|
|
115
|
-
|
|
116
|
-
- Una clase con 15 métodos públicos donde 12 son getters/setters triviales.
|
|
117
|
-
- Un service que solo pasa llamadas a otro service sin agregar lógica.
|
|
118
|
-
- Una función que solo llama a otra función con los mismos parámetros.
|
|
119
|
-
|
|
120
|
-
Cómo diseñar módulos profundos:
|
|
121
|
-
- Definir la interfaz pública primero, antes de implementar.
|
|
122
|
-
- La interfaz solo expone lo que el llamador NECESITA, no lo que es conveniente.
|
|
123
|
-
- La implementación puede ser compleja — eso es el punto.
|
|
124
|
-
- Documentar la interfaz, no la implementación (la implementación se explica sola
|
|
125
|
-
con código limpio).
|
|
126
|
-
|
|
127
|
-
---
|
|
128
|
-
|
|
129
|
-
## Dependency Injection (DI)
|
|
130
|
-
|
|
131
|
-
- Nunca instanciar dependencias dentro de una clase o función.
|
|
132
|
-
Las dependencias se RECIBEN, no se crean.
|
|
133
|
-
|
|
134
|
-
Mal:
|
|
135
|
-
```python
|
|
136
|
-
class FacturaService:
|
|
137
|
-
def __init__(self):
|
|
138
|
-
self.db = DatabaseConnection() # dependencia hardcodeada
|
|
139
|
-
self.mailer = SmtpMailer() # imposible de mockear en tests
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
Bien:
|
|
143
|
-
```python
|
|
144
|
-
class FacturaService:
|
|
145
|
-
def __init__(self, db: AsyncSession, mailer: MailerProtocol):
|
|
146
|
-
self.db = db
|
|
147
|
-
self.mailer = mailer
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
- Usar el contenedor de DI del framework (FastAPI Depends, Angular DI).
|
|
151
|
-
- Inyectar interfaces/protocolos, no implementaciones concretas.
|
|
152
|
-
- El grafo de dependencias fluye en una dirección: alto nivel → bajo nivel.
|
|
153
|
-
Nunca al revés.
|
|
154
|
-
|
|
155
|
-
---
|
|
156
|
-
|
|
157
|
-
## Separación de concerns
|
|
158
|
-
|
|
159
|
-
Cada módulo tiene UNA responsabilidad principal. Las capas del sistema:
|
|
20
|
+
## Separación de concerns (una responsabilidad por capa)
|
|
160
21
|
|
|
161
22
|
| Capa | Responsabilidad | Lo que NO hace |
|
|
162
|
-
|
|
163
|
-
| Endpoints / Controllers | Recibir HTTP, delegar al service,
|
|
164
|
-
| Services | Lógica de negocio, orquestación |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| Endpoints / Controllers | Recibir HTTP, delegar al service, responder | Lógica de negocio |
|
|
25
|
+
| Services | Lógica de negocio, orquestación | SQL directo, formateo HTTP, `db.commit()` (lo hace el endpoint) |
|
|
165
26
|
| Repositories / DAL | Acceso a datos, queries | Lógica de negocio |
|
|
166
|
-
| Schemas / DTOs | Validación y serialización | Lógica de negocio |
|
|
167
|
-
| Models / ORM | Estructura de datos en BD | Lógica de negocio |
|
|
168
|
-
|
|
169
|
-
Reglas estrictas:
|
|
170
|
-
- Los endpoints no contienen lógica de negocio — llaman al service.
|
|
171
|
-
- Los services no hacen `db.commit()` — el endpoint hace el commit.
|
|
172
|
-
- Los models ORM no contienen lógica de negocio compleja — solo helpers
|
|
173
|
-
de presentación simples.
|
|
174
|
-
- Los schemas Pydantic no acceden a la BD directamente.
|
|
175
|
-
|
|
176
|
-
---
|
|
177
|
-
|
|
178
|
-
## Sin dependencias circulares
|
|
179
|
-
|
|
180
|
-
- El grafo de dependencias entre módulos debe ser un DAG (grafo dirigido acíclico).
|
|
181
|
-
- Módulo A importa a Módulo B → Módulo B NO puede importar a Módulo A.
|
|
182
|
-
- Detectar con `import-linter` (Python) o `eslint-plugin-import` (TypeScript).
|
|
183
|
-
- Si se detecta una dependencia circular: extraer el tipo o la función compartida
|
|
184
|
-
a un módulo de bajo nivel del que ambos dependan.
|
|
185
|
-
- La solución NUNCA es `importlib.import_module()` para romper el ciclo en runtime.
|
|
186
|
-
|
|
187
|
-
Señales de dependencias circulares inminentes:
|
|
188
|
-
- Dos módulos que se referencian mutuamente "solo para un tipo".
|
|
189
|
-
- Un módulo `utils` o `helpers` que importa módulos de negocio.
|
|
190
|
-
- Un modelo ORM que importa un service.
|
|
191
|
-
|
|
192
|
-
---
|
|
27
|
+
| Schemas / DTOs | Validación y serialización | Lógica de negocio, acceso directo a BD |
|
|
28
|
+
| Models / ORM | Estructura de datos en BD | Lógica de negocio compleja |
|
|
193
29
|
|
|
194
30
|
## SOLID
|
|
195
31
|
|
|
196
|
-
**S
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
**
|
|
200
|
-
|
|
201
|
-
composición o strategy pattern, no if/else interminables).
|
|
202
|
-
|
|
203
|
-
**L — Liskov Substitution**: Un subtipo puede reemplazar a su supertipo.
|
|
204
|
-
Si se hereda de una clase, la subclase debe honrar el contrato de la base.
|
|
205
|
-
No lanzar excepciones que la base no lanza, no ignorar parámetros.
|
|
206
|
-
|
|
207
|
-
**I — Interface Segregation**: Interfaces pequeñas y específicas.
|
|
208
|
-
No forzar a una clase a implementar métodos que no usa. Preferir varias
|
|
209
|
-
interfaces pequeñas sobre una grande.
|
|
210
|
-
|
|
211
|
-
**D — Dependency Inversion**: Depender de abstracciones, no de implementaciones.
|
|
212
|
-
Los módulos de alto nivel no dependen de los de bajo nivel — ambos dependen
|
|
213
|
-
de abstracciones (protocolos, interfaces, clases abstractas).
|
|
214
|
-
|
|
215
|
-
---
|
|
216
|
-
|
|
217
|
-
## Tres capas de reutilización: regla, skill, fragmento
|
|
218
|
-
|
|
219
|
-
El sistema SWL distingue tres capas para evitar duplicación. La elección de la
|
|
220
|
-
capa correcta depende de cuándo y cómo se carga el contenido:
|
|
221
|
-
|
|
222
|
-
- **Regla** (`reglas/X.md`): política global cargada por matcher de archivos.
|
|
223
|
-
Aplicable a múltiples agentes y skills. Ejemplo: `reglas/seguridad.md`.
|
|
224
|
-
- **Skill** (`habilidades/X/SKILL.md`): conocimiento operacional invocado
|
|
225
|
-
dinámicamente con `Skill("X")`. Tiene frontmatter, descripción y carga
|
|
226
|
-
bajo demanda. Ejemplo: `habilidades/tdd-workflow/SKILL.md`.
|
|
227
|
-
- **Fragmento** (`agentes/_X.md`): bloque de prompt compartido por varios
|
|
228
|
-
agentes que se incrusta literalmente en su system prompt. Sin overhead
|
|
229
|
-
runtime, sin frontmatter operacional, no routable por el orquestador.
|
|
230
|
-
Ejemplo: `agentes/_hitl-alto-riesgo.md`.
|
|
231
|
-
|
|
232
|
-
Antes de crear texto compartido entre agentes, decidir cuál capa aplica. Ver
|
|
233
|
-
`reglas/fragmentos-compartidos.md` para la convención completa.
|
|
234
|
-
|
|
235
|
-
---
|
|
236
|
-
|
|
237
|
-
## DRY — Don't Repeat Yourself
|
|
238
|
-
|
|
239
|
-
Si una regla de negocio, una validación, un cálculo o una transformación cambia,
|
|
240
|
-
debe cambiar en un solo lugar. Si requiere cambiar en dos o más, hay duplicación
|
|
241
|
-
de conocimiento.
|
|
242
|
-
|
|
243
|
-
Estrategias para eliminar duplicación según el tipo:
|
|
244
|
-
|
|
245
|
-
- **Lógica de negocio duplicada entre services** → extraer a un service compartido
|
|
246
|
-
o un domain method.
|
|
247
|
-
- **Queries duplicadas** → extraer a un método del repositorio.
|
|
248
|
-
- **Validaciones repetidas** → centralizar en schemas (Pydantic, Zod, Bean Validation).
|
|
249
|
-
- **Configuración repetida** → extraer a variables de entorno o módulo de configuración.
|
|
250
|
-
- **Transformaciones de datos repetidas** → extraer a un mapper o utility function.
|
|
251
|
-
|
|
252
|
-
DRY aplica entre capas: si el frontend valida lo mismo que el backend, el backend
|
|
253
|
-
es la fuente de verdad. La validación del frontend es UX, no lógica de negocio.
|
|
254
|
-
|
|
255
|
-
DRY NO justifica abstracciones prematuras. Si la duplicación es casual (dos cosas
|
|
256
|
-
iguales hoy que cambiarán independientemente mañana), dejar duplicado es correcto.
|
|
257
|
-
DRY aplica cuando el conocimiento subyacente es el mismo.
|
|
258
|
-
|
|
259
|
-
---
|
|
260
|
-
|
|
261
|
-
## Patrones de arquitectura reconocidos
|
|
262
|
-
|
|
263
|
-
Antes de inventar una solución arquitectural nueva, verificar si alguno de
|
|
264
|
-
estos patrones resuelve el problema:
|
|
265
|
-
|
|
266
|
-
- **Repository Pattern**: Para abstraer el acceso a datos.
|
|
267
|
-
- **Command/Query Separation (CQS)**: Operaciones que cambian estado vs. las que leen.
|
|
268
|
-
- **Event-driven**: Para desacoplar productores de consumidores.
|
|
269
|
-
- **Strangler Fig**: Para migración incremental de sistemas legados.
|
|
270
|
-
- **Adapter**: Para integrar sistemas externos con interfaces incompatibles.
|
|
271
|
-
- **Saga**: Para transacciones distribuidas entre microservicios.
|
|
272
|
-
|
|
273
|
-
Documentar en un ADR qué patrón se usa y por qué.
|
|
274
|
-
|
|
275
|
-
---
|
|
276
|
-
|
|
277
|
-
## Tablas append-only — excepción documentada a "audit columns nullable=False"
|
|
278
|
-
|
|
279
|
-
Algunas tablas son **append-only por diseño**: solo se crean filas (INSERT) y
|
|
280
|
-
eventualmente se eliminan por purga (DELETE). Nunca se actualizan. Ejemplos
|
|
281
|
-
típicos: logs de errores (`bitacora_error`, `error_log`), audit trails inmutables,
|
|
282
|
-
telemetría, métricas históricas, event sourcing event store, outbox pattern.
|
|
283
|
-
|
|
284
|
-
Para estas tablas la regla general del proyecto "`created_by`/`updated_by`
|
|
285
|
-
`nullable=False` en tablas transaccionales" **NO aplica**. Documentar la
|
|
286
|
-
excepción explícitamente:
|
|
287
|
-
|
|
288
|
-
1. En el **docstring de la clase modelo** (Python/Java/C#):
|
|
289
|
-
|
|
290
|
-
```python
|
|
291
|
-
class BitacoraError(Base):
|
|
292
|
-
"""
|
|
293
|
-
Registro inmutable de un error backend o frontend.
|
|
294
|
-
|
|
295
|
-
Tabla append-only: solo se crean filas (INSERT) y se purgan por antigüedad
|
|
296
|
-
(DELETE). Nunca se actualizan. Esta invariante es fundamental para que el
|
|
297
|
-
log de errores sea un audit trail confiable.
|
|
298
|
-
|
|
299
|
-
Excepción a regla "audit columns nullable=False":
|
|
300
|
-
La convención del proyecto exige `created_by` y `updated_by` NOT NULL
|
|
301
|
-
en tablas transaccionales. BitacoraError queda exenta porque:
|
|
302
|
-
(a) Es un log del sistema, no una entidad de negocio modificable.
|
|
303
|
-
(b) No tiene `updated_at` ni `updated_by` — no hay concepto de
|
|
304
|
-
"última modificación" en una tabla append-only.
|
|
305
|
-
(c) `usuario_id` es nullable de forma intencional: los errores de
|
|
306
|
-
sesiones no autenticadas (401 antes del login) no tienen usuario.
|
|
307
|
-
"""
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
2. En el **comentario del DDL SQL**:
|
|
311
|
-
|
|
312
|
-
```sql
|
|
313
|
-
COMMENT ON TABLE bitacora_error IS
|
|
314
|
-
'Errores backend y frontend persistidos para diagnóstico. '
|
|
315
|
-
'Append-only: solo INSERT y DELETE (purga). '
|
|
316
|
-
'Sin updated_at/updated_by por diseño (excepción documentada en CONTEXTO).';
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
3. En el **GRANT** del rol de aplicación, omitir explícitamente `UPDATE`:
|
|
320
|
-
|
|
321
|
-
```sql
|
|
322
|
-
-- INSERT: para que el sistema cree entradas.
|
|
323
|
-
-- SELECT: para que el admin las consulte.
|
|
324
|
-
-- DELETE: para que el job de purga elimine antiguas.
|
|
325
|
-
-- NO UPDATE: la tabla es append-only por diseño.
|
|
326
|
-
GRANT SELECT, INSERT, DELETE ON bitacora_error TO ine_user;
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
**Criterios para considerar una tabla append-only legítima**:
|
|
330
|
-
|
|
331
|
-
- Toda fila representa un evento ocurrido en un momento específico (immutable in time).
|
|
332
|
-
- No hay caso de negocio que requiera modificar la fila después de creada.
|
|
333
|
-
- La única forma de "corregir" un dato erróneo es insertar una fila correctora
|
|
334
|
-
posterior (event sourcing) o purgar y re-insertar (telemetría).
|
|
335
|
-
- El borrado se hace por política de retención (antigüedad), no por revocación.
|
|
336
|
-
|
|
337
|
-
**Origen del patrón**: OIC v1.5 Slice 1 (2026-06-04). Patrón portable a cualquier
|
|
338
|
-
proyecto con logs estructurados, audit trails o event sourcing.
|
|
339
|
-
|
|
340
|
-
---
|
|
341
|
-
|
|
342
|
-
## Split modular con compositor por herencia múltiple
|
|
343
|
-
|
|
344
|
-
Cuando un módulo backend (router, service, repository) supera ~1500 LOC en un
|
|
345
|
-
solo archivo y contiene sub-dominios identificables, aplicar el playbook de
|
|
346
|
-
split documentado en `Skill("proceso-modular-split")`. El patrón clave:
|
|
347
|
-
|
|
348
|
-
- **Compositor por herencia múltiple, NO `__getattr__`**: el compositor (clase
|
|
349
|
-
monolítica que mantiene API pública previa) hereda de cada sub-service. MRO
|
|
350
|
-
inspeccionable, type checker feliz, IDE autocompleta. `__getattr__` para
|
|
351
|
-
delegación es opaco al tipado y al stack trace.
|
|
352
|
-
|
|
353
|
-
- **Helpers transversales en clase base, no duplicados entre sub-services**: si
|
|
354
|
-
un helper como `_validar_predio_existe` lo usan ≥80% de sub-services, vive
|
|
355
|
-
en `<modulo>/service_base.py` (`<Modulo>ServiceBase`). Cada sub-service
|
|
356
|
-
hereda de la base. Si solo lo usan 1-2 sub-services, vive en uno de ellos y
|
|
357
|
-
los demás importan por composición (no por herencia).
|
|
358
|
-
|
|
359
|
-
- **Helper transversal cross-sub-service NO se duplica**: validación que
|
|
360
|
-
aparece en ≥3 sub-services es candidata inmediata a la clase base. La
|
|
361
|
-
duplicación es señal de que el split fue prematuro o de que se perdió el
|
|
362
|
-
helper común durante la migración.
|
|
363
|
-
|
|
364
|
-
- **Validar a escala**: el patrón se validó a ~20,000 LOC totales en SIGM
|
|
365
|
-
(recaudación ADR-0016 + catastro ADR-0017). Aplicar al primer módulo es
|
|
366
|
-
prudente; antes de aplicar a un tercero, confirmar que el feedback de los
|
|
367
|
-
dos primeros no requiere ajuste al playbook.
|
|
368
|
-
|
|
369
|
-
Anti-patrones a evitar (las auditorías técnicas NO los detectan):
|
|
370
|
-
|
|
371
|
-
- Router que importa el compositor cuando existe sub-service específico.
|
|
372
|
-
- Router que accede a `servicio._repo` o métodos privados del sub-service.
|
|
373
|
-
- Default `None` pasado explícitamente bypasea el default del callee.
|
|
374
|
-
- CLAUDE.md y AGENTS.md desincronizados tras el refactor.
|
|
375
|
-
|
|
376
|
-
Estos los detecta revisión de arquitectura humana o senior, no `nemesis-auditor-swl`.
|
|
377
|
-
|
|
378
|
-
---
|
|
379
|
-
|
|
380
|
-
## Reglas de desempate entre principios (conflict resolution)
|
|
381
|
-
|
|
382
|
-
Los principios de ingeniería pueden entrar en tensión. Cuando dos reglas
|
|
383
|
-
correctas en abstracto sugieren caminos opuestos, aplicar las siguientes
|
|
384
|
-
heurísticas de desempate. Origen: síntesis adaptada de "Unified Software
|
|
385
|
-
Engineering" (M. Ciemborowicz, MIT) más experiencia operativa de SWL.
|
|
386
|
-
|
|
387
|
-
### Simplicidad vs. modelado rico
|
|
388
|
-
|
|
389
|
-
- Empezar con el diseño **más simple** que represente honestamente el problema.
|
|
390
|
-
- CRUD administrativo y workflows lineales: usar transaction script o
|
|
391
|
-
service layer simple.
|
|
392
|
-
- Reglas de negocio complejas, invariantes, ciclos de vida y lenguaje
|
|
393
|
-
específico del dominio: justificar modelado más rico (DDD táctico).
|
|
394
|
-
- NO usar patrones de DDD como ceremonia en subdominios genéricos.
|
|
395
|
-
- NO aplanar complejidad real del dominio en records pasivos y servicios
|
|
396
|
-
procedurales — eso lo único que hace es desplazar la complejidad al caller.
|
|
397
|
-
|
|
398
|
-
### Funciones pequeñas vs. módulos profundos
|
|
399
|
-
|
|
400
|
-
- Funciones pequeñas son una herramienta, no un objetivo en sí mismo.
|
|
401
|
-
- Preferir funciones pequeñas cuando clarifican intención, aíslan
|
|
402
|
-
responsabilidad o simplifican testing.
|
|
403
|
-
- Evitar cadenas de funciones triviales que solo pasan parámetros (pass-through)
|
|
404
|
-
y obligan al lector a saltar entre archivos para entender una operación.
|
|
405
|
-
- Un módulo puede tener implementación interna compleja siempre que su
|
|
406
|
-
interfaz pública sea pequeña, significativa y estable (módulo profundo).
|
|
407
|
-
|
|
408
|
-
### DRY vs. abstracción prematura
|
|
409
|
-
|
|
410
|
-
- DRY aplica a duplicación de **conocimiento**, no de texto.
|
|
411
|
-
- Centralizar reglas de negocio, validaciones, mappings y cálculos.
|
|
412
|
-
- Mantener código similar separado cuando la similitud es **coincidente**
|
|
413
|
-
o cuando la abstracción compartida sería vaga ("regla de tres" antes
|
|
414
|
-
de extraer).
|
|
415
|
-
- Tres líneas de código duplicado son mejores que una abstracción
|
|
416
|
-
prematura que después haya que romper.
|
|
417
|
-
|
|
418
|
-
### Boundaries vs. over-engineering
|
|
419
|
-
|
|
420
|
-
- Introducir boundaries explícitas alrededor de: volatilidad, sistemas
|
|
421
|
-
externos, persistencia, frameworks, tiempo, aleatoriedad y traducción
|
|
422
|
-
cross-context.
|
|
423
|
-
- NO agregar capas que solo reenvían llamadas (forwarding-only layers).
|
|
424
|
-
- Toda abstracción debe cumplir **al menos uno** de estos criterios:
|
|
425
|
-
reducir acoplamiento, ocultar complejidad, clarificar ownership, o
|
|
426
|
-
proteger un contrato. Si no cumple ninguno, eliminar la abstracción.
|
|
427
|
-
|
|
428
|
-
### Consistencia fuerte vs. eventual
|
|
429
|
-
|
|
430
|
-
- Proteger invariantes que **deben** cumplirse de forma inmediata dentro
|
|
431
|
-
del menor boundary de consistencia útil.
|
|
432
|
-
- Default razonable: un aggregate o una transacción local como unidad
|
|
433
|
-
atómica.
|
|
434
|
-
- Usar consistencia eventual entre aggregates, servicios o contextos
|
|
435
|
-
cuando la consistencia inmediata no sea un requisito real de negocio.
|
|
436
|
-
- Hacer **siempre explícitas** las semánticas de consistencia, staleness,
|
|
437
|
-
conflicto y retry — nunca implícitas.
|
|
438
|
-
|
|
439
|
-
### Comentarios vs. código auto-documentado
|
|
440
|
-
|
|
441
|
-
- Mejorar nombres y estructura **antes** de agregar comentarios.
|
|
442
|
-
- Comentarios válidos: contratos, invariantes, racional de decisiones
|
|
443
|
-
no-obvias, restricciones legales o regulatorias, asunciones sobre
|
|
444
|
-
protocolos externos.
|
|
445
|
-
- Eliminar comentarios que narran código obvio, repiten nombres o
|
|
446
|
-
describen comportamiento obsoleto.
|
|
447
|
-
|
|
448
|
-
### Refactor vs. preservar comportamiento
|
|
449
|
-
|
|
450
|
-
- Refactoring debe preservar el comportamiento observable. Sin excepciones.
|
|
451
|
-
- Si el comportamiento debe cambiar, mantener el cambio funcional **separado
|
|
452
|
-
del refactor estructural** cuando sea práctico (commits independientes).
|
|
453
|
-
- Preferir transformaciones pequeñas y verificables sobre rewrites grandes.
|
|
32
|
+
- **S**: una clase/módulo, un eje de cambio.
|
|
33
|
+
- **O**: extender sin modificar (composición/strategy, no if/else interminables).
|
|
34
|
+
- **L**: el subtipo honra el contrato del supertipo — sin excepciones nuevas ni parámetros ignorados.
|
|
35
|
+
- **I**: varias interfaces pequeñas antes que una grande; no forzar métodos sin uso.
|
|
36
|
+
- **D**: depender de abstracciones, no de implementaciones concretas.
|
|
454
37
|
|
|
455
|
-
|
|
38
|
+
## Repos externos y tablas append-only
|
|
456
39
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
aplica, escalar al `arquitecto-swl` con la disyuntiva concreta y dos
|
|
460
|
-
opciones evaluadas. Documentar la decisión en un ADR si tiene impacto
|
|
461
|
-
estructural.
|
|
40
|
+
- Análisis de repositorios externos: aplicar el filtro de dominio PRIMERO (*¿le sirve a un ingeniero de software en cualquier proyecto?*); si el dominio es vertical externo, descartar 80-95% del contenido sin análisis profundo.
|
|
41
|
+
- Tablas append-only (logs, audit trails, telemetría, event store): excepción documentada a "audit columns `nullable=False`" — documentar en docstring del modelo + `COMMENT` del DDL + GRANT sin `UPDATE`.
|
|
462
42
|
|
|
463
|
-
|
|
43
|
+
## Desempates entre principios
|
|
464
44
|
|
|
465
|
-
|
|
45
|
+
- Simplicidad vs. modelado rico → empezar con lo más simple que represente honestamente el problema; DDD táctico solo ante reglas de negocio complejas reales, nunca como ceremonia.
|
|
46
|
+
- Funciones pequeñas vs. módulos profundos → funciones pequeñas son herramienta, no meta; evitar cadenas pass-through que solo pasan parámetros.
|
|
47
|
+
- DRY vs. abstracción prematura → centralizar conocimiento; tres líneas duplicadas ganan a una abstracción que habrá que romper.
|
|
48
|
+
- Boundaries vs. over-engineering → un boundary solo si reduce acoplamiento, oculta complejidad, clarifica ownership o protege un contrato; sin capas forwarding-only.
|
|
49
|
+
- Consistencia fuerte vs. eventual → fuerte dentro del menor boundary útil (aggregate/transacción local); eventual entre aggregates; semánticas siempre explícitas.
|
|
50
|
+
- Comentarios vs. código auto-documentado → mejorar nombres/estructura antes de comentar; comentarios solo para contratos, invariantes y racional no obvio.
|
|
51
|
+
- Refactor vs. preservar comportamiento → el refactor preserva el comportamiento observable sin excepciones; el cambio funcional va separado del estructural.
|
|
52
|
+
- Si ninguna heurística aplica: escalar a `arquitecto-swl` con dos opciones evaluadas; documentar en ADR si hay impacto estructural.
|
|
466
53
|
|
|
467
|
-
|
|
468
|
-
- [ ] ¿El módulo nuevo tiene una interfaz más pequeña que su implementación?
|
|
469
|
-
- [ ] ¿Las dependencias fluyen en una sola dirección?
|
|
470
|
-
- [ ] ¿Hay separación clara de concerns entre capas?
|
|
471
|
-
- [ ] ¿El módulo puede testearse de forma aislada?
|
|
472
|
-
- [ ] ¿Se revisaron ADRs existentes para no contradecirlos?
|
|
473
|
-
- [ ] ¿No hay duplicación de lógica de negocio entre módulos o capas?
|
|
474
|
-
- [ ] Si dos principios entran en tensión, ¿se aplicó la regla de
|
|
475
|
-
desempate correspondiente y la decisión está justificada?
|
|
54
|
+
Detalle extendido (template ADR, ejemplos de código, split modular con compositor, checklists): `Skill("meta-reglas-extendido")` → `recursos/arquitectura.md`.
|