# 17 — Contexto para IA

> **Lee este documento completo antes de tocar una sola línea de código de este proyecto.**
> Está diseñado para ser el único documento imprescindible: contiene lo esencial y enlaza al resto.

---

## Identidad del proyecto

| | |
|---|---|
| **Nombre** | Kuorum (también "HR Kuorum") |
| **Qué es** | Plataforma web de gestión del talento humano (HRIS/HCM) para empresas colombianas |
| **Autor** | Klee Software |
| **Framework** | **Propietario ("Klee")**. No es Laravel, ni Symfony, ni CodeIgniter, ni ningún framework conocido |
| **Lenguaje** | PHP (mínimo real 7.4; probado en 8.5). **Sin namespaces. Sin `strict_types`** |
| **Base de datos** | MySQL 8 (`utf8mb4_0900_ai_ci`) |
| **Frontend** | Metronic 8.0.23 Demo 1 + jQuery + Bootstrap 5 + DataTables. **Sin build tooling, sin `package.json`** |
| **Idioma del código** | Español (nombres de método, comentarios, mensajes) |
| **Zona horaria** | `America/Bogota`, fijada en código |

---

## Arquitectura en 10 líneas

```
Navegador  →  ?c=Controlador&a=accion
           →  public/index.php  (solo define constantes)
           →  core/AutoLoad.php (bootstrap + despacho reflexivo)
           →  new {Controlador}Controller  →  ->process()
                 ├─ validateAccess(accion)      ← autorización, en el CONSTRUCTOR y en process()
                 └─ ->{accion}Action()
                       →  XxxModel::getAll(campos, criteria, filtros)
                             →  MysqlPDO  →  SQL por CONCATENACIÓN DE CADENAS  →  PDO
                       →  View::render_view('carpeta/vista', $parameters)
                             →  app/layouts/metronic.php  →  include $content
```

**No existe:** router declarativo, middleware, ORM, contenedor de dependencias, traits, repositorios, multi-tenancy activo, `Request`/`Response`, `EventDispatcher`, `MailService`, `TenantContext`, `app/config/Modules.php`, `bin/make module`.

Detalle completo: [02_ARCHITECTURE.md](02_ARCHITECTURE.md)

---

## Estructura

```
app/
├── config/       Config.php · ConfigEnv.php · Menu.php · QuickActionsConfig.php · Titles.php
├── controllers/  75 controladores  {Nombre}Controller.php
├── models/       139 ficheros: 127 modelos + 12 servicios
├── views/        291 vistas PHP, una carpeta por módulo
└── layouts/      8 layouts + parciales (menus/ shortcuts/ flashes/ logs/ alerts/)
core/             Framework: Controller · Model · View · Router · Db · ListaAjax · 26 atributos · helpers
services/         asistente_ia/ · llm/ · prompt/   (único código con interfaces e inyección)
database/         migrations/ (41) · seeders/ (39 + support/) · Migrator.php · README.md ✅
bin/              migrate · seed · make-migration · make-seeder
public/           index.php · assets/ · metronic_html_v8.0.23_demo1/
files/            Adjuntos y logotipos (ESCRIBIBLE, accesible por HTTP)
storage/cache/    classmap.php + caché (ESCRIBIBLE)
tests/            13 ficheros PHPUnit
docs/knowledge/   ← esta base de conocimiento
```

Detalle: [03_PROJECT_STRUCTURE.md](03_PROJECT_STRUCTURE.md)

---

## Módulos (24)

Inicio/Dashboard · **Colaboradores** · Reclutamiento y Selección · **Metas** · Evaluación 360 · Competencias/Preguntas/Escalas · Planes de Desarrollo · Capacitación (LMS) · **Mapa de Talento 9-Box** · Planes de Carrera · Sucesión · Reconocimientos · **Vacaciones** · **Nómina** · Adelantos de Nómina · Control de Asistencia · **Beneficios** · Servicio al Colaborador (Tickets) · **Línea de Ética** · Comunicación Interna · Mi Equipo · Portal del Colaborador · Configuración y Administración · Asistente IA

Detalle: [04_MODULES.md](04_MODULES.md)

---

## Entidades principales

| Entidad | Tabla | Papel |
|---|---|---|
| **Colaborador** | `colaboradores` | **La entidad raíz.** 20+ tablas la referencian. Autoreferencia por `IdJefeInmediato` |
| **Usuario** | `usuarios` | Cuenta del backoffice. **Distinta de Colaborador** |
| **Rol** | `roles` | 3 filas: Administrador (1), Analista (2), Colaborador (5) |
| **Permiso** | `permisos` | JSON por rol y módulo |
| **Periodo** | `periodos` | Eje temporal de metas y evaluación. 36 columnas de configuración |
| **Meta** | `metas` | Objetivo individual con peso |
| **Evaluación** | `evaluaciones` + `respuestas` | 360 multi-fuente |
| **Solicitud** | 5 tablas distintas | Vacaciones, beneficios, adelantos, ausencias, tickets |

---

## Base de datos

- **124 tablas base + 62 vistas SQL + 75 claves foráneas**
- Los modelos leen de `$VIEW_NAME` (`vista_*`) y escriben en `$TABLE_NAME`
- **`Estado = 0` es borrado lógico**, no eliminación
- **🔴 Reclutamiento, metas, evaluaciones, vacaciones, nómina y auditoría NO tienen claves foráneas declaradas.** La integridad depende del código
- Cinco migraciones sin aplicar en la base de desarrollo actual

### 🔴 Dos estilos de clave foránea coexistiendo

| Estilo | Módulos |
|---|---|
| `IdColaborador`, `IdPeriodo` | metas, evaluaciones, planes de desarrollo, vacaciones, competencias |
| `ColaboradorId`, `PeriodoId` | asistencia, beneficios, adelantos, capacitación, tickets, carrera, sucesión, nómina, comunicación |

**Comprueba siempre qué estilo usa la tabla antes de escribir una consulta.**

Detalle: [05_DATABASE.md](05_DATABASE.md)

---

## Reglas de negocio críticas

| Dominio | Regla que no se puede romper |
|---|---|
| **Metas** | La suma de pesos por colaborador y periodo ≤ 100 %; **exactamente 100 %** para enviar a revisión y para aprobar. Solo se editan en `borrador` o `rechazada` |
| **Vacaciones** | No puede haber cruce de fechas. Sin saldo suficiente no se aprueba, salvo `PermiteSaldoNegativo`. Los días hábiles descuentan festivos |
| **Nómina** | `Neto = Devengado − Deducción`. El orden de los conceptos importa (`TOTAL_DEVENGADO` es acumulado parcial). Una sola liquidación por (periodo, colaborador) |
| **Talento** | `Consolidado = 0.5 × Desempeño + 0.5 × Potencial`; `Potencial = 0.6 × criterios + 0.4 × 360` |
| **Reclutamiento** | Contratar exige oferta `ACEPTADA`. Rechazar exige motivo. La etapa destino debe pertenecer al embudo de esa vacante |
| **Beneficios** | Las reglas de **exclusión tienen prioridad absoluta** sobre las de inclusión. Sin cupo o presupuesto, no se aprueba |
| **Adelantos** | 11 validaciones contra la política activa (antigüedad, % de salario, cupos mensuales, días entre solicitudes) |
| **Tickets** | El SLA se resuelve por prioridad. Vencido si supera **cualquiera** de los dos umbrales |
| **Línea de ética** | El PIN se hashea con `password_hash` y **no es recuperable**. `archivado` es terminal absoluto |
| **Asistencia** | No se marca con vacaciones o ausencia aprobada. Salida sin entrada se rechaza. Salida anterior a la entrada → `inconsistente` |

Detalle completo con referencias al código: [10_BUSINESS_LOGIC.md](10_BUSINESS_LOGIC.md)

---

## Las 12 convenciones que hay que respetar

| # | Convención | Consecuencia de ignorarla |
|---|---|---|
| 1 | **Toda acción va declarada en `loadAccessControl()`** | Es inaccesible incluso para el administrador |
| 2 | Nombres de input **`Modelo[Campo]`** | El formulario no guarda nada y no da error |
| 3 | `loadById()` **antes** de `save()` en la edición | Crea un registro nuevo en lugar de actualizar |
| 4 | `$parameters = $this->loadMetadata()` antes de renderizar | El layout se queda sin menú, marca ni permisos |
| 5 | `Controller::generateCsrfToken()` en toda vista con formulario | "Token de seguridad inválido" |
| 6 | POST-Redirect-GET con `UserFlash` tras cada escritura | Reenvío al recargar |
| 7 | Estados en **constantes `ESTADO_*`**, nunca literales | |
| 8 | Tabla `*_historial` para todo flujo de estados | Patrón consolidado en 7 módulos |
| 9 | **Castear toda entrada** antes de meterla en un criterio | 🔴 Inyección SQL: `criteriaToSql()` no escapa |
| 10 | Pasar **`array()`** como tercer argumento para desactivar los filtros de sesión | Resultados vacíos inexplicables |
| 11 | `Menu::setActive('nombre')` al inicio del listado | El menú no marca la sección |
| 12 | Recrear la vista SQL en la misma migración que altera la tabla | Los modelos leen de la vista y quedaría obsoleta |

---

## Patrones que hay que reutilizar

| Necesitas | Usa |
|---|---|
| Un listado paginado | **`ListaAjax`**. No escribas tablas a mano |
| Un CRUD | Copia `CompetenciasController` (130 líneas) + `CompetenciasModel` + `app/views/competencias/` |
| Un mensaje al usuario | `UserFlash::setFlash('Success'\|'Error'\|'Warning', $texto)` |
| Una validación de negocio | Método estático que devuelva `['ok' => bool, 'errores' => []]` |
| Un cálculo de talento | `TalentScoreService` |
| Registro | `Logger::error()` / `LoggerManager::logAction()` |
| Caché | `Cache::setWithNamespace($clave, $valor, $ttl, $namespace)` |
| Auditoría de dominio | `BitacoraAuditoriaModel::registrar()` |
| Una utilidad de texto, fecha, número o dinero | `core/helpers/` — **búscala antes de escribirla** |
| Un endpoint JSON | Copia el patrón de `AsistenteIAController` (`jsonResponse()`) |
| Un historial de cambios | `(entidadId, Accion, ValorAnterior, ValorNuevo, UsuarioId, CreatedAt)` |

---

## ⛔ Lo que NO debes hacer

| # | Prohibición | Motivo |
|---|---|---|
| 1 | **Creer la documentación de `docs/0X_*.md` y `docs/AI_MODULE_DEVELOPMENT_GUIDE.md`** | 🔴 Describen otro producto ("KleePlanner2"): `Request`, `Response`, middleware, traits, `Modules.php`, `bin/make module`… **nada de eso existe aquí.** Ver [18_KNOWN_ISSUES.md](18_KNOWN_ISSUES.md) § HR-DOC-1 |
| 2 | Introducir namespaces | El autoload resuelve por nombre de fichero |
| 3 | Escribir SQL en un controlador o en una vista | Rompe la separación de capas |
| 4 | Interpolar entrada de usuario en un criterio sin castear | Inyección SQL |
| 5 | Editar o renombrar una migración ya aplicada | Rompe el historial de despliegues |
| 6 | Poner datos de catálogo en una migración | Van en semillas |
| 7 | Cambiar el contrato `?c=&a=` | Depende de él el menú, los permisos, DataTables, quick-search y 291 vistas |
| 8 | Redeclarar en `ConfigEnv.php` una propiedad que gestione el `.env` | PHP crea un almacenamiento separado y el `.env` se ignora **en silencio** |
| 9 | Renombrar `IdColaborador` ↔ `ColaboradorId` sin migración | 20+ tablas dependen del nombre actual |
| 10 | Modificar una tabla con vista sin recrear la vista | Los modelos leen de la vista |
| 11 | Crear un `cleanText()` número 22 | Ya está duplicado 21 veces |
| 12 | Añadir un `eval()` | Ya hay uno en `NominaCalculoModel` y es un riesgo conocido |
| 13 | "Arreglar" `SincronizacionController`, `AjaxController::getAll` o `AlertasController` creando las clases que faltan | Es legado de un producto de evaluación docente. Lo correcto casi siempre es **eliminar** |
| 14 | Confiar en `CSRF_STRICT`, `IP_BLOCKING`, `NO_COPY`, `CAMBIO_ROL`, `LOGIN_AUTOMATICO` o `MAIL_DIARIOS_MAX` | 🔴 **Ninguna tiene efecto en el código** |
| 15 | Poner `APP_DEBUG=true`, `DEMO_MODE_ENABLED=true` o `DIRECTORIO_ACTIVO=true` en producción | Volcado de SQL al navegador · siembra en la base real y suplantación · error fatal (falta `DirectorioActivoModel`) |
| 16 | Refactorizar la arquitectura para "modernizarla" | El proyecto es coherente consigo mismo. Un refactor parcial lo rompe |
| 17 | Duplicar lógica que ya existe en `TalentScoreService`, `NominaCalculoModel` o `core/helpers/` | |
| 18 | Cambiar `APP_ID` sin avisar | Invalida **todas** las sesiones abiertas |

---

## Dependencias entre módulos

```
                        colaboradores  ← 20+ tablas
                              ↑
       ┌──────────────────────┼──────────────────────┐
   reclutamiento          periodos              cargos/areas/sedes
   (alta del                  ↑                       ↑
    colaborador)   ┌──────────┴──────────┐      carrera / sucesión
                 metas              evaluaciones
                   └──────────┬──────────┘
                     metas_consolidado
                              ↓
                      TalentScoreService
                              ↓
                    potencial_evaluaciones (9-Box)
                              ↓
                     planes_desarrollo
```

Módulos **independientes** entre sí (solo dependen de `colaboradores`): vacaciones, asistencia, nómina, adelantos, beneficios, capacitación, tickets, comunicación interna, reconocimientos.
Módulo **totalmente independiente**: línea de ética (anónima, no requiere colaborador).

Detalle: [19_DEPENDENCY_MAP.md](19_DEPENDENCY_MAP.md)

---

## Flujos críticos

| Flujo | No lo rompas |
|---|---|
| **Login (×2)** | Backoffice (`usuarios`) y portal (`colaboradores`, con periodo). Cargan permisos y menú **en la sesión** |
| **Ciclo de metas** | borrador → en_revision → aprobada → cerrada, con la regla del 100 % |
| **Cálculo de talento** | Metas + 360 → `TalentScoreService` → 9-Box → plan de desarrollo |
| **Aprobación de vacaciones** | Cambio de estado + descuento de saldo (⚠️ **sin transacción**) |
| **Liquidación de nómina** | Conceptos → fórmulas → liquidación + detalle |
| **Contratación** | Postulación → etapas → oferta aceptada → contratado → colaborador activo |

Diagramas: [11_WORKFLOWS.md](11_WORKFLOWS.md)

---

## Ficheros críticos

Modificar cualquiera afecta a todo el sistema:

```
core/AutoLoad.php          Bootstrap y despacho. El orden de require importa
core/Controller.php        Autorización y CSRF de los 75 controladores
core/Model.php             Persistencia de los 127 modelos
core/db/MysqlPDO.php       Todo el acceso a datos
core/Router.php            Todos los enlaces y redirecciones
core/View.php              Todo el renderizado
core/ListaAjax.php         Todos los listados
app/config/Config.php      Configuración global; syncConfigFromEnv() es el único puente con el .env
app/config/Menu.php        La navegación de ambos portales
app/models/PermisosModel.php + UsuariosModel.php   La autorización
app/models/ColaboradoresModel.php   La entidad central (676 líneas)
app/models/TalentScoreService.php   El cálculo de talento (746 líneas)
app/layouts/metronic.php + metronic_public.php     La interfaz completa
.env                       Sin DB_NAME no arranca
```

---

## Riesgos que debes conocer antes de tocar nada

| 🔴 | Riesgo |
|---|---|
| 1 | **`criteriaToSql()` no escapa los valores.** Toda entrada de usuario debe castearse antes de entrar en un criterio |
| 2 | **`criteriaExt` permite al cliente inyectar criterios arbitrarios** en cualquier `dataListAjax` |
| 3 | **`dataListAjax` está exento de permisos** (`Config::$actionsGeneral`) |
| 4 | **Las contraseñas son MD5 sin sal** |
| 5 | **La traza de excepción se imprime al usuario, siempre**, independientemente de `APP_DEBUG` |
| 6 | **Hay un `eval()`** en `NominaCalculoModel::safeEvalFormula()` |
| 7 | **20 clases referenciadas no existen** — cualquier ruta que las alcance produce error fatal |
| 8 | **Ningún flujo de negocio usa transacciones** (salvo `deleteCascade`) |
| 9 | **No hay verificación centralizada de propiedad de registro** (IDOR) |
| 10 | **`vista_colaboradores` expone la columna `Contrasena`** |

Detalle y priorización: [18_KNOWN_ISSUES.md](18_KNOWN_ISSUES.md)

---

## Procedimiento antes de modificar código

```
 1. Identificar el módulo afectado                    → 04_MODULES.md
 2. Leer sus reglas de negocio                        → 10_BUSINESS_LOGIC.md
 3. Seguir su traza funcionalidad→tabla               → 21_TRACEABILITY.md
 4. Abrir el controlador, el modelo y las vistas que ya existen
 5. Comprobar el estilo de FK de la tabla (IdX vs XId)
 6. Comprobar si la tabla tiene vista_*  →  si la alteras, recréala
 7. Buscar un módulo equivalente e imitarlo
 8. Verificar que no duplicas algo de core/helpers/ o de un *Service
 9. Escribir el cambio respetando las 12 convenciones
10. Declarar cada acción nueva en loadAccessControl()
11. Sembrar los permisos si el módulo es nuevo
12. Castear toda entrada de petición
13. Registrar los cambios de estado en la tabla *_historial del módulo
14. Evaluar si el flujo necesita transacción
15. php bin/migrate status  ·  php bin/seed --validate  ·  composer test
16. Cerrar sesión y volver a entrar si tocaste Menu.php o permisos
17. Actualizar docs/knowledge/
```

---

## Comandos que necesitarás

```bash
# Base de datos
php bin/migrate status | up | down | validate
php bin/seed [base|modulos|completo|ClaseSeeder] | --list | --validate | --verify-demo
php bin/make-migration descripcion_en_snake_case
php bin/make-seeder <0xx|1xx|2xx> nombre_snake_case [tabla]

# Pruebas
composer test

# Depuración
rm -f storage/cache/classmap.php          # invalidar el autoload
find app core -name "*.php" -exec php -l {} \; | grep -v "No syntax"
```

> ⚠️ **`bin/migrate` no carga el `.env`** (a diferencia de `bin/seed`) y su respaldo lee `DB_PASS`, no `DB_PASSWORD`. Si no conecta:
> ```bash
> export DB_HOST=localhost DB_NAME=kuorum DB_USER=<u> DB_PASS='<p>'
> php bin/migrate up
> ```

---

# AI DEVELOPMENT RULES

Reglas explícitas para cualquier agente que trabaje sobre este proyecto.

## Sobre la arquitectura

1. **No inventes arquitectura.** Este proyecto usa un framework propietario con un contrato de URL `?c=&a=`, modelos con `getOptionsAttributes()` y vistas PHP planas. No hay middleware, ni ORM, ni router declarativo, ni namespaces. Si tu solución necesita alguno de esos elementos, la solución es incorrecta.
2. **No confíes en `docs/0X_*.md` ni en `docs/AI_MODULE_DEVELOPMENT_GUIDE.md`.** Describen un producto distinto. La fuente de verdad es el código y `docs/knowledge/`.
3. **No crees un patrón nuevo si ya existe uno equivalente.** Antes de escribir, busca cómo lo resuelve otro módulo.
4. **No refactorices la arquitectura para modernizarla.** El proyecto es internamente coherente; un refactor parcial lo rompe. Si detectas una mejora estructural, propónla, no la ejecutes.

## Sobre la reutilización

5. **Reutiliza los servicios existentes:** `TalentScoreService`, `NominaCalculoModel`, `CalculadorProgresoPlanService`, `ScoringCandidatosService`, `ContratacionDesdeOfertaService`, `GeneradorPlanesDesarrolloService`.
6. **Reutiliza los helpers de `core/helpers/`** antes de escribir una utilidad de texto, fecha, número, dinero o imagen.
7. **Reutiliza `ListaAjax` para todo listado.** No escribas tablas HTML a mano.
8. **No dupliques lógica.** Si algo aparece dos veces, promuévelo — salvo que el proyecto ya lo haya duplicado (`cleanText()` ×21): en ese caso, no añadas la copia 22, propón la extracción.

## Sobre los contratos

9. **No cambies el contrato de URL `?c=&a=`.** Dependen de él el menú, los permisos, DataTables, quick-search y 291 vistas.
10. **No cambies el contrato de formulario `Modelo[Campo]`.** Es lo que lee `Atributo::receiveData()`.
11. **No modifiques la firma de los métodos de `core/Model.php` ni de `core/Controller.php`** sin revisar a los 202 consumidores.
12. **No cambies el formato JSON de `dataListAjax`.** DataTables depende de las claves `draw`, `recordsTotal`, `recordsFiltered`, `data`.

## Sobre la base de datos

13. **No alteres el esquema sin migración**, y hazlo siempre con `bin/make-migration`.
14. **No edites ni renombres una migración ya aplicada.** Corrige con una nueva.
15. **Si alteras una tabla con vista, recrea la vista en la misma migración.**
16. **No renombres columnas de clave foránea** para unificar los dos estilos sin una migración planificada.
17. **Registra la clave de negocio** de toda tabla nueva con semilla en `ClavesDeNegocio.php`, y garantiza el índice único: hay un test que lo verifica.
18. **Los datos de catálogo van en semillas**, no en migraciones.

## Sobre la seguridad

19. **Castea o limpia toda entrada de `$_GET`/`$_POST`** antes de que llegue a un criterio. `criteriaToSql()` no escapa.
20. **Declara cada acción nueva en `loadAccessControl()`.** Sin eso es inaccesible.
21. **Valida CSRF a mano en toda mutación**, salvo `remove` (que ya lo impone el framework) y `Model::save()`.
22. **Comprueba la propiedad del registro** cuando la acción sea del portal del colaborador. No hay verificación automática.
23. **Añade la clase y la acción a `Controller::$PUBLIC_COLLABORATOR_ROUTES`** si el módulo es del portal.
24. **No devuelvas el mensaje de una excepción al usuario.** Regístralo con `Logger::error()`.
25. **No introduzcas `eval()`, `exec()`, `system()` ni deserialización de entrada no confiable.**
26. **No añadas secretos al código.** Van en `.env` y se cargan en `Config::syncConfigFromEnv()`.

## Sobre el alcance

27. **No elimines funcionalidad sin autorización explícita**, ni siquiera la que parezca muerta. Repórtala.
28. **No "arregles" el legado docente** creando las 20 clases que faltan. Repórtalo y espera decisión.
29. **Mantén la compatibilidad** con los módulos existentes: comprueba quién consume lo que vas a cambiar.
30. **Si detectas un problema fuera del alcance de tu tarea, documéntalo**, no lo corrijas sobre la marcha.

## Sobre el estilo

31. **Respeta la nomenclatura del módulo en el que trabajas.** Los antiguos usan `list/create/edit/view` en inglés; los nuevos `index/crear/ver` en español. Imita el que tengas delante.
32. **Escribe los comentarios y los mensajes al usuario en español.**
33. **Usa `array()`** si el fichero que editas lo usa.
34. **Usa constantes `ESTADO_*`** para los estados, nunca literales sueltos.
35. **Escapa con `htmlspecialchars()`** todo valor que imprimas en una vista.

## Antes de terminar

36. **Ejecuta `php bin/migrate status`, `php bin/seed --validate` y `composer test`.**
37. **Verifica que la acción sea alcanzable**: declarada en `loadAccessControl()` y con permiso en la tabla `permisos`.
38. **Si tocaste `Menu.php` o los permisos, indica al usuario que debe cerrar sesión y volver a entrar** — están congelados en la sesión.
39. **Actualiza `docs/knowledge/`** con lo que hayas cambiado.
40. **Informa con precisión de lo que hiciste y de lo que no.** Si algo quedó fuera, dilo explícitamente.

---

## Documentos relacionados

| Documento | Cuándo consultarlo |
|---|---|
| [00_INDEX.md](00_INDEX.md) | Navegación general |
| [02_ARCHITECTURE.md](02_ARCHITECTURE.md) | Antes de tocar el core |
| [04_MODULES.md](04_MODULES.md) | Al trabajar en cualquier módulo |
| [05_DATABASE.md](05_DATABASE.md) | Antes de tocar el esquema |
| [10_BUSINESS_LOGIC.md](10_BUSINESS_LOGIC.md) | **Siempre, antes de cambiar comportamiento** |
| [14_DEVELOPMENT_GUIDELINES.md](14_DEVELOPMENT_GUIDELINES.md) | Plantillas de código listas para copiar |
| [18_KNOWN_ISSUES.md](18_KNOWN_ISSUES.md) | Para no reintroducir un problema conocido |
| [21_TRACEABILITY.md](21_TRACEABILITY.md) | Para ir de una funcionalidad al código responsable |
