# DIRECTIVA: POLÍTICA DE CARGA LIMPIA (Clean Load Policy)

**Proyecto:** GAMILIT - Sistema de Gamificación Educativa
**Versión:** 1.0.0
**Fecha:** 2025-11-23
**Ámbito:** Database-Agent y todos los desarrolladores
**Tipo:** Directiva Obligatoria
**Stack:** PostgreSQL 15+ con PostGIS

---

## 🎯 PROPÓSITO

Garantizar que la base de datos pueda **recrearse completamente desde archivos DDL** en cualquier momento, sin dependencia de scripts incrementales, migrations o fixes.

Esta política establece que:
- ✅ Los **archivos DDL son la fuente de verdad**
- ✅ La **base de datos es el resultado** de ejecutar esos archivos
- ✅ Todo cambio se valida mediante **recreación completa**
- ❌ **No se usan migrations** ni scripts incrementales

---

## 📜 REGLAS OBLIGATORIAS

### 1. DDL-First Approach

**Principio:** Los archivos DDL se crean/actualizan ANTES de modificar la base de datos.

#### ✅ FLUJO CORRECTO

```
1. Crear/actualizar archivo DDL
   └─> apps/database/ddl/schemas/{schema}/{tipo}/{archivo}.sql

2. Validar sintaxis del archivo DDL
   └─> Revisar manualmente o con linter SQL

3. Ejecutar recreación completa
   └─> ./apps/database/drop-and-recreate-database.sh

4. Si funciona → Commitear archivo DDL
   └─> git add apps/database/ddl/...
   └─> git commit -m "feat(db): descripción del cambio"

5. Si falla → Corregir DDL y volver a paso 3
   └─> NO ejecutar fixes manuales en BD
   └─> Corregir archivo DDL
```

#### ❌ FLUJO PROHIBIDO

```
❌ 1. Ejecutar ALTER TABLE directamente en psql
❌ 2. "Documentar" el cambio creando archivo DDL después
❌ 3. Esperar que funcione en producción
❌ 4. Crear migration incremental para aplicar cambio
```

**Razón de prohibición:**
- La BD y el DDL quedan desincronizados
- No hay garantía de que el cambio funcione en recreación limpia
- Otros desarrolladores no pueden recrear la BD localmente
- Riesgo alto en producción (cambio no validado)

---

### 2. Prohibición de Migrations

**PROHIBIDO crear o usar:**

```yaml
❌ Carpeta migrations/:
  - apps/database/migrations/
  - Archivos estilo TypeORM/Prisma migrations
  - Archivos versionados tipo: 001-create-users.sql, 002-add-column.sql

❌ Scripts incrementales:
  - migration-*.sql
  - alter-*.sql
  - update-*.sql
  - change-*.sql

❌ Estrategia ALTER TABLE como cambio principal:
  - ALTER TABLE ... ADD COLUMN (sin actualizar DDL base)
  - ALTER TABLE ... DROP COLUMN (sin actualizar DDL base)
  - ALTER TABLE ... MODIFY COLUMN (sin actualizar DDL base)
```

#### ¿Por qué NO migrations?

**Problemas de migrations incrementales:**
1. ❌ **Orden de ejecución:** Difícil de mantener, errores si se ejecuta fuera de orden
2. ❌ **Estado de BD desconocido:** No sabes si migration ya se aplicó o no
3. ❌ **Recreación imposible:** No puedes crear BD limpia sin ejecutar todas las migrations en orden
4. ❌ **Dependencias complejas:** Migrations dependen de migrations anteriores
5. ❌ **Debugging difícil:** Difícil saber en qué migration está el problema
6. ❌ **Rollback riesgoso:** Difícil revertir migrations sin perder datos

**Ventajas de carga limpia:**
1. ✅ **Fuente de verdad clara:** DDL es el estado actual, siempre
2. ✅ **Recreación simple:** `./drop-and-recreate-database.sh` y listo
3. ✅ **Sin estado:** No importa el estado anterior de la BD
4. ✅ **Debugging fácil:** Error en recreación = DDL tiene problema
5. ✅ **Onboarding rápido:** Nuevos devs crean BD en 1 comando
6. ✅ **Testing robusto:** Tests siempre empiezan con BD limpia

---

### 3. Prohibición de Fixes y Patches

**PROHIBIDO crear:**

```yaml
❌ Archivos de corrección única (one-time scripts):
  - fix-*.sql
  - patch-*.sql
  - hotfix-*.sql
  - repair-*.sql
  - cleanup-*.sql

❌ Scripts "temporales" que se vuelven permanentes:
  - temp-fix-users.sql
  - manual-update-points.sql
  - data-correction-2025-11-23.sql
```

#### ¿Qué hacer en lugar de fix/patch?

**Escenario 1: Error en DDL**

```markdown
❌ INCORRECTO:
1. Crear fix-missing-column.sql con ALTER TABLE
2. Ejecutar fix en BD
3. "Ya funciona, no tocar"

✅ CORRECTO:
1. Identificar archivo DDL original con error
   └─> apps/database/ddl/schemas/auth_management/tables/01-users.sql
2. Corregir DDL (agregar columna faltante en CREATE TABLE)
3. Validar con recreación completa: ./drop-and-recreate-database.sh
4. Commitear DDL corregido
```

**Escenario 2: Datos incorrectos en seeds**

```markdown
❌ INCORRECTO:
1. Crear fix-seed-data.sql con UPDATE/INSERT
2. Ejecutar fix en BD
3. Dejar seed original con datos incorrectos

✅ CORRECTO:
1. Identificar archivo seed con error
   └─> apps/database/seeds/dev/auth_management/01-users.sql
2. Corregir seed (arreglar datos)
3. Validar con recreación completa: ./drop-and-recreate-database.sh
4. Commitear seed corregido
```

**Escenario 3: Error en producción**

```markdown
❌ INCORRECTO:
1. Ejecutar fix directo en BD de producción
2. "Olvidar" actualizar DDL
3. Siguiente deploy rompe porque DDL está desactualizado

✅ CORRECTO:
1. Corregir DDL en desarrollo
2. Validar con recreación completa local
3. Crear ADR documentando el cambio
4. Aplicar cambio en producción usando DDL corregido
5. Commitear DDL + ADR
```

---

### 4. Cambios en Tablas Existentes

#### ✅ PROCESO CORRECTO para Cambios

**Ejemplo: Agregar columna a tabla existente**

```bash
# 1. Actualizar DDL base (NO crear migration)
vim apps/database/ddl/schemas/auth_management/tables/01-users.sql

# Cambiar de:
CREATE TABLE auth_management.users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    username VARCHAR(50) NOT NULL,
    email VARCHAR(255) NOT NULL
);

# A:
CREATE TABLE auth_management.users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    username VARCHAR(50) NOT NULL,
    email VARCHAR(255) NOT NULL,
    phone_number VARCHAR(20),  -- ← Nueva columna agregada
    phone_verified BOOLEAN DEFAULT false
);

# 2. Validar con recreación completa
cd apps/database
./drop-and-recreate-database.sh

# 3. Si funciona, commitear
git add apps/database/ddl/schemas/auth_management/tables/01-users.sql
git commit -m "feat(db): add phone_number and phone_verified to users table"

# 4. Documentar en TRAZA-TAREAS-DATABASE.md
echo "## [DB-042] Agregar verificación de teléfono
**Fecha:** 2025-11-23
**Estado:** ✅ Completado
**Cambios:**
- Agregadas columnas phone_number, phone_verified a auth_management.users
**Archivos modificados:**
- apps/database/ddl/schemas/auth_management/tables/01-users.sql
" >> orchestration/trazas/TRAZA-TAREAS-DATABASE.md
```

#### ❌ PROCESO PROHIBIDO

```bash
# ❌ NO hacer esto:
psql -d gamilit_db -c "ALTER TABLE auth_management.users ADD COLUMN phone_number VARCHAR(20);"

# ❌ NO crear migration:
echo "ALTER TABLE auth_management.users ADD COLUMN phone_number VARCHAR(20);" \
  > apps/database/migrations/002-add-phone-to-users.sql

# ❌ NO crear fix:
echo "ALTER TABLE auth_management.users ADD COLUMN phone_number VARCHAR(20);" \
  > apps/database/fix-add-phone.sql
```

---

### 5. Validación de Carga Limpia

**Regla:** TODO cambio en DDL DEBE validarse con recreación completa.

#### Comandos de Validación

```bash
# Validación básica (desarrollo)
cd apps/database
./drop-and-recreate-database.sh

# Validación completa (pre-commit)
cd apps/database
./drop-and-recreate-database.sh && \
  psql -d gamilit_platform -f scripts/validate-integrity.sql && \
  echo "✅ Carga limpia validada"

# Si falla la recreación
# → El DDL tiene un problema
# → NO ejecutar fixes manuales
# → Corregir el archivo DDL y volver a intentar
```

#### Frecuencia de Validación

```yaml
Desarrollo local:
  - Después de cada cambio en DDL
  - Antes de cada commit que toca apps/database/

CI/CD:
  - En cada pull request
  - Antes de merge a main/master
  - En cada deploy a staging/producción

Mantenimiento:
  - Recreación semanal de BD de desarrollo
  - Validación mensual de que DDL + seeds = BD completa
```

#### Checklist de Validación

```markdown
- [ ] Recreación completa ejecuta sin errores
- [ ] Todas las tablas se crean correctamente
- [ ] Todos los índices se crean
- [ ] Todas las funciones y triggers se crean
- [ ] Todas las RLS policies se aplican
- [ ] Seeds se cargan sin errores
- [ ] Integridad referencial validada (FKs)
- [ ] No hay warnings en el log de create-database.sh
```

---

### 6. Homologación BD ↔ Archivos DDL

**Principio:** Los archivos DDL son la fuente de verdad, la BD es derivada.

```yaml
Fuente de verdad:
  ✅ apps/database/ddl/schemas/**/*.sql
  ✅ apps/database/seeds/**/*.sql

Derivado (resultado de ejecutar DDL):
  ✅ Base de datos PostgreSQL real

Flujo de sincronización:
  DDL actualizado → Recreación BD → BD actualizada

Flujo PROHIBIDO:
  ❌ BD actualizada manualmente → "Documentar" en DDL después
```

#### Validación de Homologación

```bash
# ¿Cómo saber si DDL y BD están sincronizados?
# → Recrear BD completa y comparar

# 1. Backup de BD actual (por seguridad)
pg_dump gamilit_platform > /tmp/backup-before-recreation.sql

# 2. Recrear desde DDL
./drop-and-recreate-database.sh

# 3. Si recreación falla:
# → DDL y BD NO están sincronizados
# → Actualizar DDL con cambios faltantes
# → Volver a intentar recreación

# 4. Si recreación funciona:
# → DDL y BD están sincronizados ✅
```

---

## 🔧 HERRAMIENTAS Y SCRIPTS

### Scripts de Recreación

```bash
apps/database/
├── create-database.sh              # Crear BD completa desde DDL
├── drop-and-recreate-database.sh   # Drop + Create (carga limpia total)
├── reset-database.sh               # Reset a estado inicial
└── recreate-database.sh            # Alias de drop-and-recreate
```

**Uso principal:**
```bash
# Desarrollo diario
cd apps/database
./drop-and-recreate-database.sh

# Pre-commit
git add apps/database/ddl/...
./drop-and-recreate-database.sh && git commit -m "feat(db): ..."

# Validar que DDL está completo
./drop-and-recreate-database.sh && echo "✅ DDL completo"
```

### Script de Validación (Opcional)

```bash
# apps/database/scripts/validate-clean-load-policy.sh
# Validar cumplimiento de Política de Carga Limpia

#!/bin/bash
echo "🔍 Validando Política de Carga Limpia..."

# 1. Verificar que no existe carpeta migrations/
if [ -d "apps/database/migrations" ]; then
  echo "❌ ERROR: Carpeta migrations/ detectada (PROHIBIDA)"
  exit 1
fi

# 2. Verificar que no hay archivos fix-*.sql o patch-*.sql
FIXES=$(find apps/database -name "fix-*.sql" -o -name "patch-*.sql" -o -name "hotfix-*.sql")
if [ -n "$FIXES" ]; then
  echo "❌ ERROR: Archivos fix/patch detectados (PROHIBIDOS):"
  echo "$FIXES"
  exit 1
fi

# 3. Validar que recreación completa funciona
echo "🔄 Validando recreación completa..."
./apps/database/drop-and-recreate-database.sh > /tmp/clean-load-test.log 2>&1
if [ $? -ne 0 ]; then
  echo "❌ ERROR: Recreación completa falló"
  echo "Ver log: /tmp/clean-load-test.log"
  exit 1
fi

echo "✅ Política de Carga Limpia: CUMPLIDA"
exit 0
```

---

## 📊 EJEMPLOS PRÁCTICOS

### Ejemplo 1: Crear Nueva Tabla

```sql
-- ✅ CORRECTO: Crear archivo DDL primero
-- File: apps/database/ddl/schemas/gamification_system/tables/05-challenges.sql

-- ============================================================================
-- Tabla: challenges
-- Schema: gamification_system
-- Descripción: Desafíos y retos del sistema de gamificación
-- Autor: Database-Agent
-- Fecha: 2025-11-23
-- Dependencias: gamification_system.levels
-- ============================================================================

DROP TABLE IF EXISTS gamification_system.challenges CASCADE;

CREATE TABLE gamification_system.challenges (
    -- Identificador
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Datos del desafío
    code VARCHAR(50) NOT NULL UNIQUE,
    name VARCHAR(200) NOT NULL,
    description TEXT,
    difficulty VARCHAR(20) NOT NULL,
    points_reward INTEGER NOT NULL DEFAULT 0,

    -- Requisitos
    required_level_id UUID,

    -- Auditoría
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),

    -- Constraints
    CONSTRAINT fk_challenges_to_levels
        FOREIGN KEY (required_level_id)
        REFERENCES gamification_system.levels(id)
        ON DELETE SET NULL,

    CONSTRAINT chk_challenges_difficulty_valid
        CHECK (difficulty IN ('easy', 'medium', 'hard', 'expert')),

    CONSTRAINT chk_challenges_points_positive
        CHECK (points_reward >= 0)
);

-- Índices
CREATE INDEX idx_challenges_difficulty ON gamification_system.challenges(difficulty);
CREATE INDEX idx_challenges_required_level_id ON gamification_system.challenges(required_level_id);

-- Comentarios
COMMENT ON TABLE gamification_system.challenges IS
'Desafíos del sistema de gamificación que los estudiantes pueden completar para ganar puntos adicionales';

COMMENT ON COLUMN gamification_system.challenges.difficulty IS
'Dificultad del desafío: easy, medium, hard, expert';
```

**Luego validar:**
```bash
cd apps/database
./drop-and-recreate-database.sh
# Si funciona → commit
git add apps/database/ddl/schemas/gamification_system/tables/05-challenges.sql
git commit -m "feat(db): add challenges table to gamification_system"
```

### Ejemplo 2: Modificar Tabla Existente

```sql
-- ✅ CORRECTO: Actualizar DDL existente (NO crear migration)
-- File: apps/database/ddl/schemas/auth_management/tables/01-users.sql

-- Cambio: Agregar columnas para autenticación de dos factores

DROP TABLE IF EXISTS auth_management.users CASCADE;

CREATE TABLE auth_management.users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    username VARCHAR(50) NOT NULL UNIQUE,
    email VARCHAR(255) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL,

    -- ← NUEVAS COLUMNAS AGREGADAS
    two_factor_enabled BOOLEAN DEFAULT false,
    two_factor_secret VARCHAR(100),
    backup_codes TEXT[],
    -- ← FIN NUEVAS COLUMNAS

    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
```

**Validar:**
```bash
./drop-and-recreate-database.sh
# ✅ Si funciona → DDL correcto, commitear
# ❌ Si falla → Corregir DDL, no ejecutar ALTER TABLE manual
```

### Ejemplo 3: Corregir Error en Seed

```sql
-- ❌ INCORRECTO: Crear fix-seed-data.sql
-- apps/database/fix-seed-users.sql
UPDATE auth_management.users SET role = 'admin' WHERE username = 'admin';

-- ✅ CORRECTO: Corregir archivo seed original
-- apps/database/seeds/dev/auth_management/01-users.sql

INSERT INTO auth_management.users (username, email, password_hash, role)
VALUES
    ('admin', 'admin@gamilit.com', '$2b$10$...', 'admin'),  -- ← Corregir role aquí
    ('teacher1', 'teacher1@gamilit.com', '$2b$10$...', 'teacher'),
    ('student1', 'student1@gamilit.com', '$2b$10$...', 'student')
ON CONFLICT (username) DO NOTHING;
```

**Validar:**
```bash
./drop-and-recreate-database.sh
# Verificar que admin tiene role correcto desde el inicio
psql -d gamilit_platform -c "SELECT username, role FROM auth_management.users WHERE username = 'admin';"
```

---

## 🚨 CASOS ESPECIALES

### Caso 1: Migración desde Otro Sistema

**Escenario:** Importar datos desde sistema legacy.

```markdown
❌ INCORRECTO:
1. Crear migration-import-legacy.sql con INSERT masivo
2. Ejecutar una vez y "olvidar"

✅ CORRECTO:
1. Crear seed en apps/database/seeds/prod/migration/01-import-legacy.sql
2. Documentar que es importación única con comentarios
3. Incluir en create-database.sh con flag condicional
4. Mantener seed para recreaciones futuras (testing)
```

### Caso 2: Datos de Producción

**Escenario:** Necesito actualizar datos en producción.

```markdown
❌ INCORRECTO:
1. Ejecutar UPDATE directo en producción
2. No actualizar seeds

✅ CORRECTO:
1. Si es dato de configuración:
   └─> Actualizar seed en apps/database/seeds/prod/
   └─> Validar con recreación local
   └─> Aplicar seed en producción

2. Si es dato de usuario (transaccional):
   └─> NO va en seeds (datos dinámicos)
   └─> Crear script de actualización documentado
   └─> Ejecutar en producción
   └─> Archivar script como documentación (NO en seeds)
```

### Caso 3: Hotfix en Producción

**Escenario:** Bug crítico en producción que requiere cambio urgente en BD.

```markdown
❌ INCORRECTO:
1. Ejecutar ALTER TABLE directo en producción
2. "Ya funcionó, documentar después"

✅ CORRECTO (incluso en emergencia):
1. Corregir DDL localmente
2. Validar con recreación local (rápido: 2-3 min)
3. Crear ADR documentando el hotfix
4. Aplicar DDL en producción
5. Commitear DDL + ADR inmediatamente
6. Post-mortem: ¿Por qué no se detectó en testing?
```

---

## ✅ CHECKLIST DE CUMPLIMIENTO

### Para Database-Agent

Antes de completar una tarea, verificar:

```markdown
- [ ] Todos los cambios están en archivos DDL (no en BD directamente)
- [ ] NO se crearon archivos en migrations/
- [ ] NO se crearon archivos fix-*.sql o patch-*.sql
- [ ] Recreación completa funciona: ./drop-and-recreate-database.sh
- [ ] MASTER_INVENTORY.yml actualizado
- [ ] TRAZA-TAREAS-DATABASE.md actualizado
- [ ] Commits incluyen archivos DDL, no scripts temporales
```

### Para Code Reviewers

Al revisar PRs que tocan base de datos:

```markdown
- [ ] Cambios están en apps/database/ddl/, no en migrations/
- [ ] NO hay archivos fix-*.sql, patch-*.sql, hotfix-*.sql
- [ ] DDL sigue estándares (ver DIRECTIVA-DISENO-BASE-DATOS.md)
- [ ] CI/CD ejecutó recreación completa exitosamente
- [ ] TRAZA-TAREAS-DATABASE.md documenta el cambio
```

### Para Desarrolladores

Al trabajar con base de datos:

```markdown
- [ ] Leí DIRECTIVA-POLITICA-CARGA-LIMPIA.md (este documento)
- [ ] Entiendo que DDL es fuente de verdad, BD es derivada
- [ ] Sé que NO debo crear migrations/
- [ ] Sé que debo actualizar DDL antes de modificar BD
- [ ] Sé validar con ./drop-and-recreate-database.sh
```

---

## 📚 REFERENCIAS

### Documentos Relacionados

- **[PROMPT-DATABASE-AGENT.md](../prompts/PROMPT-DATABASE-AGENT.md)** - Workflow de Database-Agent
- **[DIRECTIVA-DISENO-BASE-DATOS.md](DIRECTIVA-DISENO-BASE-DATOS.md)** - Estándares de diseño
- **[ESTANDARES-NOMENCLATURA.md](ESTANDARES-NOMENCLATURA.md)** - Nomenclatura de objetos DB
- **[TRAZA-TAREAS-DATABASE.md](../trazas/TRAZA-TAREAS-DATABASE.md)** - Historial de cambios

### Scripts Importantes

```bash
apps/database/
├── create-database.sh              # Crear BD desde DDL
├── drop-and-recreate-database.sh   # Recreación completa (carga limpia)
└── reset-database.sh               # Reset a estado inicial
```

### Estructura de Archivos DDL

```bash
apps/database/ddl/
├── 00-prerequisites.sql            # Extensions, configuración
└── schemas/
    ├── auth_management/
    │   ├── 00-schema.sql
    │   ├── tables/
    │   │   ├── 01-users.sql
    │   │   └── 02-roles.sql
    │   ├── functions/
    │   └── policies/
    ├── gamification_system/
    │   └── ...
    └── educational_content/
        └── ...
```

---

## 🎓 BENEFICIOS DE ESTA POLÍTICA

### Técnicos

1. ✅ **Reproducibilidad:** BD puede recrearse en cualquier momento, en cualquier ambiente
2. ✅ **Simplicidad:** Un script (drop-and-recreate), un resultado (BD completa)
3. ✅ **Debugging:** Error en recreación = DDL tiene problema (fácil de localizar)
4. ✅ **Testing:** Tests siempre empiezan con BD limpia predecible
5. ✅ **Onboarding:** Nuevos devs tienen BD funcional en minutos

### Operacionales

1. ✅ **Disaster Recovery:** Recrear BD desde DDL es rápido y confiable
2. ✅ **Ambientes:** Dev, Staging, Prod tienen misma estructura (desde mismo DDL)
3. ✅ **Auditoría:** Git history de DDL = historia completa de cambios en BD
4. ✅ **Rollback:** Revertir commit de DDL = revertir cambio en BD
5. ✅ **Compliance:** Cambios en BD rastreables y versionados

### De Equipo

1. ✅ **Claridad:** Todo el equipo sabe dónde están los cambios (DDL)
2. ✅ **Colaboración:** Conflictos en DDL son fáciles de resolver (Git)
3. ✅ **Documentación:** DDL es documentación ejecutable y siempre actualizada
4. ✅ **Confianza:** Cambios validados con recreación = alta confianza
5. ✅ **Velocidad:** No hay "estado misterioso" de BD, siempre es predecible

---

## ⚖️ CONTRASTE: Carga Limpia vs Migrations

| Aspecto | Migrations Incrementales | Carga Limpia (Este Proyecto) |
|---------|-------------------------|------------------------------|
| **Fuente de verdad** | Estado de BD + Migrations históricas | Archivos DDL actuales |
| **Recreación** | Ejecutar todas las migrations en orden | Un script: drop-and-recreate |
| **Debugging** | Difícil (¿cuál migration falló?) | Fácil (DDL tiene el problema) |
| **Onboarding** | Complejo (ejecutar N migrations) | Simple (1 comando, BD lista) |
| **Estado de BD** | Incierto (¿migrations aplicadas?) | Siempre conocido (DDL) |
| **Rollback** | Requiere migration de rollback | Revertir commit de DDL |
| **Testing** | Difícil (estado previo incierto) | Simple (siempre BD limpia) |
| **Producción** | Riesgoso (migration puede fallar) | Confiable (validado en recreación) |

**Cuándo usar migrations:** Proyectos con datos de producción que NO pueden perderse (ej: e-commerce, banking).

**Cuándo usar carga limpia:** Proyectos educativos, startups, MVPs, sistemas donde BD puede recrearse (como GAMILIT).

---

**Versión:** 1.0.0
**Fecha:** 2025-11-23
**Próxima revisión:** Trimestral o al identificar necesidad
**Responsable:** Database-Agent + Tech Lead
**Aprobado por:** Tech Lead

---

**NOTA IMPORTANTE:**

Esta política formaliza la práctica que ya se viene aplicando exitosamente en GAMILIT. El objetivo es documentarla para prevenir desviaciones futuras y facilitar el onboarding de nuevos desarrolladores.

**Evidencia de cumplimiento histórico:**
- ✅ 45+ menciones a "Política de Carga Limpia" en `TRAZA-TAREAS-DATABASE.md`
- ✅ 0 migrations creadas en historial del proyecto
- ✅ Scripts de recreación completa (`drop-and-recreate-database.sh`) funcionando desde inicio
- ✅ 100% de cambios en BD documentados en archivos DDL
