Integración de Didact en SkillNet
Estado: inventario completo integrado; adopción funcional por familias
Didact: https://github.com/JoseEstevez520/Didact (MIT)
Revisión examinada: 06c80e8
Relacionado: openui-adoption.md, personalization-architecture.md,
learning-experience-architecture.md, v2-dynamic-courses.md
Alcance de este documento: describe el inventario y la integración ejecutable actual de Didact. La arquitectura objetivo neutral —donde Didact es un proveedor reemplazable,
LearningExperiencesustituye la frontera específica y los bloques pedagógicos legacy salen de cursos nuevos— se define enlearning-experience-architecture.md. Cuando una decisión histórica de adopción incremental de esta página contradiga ese objetivo, gana el documento neutral; esta página sigue ganando sobre qué tipos y puertos funcionan hoy.
Decisión
SkillNet conserva la autoría pedagógica, la personalización, el RAG, la seguridad de evaluación y la composición OpenUI generada en el momento. Didact aporta contratos y componentes educativos accesibles. No se integra como un segundo motor de cursos ni como una lista de widgets que el LLM deba conocer completa.
objetivo + knowledge pack + perfil cerrado
│
▼
plan de experiencia SkillNet
│
▼
resolver de capacidades de Didact
│ 2–5 candidatos compatibles
▼
generación OpenUI on-the-fly
│
▼
validación → render Didact adaptado → eventos
Didact ofrece las facetas necesarias para seleccionar sin inferir por nombres: propósito, representación, acción del alumno, contexto, accesibilidad, madurez, esquema de autoría, capacidades y dependencias opcionales. SkillNet las adapta a ComponentDescriptor; el catálogo no decide por sí solo qué debe aprender la persona.
Base OpenUI directa
La integración comenzó con dos experiencias del catálogo real skillnet-ui/1:
| Componente | Para qué entra | Estado que conserva |
|---|---|---|
Flashcard(front, back) |
Intento de recuerdo antes de revelar; útil para reconocer o reconstruir | revelado y autoevaluación local |
HintReveal(title, hints, solution) |
Pistas progresivas y solución bajo petición; especialmente útil con más apoyo | número de pistas y solución visible |
Ambos cumplen el dialecto estático: propiedades literales, estado React local, sin Query, Mutation, código ejecutable ni identidad. Después se sumaron Glossary, Timeline y WorkedExample como bloques directos, y DidactActivity como referencia opaca a definiciones server-owned. Sus esquemas existen en frontend y backend; el test de deriva comprueba nombres, orden de propiedades y artefacto del prompt. La versión del prompt invalida renders producidos con catálogos anteriores.
En la primera adopción no se sustituyó StepSequence por Timeline: representaban la misma
capacidad y se evitó duplicarlas en el catálogo. Esta fue una decisión incremental, no el estado
objetivo. Para cursos nuevos, la migración aprobada retira StepSequence y los demás componentes
pedagógicos legacy del catálogo de autoría; Didact entra a través de la frontera neutral
LearningExperience. Los renderers legacy permanecen sólo para reproducir cursos publicados.
Tampoco se añadió repetición espaciada; Didact separa correctamente la tarjeta de la planificación de
repasos y SkillNet no necesita todavía ese scheduler.
Selección cuando crezca el catálogo
Frontera ejecutable actual
La disponibilidad completa y la exposición al modelo son dos conjuntos distintos:
didact_snapshot.jsonyexport_didact_descriptors()proyectan los 34 tipos al resolver. Conservan identidad, facetas, acciones, representaciones, accesibilidad, productor y requisitos de puertos; un tipo bloqueado sigue siendo descubrible para experimentos y para explicar qué capacidad falta.openui_names_for_shortlist()es la puerta fail-closed. Solo traduce un tipo a su nombre de schema cuando renderer, permiso de emisión y puertos están listos.build_didact_prompt_slice()serializa exclusivamente esos schemas aceptados junto con el shell seguro de pantalla. Un tipo instalado pero bloqueado produce error explícito; nunca desaparece silenciosamente ni llega al LLM sin contrato.
Hoy los 34 tipos están inventariados y se cargan de forma lazy en el frontend. Veintinueve tienen una ruta de emisión honesta: cinco bloques OpenUI directos, once evaluaciones server-side, tres actividades con assets revisados, dos lecturas de progreso del host y ocho actividades con definición, estado y puertos. Los otros cinco permanecen disponibles para el resolver, pero bloqueados hasta que existan scheduler, simulación adaptada o sandbox. La tabla de runtime al final de este documento es la autoridad sobre cada familia.
La frontera ya está conectada al generador: el runtime forma una shortlist de 3-5 tipos,
aplica gates de renderer, puertos y datos, y entrega al modelo solo el slice permitido. Para
actividades ricas, una fase de autoría crea una ActivityDefinition server-owned y la
valida antes de persistir. Si no puede construirla con datos respaldados, hace Decline y
vuelve a una representación segura.
El modelo no debe recibir todos los componentes de Didact. Antes de cada generación se aplican filtros deterministas:
- disponibilidad y madurez permitida;
- misión cognitiva y función de la fuente;
- requisitos presentes en el knowledge pack;
- capacidades obligatorias de accesibilidad;
- productor disponible (
content,assessment,media,simulationodeterministic); - preferencias declaradas de presentación, como sesgo y no como obligación;
- presupuesto de complejidad de la pantalla.
El resultado es una colección pequeña y versionada, no una elección final rígida. El LLM puede componer entre esos candidatos y Decline si ninguno representa honestamente la misión. component_id@version, capacidades y versión de selección entrarán en traza y caché cuando el filtro pase de sombra a producción.
Niveles de adopción
Nivel A — estático y seguro
Props planas o listas, estado efímero, sin servicios externos. Puede entrar directamente en OpenUI: Flashcard, HintReveal, Glossary y algunas representaciones visuales.
Nivel B — respuesta y evaluación del host
El componente recoge una respuesta serializable, pero SkillNet conserva la respuesta correcta y evalúa por API. Matching, rúbricas con evidencia, anotación y preguntas avanzadas necesitan mapearse al endpoint y al sobre de eventos antes de entrar.
Nivel C — motor o medio inyectado
CodeExercise, InteractiveMedia, BranchingScenario y SimulationLab necesitan un puerto explícito de ejecución, reproducción o transición de estados. Una simulación es datos + estado + transiciones deterministas + renderer; nunca código inventado por el LLM dentro del programa OpenUI.
Invariantes
- Más componentes aportan riqueza cuando añaden acciones, estados, feedback o representaciones útiles.
- Los hechos críticos y las reglas de seguridad proceden del knowledge pack, no del componente.
- Una preferencia visual no fuerza una imagen sin valor ni permite inventar un asset.
- El answer key nunca llega en las props del navegador.
- Arrastrar nunca es la única vía de interacción.
- Una capacidad ausente produce fallback explícito o
Decline, no una simulación fingida. - La copia de un componente Didact vive en SkillNet y se actualiza deliberadamente; no se consume
mainmutable en producción.
Matriz de runtime del frontend (2026-08-13)
Los 34 tipos estan instalados, tienen loader lazy y pueden referenciarse mediante
DidactActivity(activity_id, component_id). OpenUI nunca recibe la definicion publica,
respuestas correctas ni configuracion de evaluacion. El porcentaje de didact.progress y
didact.mastery-badge lo inyecta el host desde LearnerNodeState; el cliente no puede
escribirlo.
| Estado | Tipos | Motivo |
|---|---|---|
| Usable local/estatico | flashcard, glossary-term, hint-reveal, rubric, timeline-steps, worked-example, data-explorer | No afirman correccion; puertos opcionales ausentes degradan |
| Persistencia host | self-explanation-prompt, concept-map, drawing-response, evidence-annotation | Estado por /activities/{id}/state; dibujo y anotacion aceptan evaluacion async |
| Evaluacion host compatible | equation-workbench, measurement-lab | Callback async con resultado de /activities/{id}/evaluate |
| Evaluacion server-side | matching, sort, categorize, cinco quiz, completion-problem, numeric-question, word-bank | Adaptador SecureEvaluatedActivity; la clave no llega a props, DOM ni eventos |
| Assets revisados | hotspot, label-diagram, interactive-media | Refs opacas skasset_; geometria/transcript verificados en servidor |
| Progreso de solo lectura | progress, mastery-badge | GET /activities/{id}/progress proyecta mastery del nodo; progress.write esta prohibido |
| Bloqueado: composicion/agenda | practice-set, retrieval-practice-session | Compone hijos evaluables o exige scheduler; no se finge |
| Bloqueado: runtime | branching-scenario, simulation-lab | Falta adaptar transiciones remotas al estado concreto del componente |
| Bloqueado: ejecucion | code-exercise | La respuesta generica aun no satisface ArtifactExecutionResponse |
Los endpoints de definicion, estado, evaluacion, transicion, ejecucion, assets y progreso
estan conectados como puertos genericos. Un puerto solo se expone cuando el contrato
concreto es compatible. La mera existencia de /evaluate no desbloquea un quiz que se
autocorrige en el navegador, ni /progress habilita practice-set.
Siguiente ola propuesta
- scheduler real antes de emitir
retrieval-practice-session; - composición de hijos evaluables antes de emitir
practice-set; - transiciones deterministas de
branching-scenarioysimulation-labsobre el estado concreto del componente; - sandbox de
code-exerciseque cumplaArtifactExecutionResponse; - medir las 7 estrategias de selección con el banco offline y, si hay clave, un piloto LLM pequeño.
Cada ola se mide con el mismo nodo y knowledge pack: cobertura de hechos críticos, evidencia obtenible, variedad de acciones, accesibilidad, tasa de reparación, tokens, latencia y estabilidad. No se promueve un componente solo porque su story aislada sea atractiva.
Estado de cierre del 13 de agosto de 2026
- Los 34 tipos de Didact están fijados por commit, inventariados y disponibles mediante loaders lazy; el catálogo completo no aumenta el bundle inicial.
- 29 tipos son emitibles. Cinco siguen bloqueados con honestidad:
practice-set,retrieval-practice-session,branching-scenario,simulation-labycode-exercise. - El runtime usa por defecto
top5sobre una shortlist de 3-5 candidatos. Dual-agent y specialist permanecen en sombra. El catálogo completo permanece consultable por el resolver. - La llamada opcional de autoría registra tokens, modelo y duración; si falla, la lección
continúa con una representación segura. Un tipo
unsupporteddeclina antes del LLM. - El experimento fixture favorece intención + shortlist + esquema específico: 89,8 puntos y 100% de gates, frente a 27,8 del brazo legacy. Es evidencia de arquitectura, no prueba definitiva de calidad LLM.
- La personalización causal sigue siendo débil (15,4% en el fixture). La próxima ronda debe aislar apoyo, presentación y profundidad con modelos reales y evaluación ciega.