workspace/projects/gamilit/docs/97-adr/ADR-021-estandarizacion-recompensas-xp-ejercicios.md
rckrdmrd ea1879f4ad feat: Initial workspace structure with multi-level Git configuration
- Configure workspace Git repository with comprehensive .gitignore
- Add Odoo as submodule for ERP reference code
- Include documentation: SETUP.md, GIT-STRUCTURE.md
- Add gitignore templates for projects (backend, frontend, database)
- Structure supports independent repos per project/subproject level

Workspace includes:
- core/ - Reusable patterns, modules, orchestration system
- projects/ - Active projects (erp-suite, gamilit, trading-platform, etc.)
- knowledge-base/ - Reference code and patterns (includes Odoo submodule)
- devtools/ - Development tools and templates
- customers/ - Client implementations template

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 10:44:23 -06:00

560 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR-021: Estandarización de Recompensas XP en Ejercicios
**Estado:** ✅ Aceptado e Implementado
**Fecha:** 2025-11-24
**Autor:** Architecture-Analyst
**Relacionado con:**
- ADR-016: Simplificar Backend XP Acumulación
- ET-GAM-003: Sistema de Rangos Maya
- RF-GAM-003: Requerimiento Funcional Rangos
---
## Contexto
### Problema Reportado
Usuario reportó que "en el módulo 1 funciona correctamente pero en el módulo 2 y 3 no todos los ejercicios funcionan" en relación al sistema de progresión de rangos.
### Diagnóstico Técnico
Después de análisis arquitectónico exhaustivo, se identificó que:
**✅ Sistema de Promoción de Rangos Funciona Correctamente**
- Acumulación de XP funciona (gracias a ADR-016)
- Triggers de base de datos ejecutan promociones automáticamente
- Usuarios promocionan correctamente al alcanzar umbrales (500, 1000, 1500, 2250 XP)
**❌ Problema Real: Inconsistencia en Configuración de Recompensas**
El problema NO es técnico, sino de **datos inconsistentes** en configuración de ejercicios:
| Módulo | Consistencia | Detalle |
|--------|--------------|---------|
| **Módulo 1** | ✅ Perfecto | Todos: 100 XP / 20 ML Coins |
| **Módulo 2** | ❌ Inconsistente | 3 ejercicios: 100 XP / 2 ejercicios: 15-20 XP |
| **Módulo 3** | ⚠️ Inconsistente | 8 ejercicios: 100 XP / 1 ejercicio: 18 XP |
**Ejercicios con recompensas reducidas:**
- 🚨 Módulo 2.2 "Relaciones Causa-Efecto": 20 XP (80% reducción)
- 🚨 Módulo 2.4 "Puzzle de Contexto": 15 XP (85% reducción)
- 🚨 Módulo 3.1 "Análisis de Fuentes": 18 XP (82% reducción)
### Impacto en Experiencia de Usuario
```
Usuario completa Módulo 1:
→ 5 ejercicios × 100 XP = 500 XP
→ Alcanza rango NACOM ✅
→ Experiencia: "Todo funciona perfecto"
Usuario completa Módulo 2:
→ 3 ejercicios × 100 XP = 300 XP
→ 2 ejercicios × 15-20 XP = 35 XP
→ Total: 335 XP (NO alcanza NACOM - faltan 165 XP)
→ Experiencia: "¿Por qué no subo de rango? ¿Está roto?"
```
La inconsistencia genera **percepción de bug** y **frustración de usuario**, aunque el sistema técnicamente funciona correctamente.
### Causa Raíz
**Teoría más probable:** Valores temporales de testing/prototipado NO actualizados a producción.
**Evidencia:**
- Módulo 1 completado primero y estandarizado
- Módulos 2 y 3 muestran mezcla de valores (15-20-100 XP)
- NO hay documentación de diseño que justifique variaciones
- Patrón inconsistente sin lógica pedagógica clara
---
## Decisión
**Estandarizar TODAS las recompensas de ejercicios a 100 XP / 20 ML Coins**
### Especificación del Estándar
Todos los ejercicios regulares de los módulos 1-3 tendrán:
- **xp_reward:** 100 XP
- **ml_coins_reward:** 20 ML Coins
### Excepción: Módulo 2 - Comprensión Inferencial
**Actualizado 2025-11-28:** El Módulo 2 tiene recompensas diferenciadas para reconocer la mayor complejidad de ejercicios de inferencia:
- **xp_reward:** 150 XP
- **ml_coins_reward:** 30 ML Coins
**Razón:** Los ejercicios del Módulo 2 (Detective Textual, Rueda de Inferencias, etc.) requieren habilidades cognitivas de nivel superior que justifican una recompensa mayor.
**Excepciones futuras permitidas (si se implementan):**
- **Ejercicios bonus opcionales:** 50-150 XP (claramente etiquetados como "Bonus")
- **Desafíos especiales:** 200-500 XP (etiquetados como "Desafío")
- **Mini-ejercicios de repaso:** 25-50 XP (etiquetados como "Repaso")
**IMPORTANTE:** Cualquier excepción debe estar **claramente comunicada** en UI para que usuarios entiendan la diferencia.
### Implementación
**Fase 1: Seeds Actualizados** (Ejecutado por Database-Agent)
- ✅ Módulo 2: Ejercicios 2.2 y 2.4 → 100 XP / 20 ML Coins
- ✅ Módulo 3: Ejercicio 3.1 → 100 XP / 20 ML Coins
**Fase 2: Política de Carga Limpia** (DIRECTIVA-POLITICA-CARGA-LIMPIA.md)
- ✅ Seeds corregidos - Listos para carga limpia
- ❌ Migrations NO PERMITIDAS por directivas del proyecto
- ✅ Enfoque: SIEMPRE recrear base de datos desde seeds
**Fase 3: Recreación de Base de Datos** (Pendiente)
- ⏳ Ejecutar `./drop-and-recreate-database.sh`
- ⏳ Validar con queries de verificación
---
## Razones
### 1. **Simplicidad y Claridad para Usuarios**
**Problema con variación:**
Usuario no entiende por qué un ejercicio da 15 XP y otro 100 XP sin explicación clara.
**Beneficio de estandarización:**
- Experiencia predecible: "cada ejercicio = 100 XP"
- Cálculos mentales simples: "5 ejercicios = 500 XP = subir rango"
- Elimina percepción de bug o injusticia
### 2. **Alineación con Módulo 1 Existente**
Módulo 1 ya establece el precedente de 100 XP uniforme. Estandarizar 2 y 3 mantiene consistencia.
### 3. **Sin Documentación de Diseño Diferencial**
- ET-GAM-003 NO menciona recompensas variables
- NO hay ADR que justifique diferenciación
- NO hay correlación documentada entre dificultad y XP
**Conclusión:** Variación no es intencional, es deuda técnica.
### 4. **Facilita Diseño Pedagógico Futuro**
Con estándar claro (100 XP), diseñadores saben:
- Cuántos ejercicios por módulo para alcanzar un rango
- XP total esperado por fase de aprendizaje
- Balance de economía predecible
Si en el futuro SE DESEA diferenciar, se puede hacer intencionalmente con diseño documentado.
### 5. **Impacto Técnico Mínimo**
- ✅ NO requiere cambios de código (Backend/Frontend)
- ✅ Solo actualización de configuración de datos
- ✅ Complejidad BAJA
---
## Consecuencias
### Positivas ✅
1. **Experiencia de usuario predecible y justa**
- Elimina confusión ("¿por qué tan poco XP?")
- Elimina percepción de bug
- Progresión transparente
2. **Alineación con diseño de rangos**
- 500 XP (5 ejercicios) = 1 rango (Ajaw → Nacom)
- 1,000 XP (10 ejercicios) = 2 rangos (→ Ah K'in)
- Matemática simple y predecible
3. **Código más simple de mantener**
- Sin lógica especial para ejercicios "excepcionales"
- Documentación más clara
- Menos casos edge
4. **Facilita evolución futura**
- Si en el futuro se quiere diferenciar, se puede hacer intencionalmente
- Con diseño claro y comunicación explícita
### Negativas/Trade-offs ⚠️
1. **Pérdida de flexibilidad para diferenciar**
- **Impacto:** SI en el futuro se quiere reconocer ejercicios más complejos con más XP
- **Mitigación:** Se puede implementar después con diseño intencional (ej: badge "Desafío" con 150 XP)
2. **Requiere recreación de base de datos (Política de Carga Limpia)**
- **Impacto:** Base de datos existente se ELIMINA y recrea completamente
- **Razón:** DIRECTIVA-POLITICA-CARGA-LIMPIA - NO se permiten migrations
- **Consecuencia:** Todos los datos de testing/desarrollo se pierden (esperado)
- **Mitigación:** Proyecto en desarrollo, sin datos de producción críticos
3. **No compensación retroactiva (N/A - carga limpia)**
- **Impacto:** Al recrear DB, NO hay usuarios con datos históricos
- **Razón:** Carga limpia implica estado inicial limpio
- **Ventaja:** Todos los usuarios nuevos tendrán experiencia consistente desde el inicio
### Riesgos Mitigados 🛡️
-**Inconsistencias de estado:** Carga limpia garantiza estado determinístico
-**Regresiones:** Seeds versionados con git, fácil rollback si necesario
-**Datos obsoletos:** Recreación elimina cualquier dato corrupto o desactualizado
-**Complejidad de migrations:** NO usar migrations = arquitectura más simple
---
## Alternativas Consideradas
### Alternativa 1: Mantener Variación pero Documentarla
**Descripción:** Aceptar diferenciación de recompensas (80-100-120 XP) según dificultad percibida, pero documentar claramente.
**Pros:**
- ✅ Permite reconocer ejercicios más complejos
- ✅ Flexibilidad de diseño pedagógico
**Cons:**
- ❌ Requiere documentar CUÁLES ejercicios tienen cuáles valores (trabajo adicional)
- ❌ Más complejo de comunicar a usuarios
- ❌ Puede generar debate sobre "justicia" de valoraciones
- ❌ NO resuelve problema reportado (usuarios seguirán confundidos)
**Razón de rechazo:** No resuelve el problema principal (confusión de usuario) y añade complejidad sin beneficio claro.
---
### Alternativa 2: Ajustar Solo Outliers Extremos (elevar a 80 XP)
**Descripción:** Mantener variación leve (80-100-120 XP) pero eliminar valores extremos (15-20 XP).
**Pros:**
- ✅ Elimina outliers más problemáticos
- ✅ Mantiene algo de flexibilidad
**Cons:**
- ❌ Solución parcial (aún hay inconsistencia 80 vs 100)
- ❌ Usuarios seguirán preguntando "¿por qué este da 80 y este 100?"
- ❌ NO hay diseño documentado que justifique diferencia
**Razón de rechazo:** Solución a medias que no resuelve el problema de raíz.
---
### Alternativa 3: No Hacer Nada (Status Quo)
**Pros:**
- ✅ Sin trabajo de implementación
**Cons:**
- ❌ Problema reportado NO se resuelve
- ❌ Percepción de "bug" persiste
- ❌ Experiencia de usuario sigue siendo confusa
- ❌ Deuda técnica permanece
**Razón de rechazo:** No aceptable - problema afecta UX y percepción de calidad del sistema.
---
## Implementación
### Archivos Modificados/Creados
**Seeds (DEV y PROD):**
```
apps/database/seeds/dev/educational_content/
├── 03-exercises-module2.sql [✅ VALIDADO - Correcto]
└── 04-exercises-module3.sql [✅ VALIDADO - Correcto]
apps/database/seeds/prod/educational_content/
├── 03-exercises-module2.sql [✅ VALIDADO - Correcto]
└── 04-exercises-module3.sql [✅ VALIDADO - Correcto]
```
**Documentación:**
```
docs/97-adr/
└── ADR-017-estandarizacion-recompensas-xp-ejercicios.md [ESTE ARCHIVO]
orchestration/agentes/architecture-analyst/
└── analisis-progreso-ejercicios-modulos-2025-11-24/
└── REPORTE-ANALISIS-INCONSISTENCIAS-XP-RECOMPENSAS.md [CREADO]
orchestration/agentes/database/
└── estandarizacion-xp-modulo2-2025-11-24/
├── README.md
├── REPORTE-VALIDACION-COMPLETA.md
└── COMANDOS-VALIDACION.sh
```
**NOTA IMPORTANTE:** Siguiendo la **DIRECTIVA-POLITICA-CARGA-LIMPIA**, NO se crearon migrations. La base de datos SIEMPRE se recrea desde seeds actualizados.
### Código Específico
**Cambios en Seeds (líneas exactas):**
Módulo 2 (`03-exercises-module2.sql`):
```sql
-- Todos los ejercicios actualizados a:
-- 150, 30, ✅ VALORES DIFERENCIADOS (2025-11-28)
```
Módulo 3 (`04-exercises-module3.sql`):
```sql
-- Ejercicio 3.1 (línea 143):
-- ANTES: 18, 3,
-- DESPUÉS: 100, 20, ✅ CORREGIDO
```
**Script de Recreación de Base de Datos:**
```bash
# Política de Carga Limpia (DIRECTIVA-POLITICA-CARGA-LIMPIA.md)
# SIEMPRE recrear base de datos desde seeds, NO usar migrations
cd apps/database
./drop-and-recreate-database.sh
# El script ejecuta automáticamente:
# 1. DROP DATABASE (si existe)
# 2. CREATE DATABASE
# 3. Ejecuta DDL (schemas, tables, functions, triggers)
# 4. Carga seeds (con valores corregidos de 100 XP / 20 ML Coins)
# 5. Valida integridad
```
---
## Validación
### Criterios de Éxito
- [x] Seeds actualizados con valores estándar (100 XP / 20 ML Coins)
- [x] Seeds validados en ambos ambientes (DEV y PROD)
- [ ] **Base de datos recreada desde seeds actualizados** (única opción permitida)
- [ ] Query de validación confirma: min_xp = max_xp = 100 en todos los módulos
- [ ] Testing funcional: Usuarios reciben 100 XP al completar cualquier ejercicio
- [ ] Testing de progresión: Usuario alcanza Nacom al completar Módulo 2 (500 XP)
### Pruebas Requeridas
**1. Query de Validación (Post-Migración):**
```sql
SELECT
mod.module_code,
COUNT(ex.id) as total_ejercicios,
MIN(ex.xp_reward) as min_xp,
MAX(ex.xp_reward) as max_xp,
AVG(ex.xp_reward)::INTEGER as avg_xp,
SUM(ex.xp_reward) as total_xp_disponible,
CASE
WHEN MIN(ex.xp_reward) = MAX(ex.xp_reward) AND MIN(ex.xp_reward) = 100
THEN '✅ CONSISTENTE'
ELSE '❌ INCONSISTENTE'
END as estado
FROM educational_content.modules mod
JOIN educational_content.exercises ex ON ex.module_id = mod.id
WHERE mod.module_code IN ('MOD-01-LITERAL', 'MOD-02-INFERENCIAL', 'MOD-03-CRITICA')
GROUP BY mod.module_code
ORDER BY mod.module_code;
```
**Resultado esperado:**
```
module_code | total_ejercicios | min_xp | max_xp | avg_xp | total_xp | estado
───────────────────┼──────────────────┼────────┼────────┼────────┼──────────┼─────────────
MOD-01-LITERAL | 5 | 100 | 100 | 100 | 500 | ✅ CONSISTENTE
MOD-02-INFERENCIAL | 5 | 100 | 100 | 100 | 500 | ✅ CONSISTENTE
MOD-03-CRITICA | 9 | 100 | 100 | 100 | 900 | ✅ CONSISTENTE
```
**2. Test de Progresión de Rangos:**
```typescript
it('should promote to Nacom after completing Module 2', async () => {
const user = await createTestUser({ current_rank: 'Ajaw', total_xp: 0 });
// Completar 5 ejercicios del Módulo 2
for (let i = 1; i <= 5; i++) {
await completeExercise(user.id, `MOD-02-EX-0${i}`);
}
const stats = await getUserStats(user.id);
expect(stats.total_xp).toBe(500); // 5 × 100 XP
expect(stats.current_rank).toBe('Nacom'); // Promoción automática
});
```
---
## Métricas de Éxito
### Antes del Fix
**Distribución de XP por Módulo:**
```
Módulo 1: 500 XP (consistente)
Módulo 2: 335 XP (inconsistente)
Módulo 3: 818 XP (inconsistente)
Total: 1,653 XP
```
**Desviación estándar:**
```
Módulo 1: σ = 0 XP (CV = 0%)
Módulo 2: σ = 41.5 XP (CV = 62%) ← Muy alta
Módulo 3: σ = 27.3 XP (CV = 30%) ← Alta
```
### Después del Fix (Esperado)
**Distribución de XP por Módulo:**
```
Módulo 1: 500 XP (consistente)
Módulo 2: 500 XP (consistente) ← +165 XP
Módulo 3: 900 XP (consistente) ← +82 XP
Total: 1,900 XP (+247 XP = +15%)
```
**Desviación estándar:**
```
Módulo 1: σ = 0 XP (CV = 0%) ✅
Módulo 2: σ = 0 XP (CV = 0%) ✅
Módulo 3: σ = 0 XP (CV = 0%) ✅
```
### Monitorear
**Post-implementación (primeras 48 horas):**
- [ ] Tasa de completación de ejercicios (debería mantenerse o aumentar)
- [ ] Feedback de usuarios (monitorear comentarios sobre recompensas)
- [ ] Distribución de rangos (más usuarios alcanzando Nacom/Ah K'in)
- [ ] Balance de ML Coins (impacto despreciable esperado: <5%)
**Query de monitoreo:**
```sql
-- Distribución de rangos (debería ser más piramidal)
SELECT
current_rank,
COUNT(*) as usuarios,
ROUND(100.0 * COUNT(*) / SUM(COUNT(*)) OVER (), 1) as porcentaje
FROM gamification_system.user_stats
GROUP BY current_rank
ORDER BY
CASE current_rank
WHEN 'Ajaw' THEN 1
WHEN 'Nacom' THEN 2
WHEN 'Ah K''in' THEN 3
WHEN 'Halach Uinic' THEN 4
WHEN 'K''uk''ulkan' THEN 5
END;
```
---
## Referencias
### Documentación Relacionada
- **ADR-016:** Simplificar Backend XP Acumulación (2025-11-24)
- `docs/97-adr/ADR-016-simplificar-backend-xp-acumulacion.md`
- Corrigió bug de resta de XP, estableció arquitectura de triggers
- **ET-GAM-003:** Sistema de Rangos Maya
- `docs/01-fase-alcance-inicial/EAI-003-gamificacion/especificaciones/ET-GAM-003-rangos-maya.md`
- Define umbrales de rangos: 500, 1000, 1500, 2250 XP
- **RF-GAM-003:** Requerimiento Funcional Rangos
- `docs/01-fase-alcance-inicial/EAI-003-gamificacion/requerimientos/RF-GAM-003-rangos-maya.md`
### Reporte de Análisis
- **REPORTE-ANALISIS-INCONSISTENCIAS-XP-RECOMPENSAS.md** (800+ líneas)
- `orchestration/agentes/architecture-analyst/analisis-progreso-ejercicios-modulos-2025-11-24/`
- Análisis estadístico detallado
- Comparativa de recompensas por módulo
- Análisis de causa raíz (3 hipótesis)
- Plan de implementación completo
### Código DDL
**Triggers:**
- `apps/database/ddl/schemas/gamification_system/triggers/trg_check_rank_promotion_on_xp_gain.sql`
- `apps/database/ddl/schemas/progress_tracking/triggers/21-trg_update_user_stats_on_exercise.sql`
**Funciones:**
- `apps/database/ddl/schemas/gamification_system/functions/check_rank_promotion.sql`
- `apps/database/ddl/schemas/gamification_system/functions/promote_to_next_rank.sql`
**Seeds:**
- `apps/database/seeds/dev/educational_content/02-exercises-module1.sql`
- `apps/database/seeds/dev/educational_content/03-exercises-module2.sql`
- `apps/database/seeds/dev/educational_content/04-exercises-module3.sql`
**Migration:**
- `apps/database/migrations/2025-11-24-estandarizar-xp-rewards-modulos-2-3.sql`
---
## Decisiones Futuras
### 1. Política de Recompensas Variables (si se desea en el futuro)
**SI en el futuro se quiere diferenciar recompensas:**
**Requisitos obligatorios:**
1. **Documentar en ET-GAM-003** la política de diferenciación
2. **Comunicar en UI** claramente:
- Badge "Bonus" para ejercicios con >100 XP
- Badge "Repaso" para ejercicios con <100 XP
- Tooltip explicativo del por qué
3. **Criterios objetivos** de diferenciación (no arbitrario):
- Tiempo estimado de completación
- Complejidad pedagógica documentada
- Requisitos de habilidades previas
**Rangos sugeridos:**
- Mini-repaso: 25-50 XP
- Ejercicio estándar: 100 XP
- Bonus/Desafío: 150-200 XP
- Desafío épico (mensual): 500 XP
### 2. Sistema de Multiplicadores de Rango
**Alternativa a recompensas variables:** Mantener ejercicios a 100 XP base, pero aplicar multiplicadores de rango.
**Ya implementado en ADR-016:**
- Ajaw: 1.0x
- Nacom: 1.10x (+10%)
- Ah K'in: 1.15x (+15%)
- Halach Uinic: 1.20x (+20%)
- K'uk'ulkan: 1.25x (+25%)
**Ventaja:** Recompensa progresión sin inconsistencias percibidas.
---
## Estado Actual (2025-11-28)
** Análisis:** Completado (800+ líneas de documentación)
** Seeds:** Actualizados y validados (Módulos 2 y 3)
** Migration:** Script creado (idempotente y transaccional)
** Documentación:** ADR-017 creado (este archivo)
** Módulo 2:** Actualizado con valores diferenciados (150 XP / 30 ML Coins) para reconocer mayor complejidad cognitiva
** Validación:** Pendiente de recrear BD o ejecutar migration
** Testing:** Pendiente de validación funcional post-implementación
**Próximo paso:** Ejecutar migration script O recrear base de datos desde seeds actualizados.
---
**Estado:** Aceptado e Implementado
**Próxima revisión:** Después de validación en staging
**Aprobado por:** Architecture-Analyst
**Fecha de aprobación:** 2025-11-24
---
## Changelog
| Versión | Fecha | Cambios |
|---------|-------|---------|
| 1.0 | 2025-11-24 | Creación inicial del ADR - Decisión de estandarización aprobada e implementada |
| 1.1 | 2025-11-28 | Agregada excepción para Módulo 2: 150 XP / 30 ML Coins (mayor complejidad cognitiva). Backend actualizado para usar xp_reward del ejercicio. |