- 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>
11 KiB
ADR-020: Soporte de Múltiples Alternativas en Ejercicios Completar Espacios
Estado: Aceptado Fecha: 2025-11-24 Autor: Architecture-Analyst Relacionado con: GAP-EJERCICIO-1.3-001, DB-122 Implementado por: Database-Agent
Contexto
El ejercicio 1.3 "Completar Espacios en Blanco" del Módulo 1 sobre Marie Curie tiene espacios en blanco que aceptan múltiples respuestas válidas. Específicamente, los espacios 5 y 6 deben aceptar cualquiera de las palabras: ciencias, matemáticas, física en cualquier orden, con la restricción de que no pueden ser la misma palabra.
Problema Identificado
La función SQL validate_fill_in_blank solo validaba contra el campo solution->correctAnswers[id], que contiene UNA SOLA respuesta por espacio. Esto causaba que 4 de 6 combinaciones válidas (66%) fueran rechazadas incorrectamente:
"solution": {
"correctAnswers": {
"5": "ciencias", // ❌ Solo aceptaba "ciencias"
"6": "matemáticas" // ❌ Solo aceptaba "matemáticas"
}
}
Impacto:
- Estudiantes con respuestas correctas recibían calificación incorrecta
- Contradecía la documentación pedagógica oficial
- Generaba frustración y desconfianza en el sistema
Estructura Existente en Seeds
Los seeds ya contenían la estructura correcta con alternatives en el campo content->blanks[]:
"content": {
"blanks": [
{
"id": "5",
"position": 4,
"correctAnswer": "ciencias",
"alternatives": ["matemáticas", "física"] // ✅ Ya existía
},
{
"id": "6",
"position": 5,
"correctAnswer": "matemáticas",
"alternatives": ["ciencias", "física"] // ✅ Ya existía
}
]
}
Pero la función SQL NO leía ni usaba este campo alternatives.
Decisión
Se implementó soporte de múltiples alternativas válidas modificando la función SQL validate_fill_in_blank para:
- Aceptar un nuevo parámetro opcional
p_content JSONB DEFAULT NULL - Leer el campo
content->blanks[]del ejercicio - Para cada espacio en blanco:
- Validar primero contra
correctAnswer(lógica existente) - Si no coincide, validar contra cada elemento del array
alternatives - Marcar como válido si coincide con
correctAnswerO cualquieralternative
- Validar primero contra
Implementación Técnica
Función modificada: educational_content.validate_fill_in_blank()
Cambios realizados:
- Nueva firma (compatible hacia atrás):
CREATE OR REPLACE FUNCTION educational_content.validate_fill_in_blank(
p_solution JSONB,
p_submitted_answer JSONB,
p_max_points INTEGER,
p_case_sensitive BOOLEAN DEFAULT false,
p_normalize_text BOOLEAN DEFAULT true,
p_fuzzy_threshold NUMERIC DEFAULT NULL,
p_allow_partial_credit BOOLEAN DEFAULT true,
p_content JSONB DEFAULT NULL -- ✅ NUEVO parámetro (opcional)
)
- Nuevas variables:
v_content_blanks JSONB; -- Array de blanks del content
v_alternatives JSONB; -- Array de alternativas para el blank actual
v_is_valid BOOLEAN; -- Flag de validación
- Algoritmo de validación:
FOR cada blank_id EN correctAnswers:
1. Obtener correctAnswer de solution->correctAnswers[id]
2. Obtener alternatives de content->blanks[donde id=blank_id]->alternatives
3. Normalizar y comparar respuesta contra correctAnswer
4. SI no coincide Y alternatives existe:
FOR cada alternative EN alternatives:
Normalizar y comparar respuesta contra alternative
SI coincide: marcar como válido y SALIR
5. Registrar resultado (válido/inválido)
- Llamada desde
validate_answer:
WHEN 'validate_fill_in_blank' THEN
SELECT * INTO v_result
FROM educational_content.validate_fill_in_blank(
v_exercise.solution,
p_submitted_answer,
max_score,
v_config.case_sensitive,
v_config.normalize_text,
v_config.fuzzy_matching_threshold,
v_config.allow_partial_credit,
v_exercise.content -- ✅ NUEVO: pasar content
);
Alternativas Consideradas
Alternativa 1: Modificar estructura de solution->correctAnswers
Convertir correctAnswers[id] de string a array:
"solution": {
"correctAnswers": {
"5": ["ciencias", "matemáticas", "física"],
"6": ["ciencias", "matemáticas", "física"]
}
}
Rechazada porque:
- ❌ Rompe la estructura actual de solution (breaking change)
- ❌ Duplica información ya en
content->blanks[].alternatives - ❌ Requiere cambios en múltiples funciones SQL
- ❌ Requiere cambios en seeds de todos los ejercicios
- ❌ Mayor riesgo de bugs
Alternativa 2: Validación en Backend (TypeScript)
Mover la lógica de alternativas al servicio backend.
Rechazada porque:
- ❌ Viola el principio de validación centralizada en SQL
- ❌ Duplica lógica de validación en dos capas
- ❌ Dificulta auditoría (registros de validación incompletos)
- ❌ Mayor complejidad de mantenimiento
Alternativa 3: Mantener status quo
No implementar alternativas, modificar documentación para aceptar solo 1 respuesta.
Rechazada porque:
- ❌ Contradice la justificación pedagógica (Marie Curie estudió matemáticas Y física)
- ❌ Limita artificialmente las respuestas válidas
- ❌ No resuelve el problema de estudiantes con respuestas correctas rechazadas
Consecuencias
Positivas
-
Problema crítico resuelto:
- ✅ Las 6 combinaciones válidas ahora son aceptadas (vs 1 anterior)
- ✅ Estudiantes ya no reciben calificaciones incorrectas
- ✅ Alineación 100% con documentación pedagógica
-
Solución genérica y reutilizable:
- ✅ Cualquier ejercicio completar_espacios puede usar alternatives
- ✅ No requiere cambios en backend o frontend
- ✅ Estructura de seeds ya soportaba esto
-
Compatibilidad hacia atrás:
- ✅ Parámetro
p_contentes opcional (DEFAULT NULL) - ✅ Ejercicios sin alternatives siguen funcionando igual
- ✅ No breaking changes
- ✅ Parámetro
-
Mejor arquitectura:
- ✅ Validación sigue centralizada en SQL
- ✅ Usa estructura existente en seeds
- ✅ No duplica información
- ✅ Auditoría completa en una sola capa
Negativas
-
Mayor complejidad en función SQL:
- ⚠️ Loop adicional para validar alternatives
- Mitigación: Complejidad es O(n) donde n < 5 típicamente (aceptable)
-
Cambio en firma de función:
- ⚠️ Nuevo parámetro
p_content - Mitigación: Es opcional (DEFAULT NULL), no rompe compatibilidad
- ⚠️ Nuevo parámetro
-
Dependencia en estructura de
content->blanks[]:- ⚠️ Función asume que
blankses un array con estructura específica - Mitigación: Estructura ya validada en seeds, es estándar del proyecto
- ⚠️ Función asume que
Neutras
- Performance: Incremento < 5ms por validación (insignificante)
- Testing: Requiere tests adicionales (ya implementados: 7/7 pasados)
Validación
Tests Ejecutados (7/7 PASARON)
| Test | Combinación | Score | is_correct | Resultado |
|---|---|---|---|---|
| 1 | ciencias + física | 100 | true | ✅ PASS |
| 2 | ciencias + matemáticas | 100 | true | ✅ PASS |
| 3 | física + matemáticas | 100 | true | ✅ PASS |
| 4 | matemáticas + ciencias | 100 | true | ✅ PASS |
| 5 | matemáticas + física | 100 | true | ✅ PASS |
| 6 | física + ciencias | 100 | true | ✅ PASS |
| 7 | Polonia + matemáticas (incorrecto) | 83 | false | ✅ PASS |
SUCCESS RATE: 100%
Validación de Compatibilidad
- ✅ Recreación de base de datos exitosa
- ✅ Carga limpia sin errores
- ✅ Otros ejercicios completar_espacios no afectados
- ✅ Backend: validación anti-redundancia sigue activa
- ✅ Frontend: componente
FillBlankActivitysin cambios
Alineación Entre Capas
Database (✅ ACTUALIZADA)
- Seeds: Estructura con
alternativesmantenida - Función SQL: Ahora lee y usa
alternatives - Validación: Acepta múltiples respuestas válidas
Backend (✅ COMPATIBLE)
- Anti-redundancia: Validación de espacios 5 y 6 sigue activa
- DTO: Sin cambios necesarios
- Servicio: Llama a SQL que ahora valida correctamente
Frontend (✅ COMPATIBLE)
- Componente:
FillBlankActivitynormaliza respuestas - Interfaz: Sin cambios necesarios
- Flujo: Usuario envía respuestas → backend valida → SQL valida correctamente
Aplicabilidad Futura
Esta decisión establece un patrón estándar para ejercicios con múltiples respuestas válidas:
Cómo usar alternatives en nuevos ejercicios
- En seeds (content->blanks):
"blanks": [
{
"id": "1",
"position": 0,
"correctAnswer": "respuesta_principal",
"alternatives": ["alternativa1", "alternativa2"]
}
]
- En seeds (solution):
"solution": {
"correctAnswers": {
"1": "respuesta_principal"
}
}
- Validación automática:
La función SQL
validate_fill_in_blankahora valida automáticamente contracorrectAnswerO cualquieralternative.
Casos de uso aplicables
- ✅ Sinónimos (ej: "feliz" / "contento" / "alegre")
- ✅ Formatos variados (ej: "1900" / "mil novecientos")
- ✅ Traducciones (ej: "science" / "ciencia")
- ✅ Nombres alternativos (ej: "Marie Curie" / "Marie Sklodowska-Curie")
Referencias
Documentación del Problema
orchestration/agentes/architecture-analyst/ejercicio-1-3-validacion-alternativas-2025-11-24/01-ANALISIS-GAP.mddocs/00-vision-general/GUIA-PRUEBAS-MODULO1-Respuestas-Ejemplo.md(líneas 372-386)
Implementación
orchestration/agentes/architecture-analyst/ejercicio-1-3-validacion-alternativas-2025-11-24/02-PLAN-CORRECCION.mdorchestration/agentes/database/ejercicio-1-3-validacion-alternativas-2025-11-24/00-RESUMEN-EJECUTIVO.md
Código Afectado
apps/database/ddl/schemas/educational_content/functions/06-validate_fill_in_blank.sqlapps/database/ddl/schemas/educational_content/functions/02-validate_answer.sqlapps/database/seeds/prod/educational_content/02-exercises-module1.sql
Directivas Aplicadas
orchestration/directivas/DIRECTIVA-POLITICA-CARGA-LIMPIA.mdorchestration/directivas/DIRECTIVA-DOCUMENTACION-OBLIGATORIA.md
Decisiones Relacionadas
- ADR-001: Estructura de ejercicios en JSONB
- ADR-005: Validación centralizada en SQL
- ADR-010: Documento de diseño como fuente de verdad
Notas de Implementación
Fecha de implementación: 2025-11-24 Implementado por: Database-Agent Revisado por: Architecture-Analyst Aprobado para producción: ⏳ Pendiente
Testing:
- ✅ Unit tests (SQL): 7/7 pasados
- ⏳ Integration tests (Backend): Pendiente
- ⏳ E2E tests (Frontend): Pendiente
Rollout:
- Ambiente: DEV ✅ COMPLETADO
- Ambiente: STAGING ⏳ Pendiente
- Ambiente: PRODUCTION ⏳ Pendiente
Estado: ✅ ACEPTADO E IMPLEMENTADO Revisión: Anual (2026-11-24)