diff --git a/docs/UX_AUDIT_AULA_3_3.md b/docs/UX_AUDIT_AULA_3_3.md
new file mode 100644
index 0000000..10173b9
--- /dev/null
+++ b/docs/UX_AUDIT_AULA_3_3.md
@@ -0,0 +1,66 @@
+# Auditoría de interacción: Aula 3.3
+
+## Objetivo
+
+Hacer que el aula sea fácil de entender para estudiantes que están empezando y rápida de operar para un profesor con diez alumnos. Esta revisión no representa una certificación de Stanford, MIT o UDD: aplica principios públicos de diseño centrado en las personas y usabilidad publicados por esas instituciones.
+
+## Referentes aplicados
+
+- Stanford d.school: observar a las personas, definir el problema, probar y volver a iterar. [Design Thinking Bootleg](https://dschool.stanford.edu/tools/design-thinking-bootleg)
+- MIT: priorizar facilidad de aprendizaje, eficiencia, prevención de errores y satisfacción. [Usability](https://ocw.mit.edu/courses/6-831-user-interface-design-and-implementation-spring-2011/pages/in-class-activities/usability/)
+- MIT: mantener visibles el estado del sistema, el control del usuario y la protección de su trabajo. [Heuristic Evaluation](https://web.mit.edu/6.813/www/sp16/classes/20-heuristic-evaluation/)
+- UDD: diseñar la interacción a partir del comportamiento humano y no solo desde la tecnología. [Diseño de Interacción Digital](https://www.udd.cl/internacional/catalogo-cursos-diseno-digital/)
+
+## Recorrido del estudiante
+
+### Problemas observados
+
+- El inicio repetía dos accesos principales para continuar la misma tarea.
+- Una frase prometía un catálogo de práctica que ya no está disponible para estudiantes.
+- Las tareas se abrían mediante una flecha pequeña, aunque toda la fila parecía interactiva.
+- El compilador usaba palabras como `tests`, `diagnósticos` y `provider`, poco útiles para un principiante.
+- El resultado explicaba el estado técnico antes que el siguiente paso.
+
+### Cambios aplicados
+
+- Un solo botón principal lleva a la próxima tarea.
+- Toda la fila de una tarea abre su workspace y funciona con teclado.
+- El inicio explica que allí aparecen solamente las tareas asignadas.
+- El compilador habla de pruebas, errores para corregir y próximos pasos.
+- Los mensajes distinguen con palabras simples si todo salió bien, si hay resultados incorrectos o si el servicio no pudo ejecutar.
+
+## Recorrido del profesor
+
+### Problemas observados
+
+- La navegación lateral se repetía en una segunda barra con las mismas ocho secciones.
+- Ocho indicadores tenían la misma importancia y desplazaban la acción principal.
+- El contador de revisiones podía mostrar estados sin una entrega realmente disponible.
+- “Matriz del curso” y los criterios “Correctitud” o “Casos límite” requerían interpretación.
+- La revisión podía generar un enlace inválido si la versión de una misión ya no estaba en el catálogo local.
+
+### Cambios aplicados
+
+- Se conserva una sola navegación.
+- Las entregas por revisar aparecen primero; luego se muestran cuatro datos esenciales.
+- Los indicadores secundarios quedan bajo “Ver más indicadores”.
+- El contador usa exactamente la misma cola que la pantalla de revisiones.
+- “Estado de las tareas” reemplaza “Matriz del curso”.
+- La lista opcional de revisión usa tres preguntas directas y los botones indican claramente “Pedir cambios” o cuántos XP se aprobarán.
+- “Ver misión” aparece únicamente cuando la versión existe.
+
+## Validación pendiente con personas
+
+Una evaluación heurística detecta problemas probables, pero no reemplaza observar a usuarios reales. Antes de agregar funciones grandes conviene hacer dos sesiones de 20 minutos: una con un estudiante resolviendo y entregando una misión, y otra con eeminionn creando una tarea y corrigiendo dos entregas. Registrar dónde dudan, qué texto leen y cuántas acciones necesitan.
+
+## Funciones grandes no implementadas
+
+Estas ideas necesitan una prueba breve de necesidad antes de construirlas:
+
+1. Recorrido guiado para la primera sesión del estudiante y lista de preparación inicial para el profesor.
+2. Plantillas de corrección configurables por tarea, con criterios definidos por eeminionn.
+3. Corrección en lote para revisar o aprobar varias entregas similares.
+4. Alertas pedagógicas que sugieran a quién ayudar según atrasos, errores repetidos y uso de pistas.
+5. Panel histórico del curso con tendencias semanales y exportación de resultados.
+
+La regla para una próxima iteración será sencilla: una función nueva debe reducir tiempo, evitar un error frecuente o responder una necesidad observada en las sesiones. Si no cumple una de esas condiciones, no entra al aula.
diff --git a/v2/e2e/frontend-only.spec.ts b/v2/e2e/frontend-only.spec.ts
index da65fa7..7236e07 100644
--- a/v2/e2e/frontend-only.spec.ts
+++ b/v2/e2e/frontend-only.spec.ts
@@ -92,10 +92,10 @@ test("frontend sandbox displays mentor controls but blocks mutations", async ({
await page.getByRole("link", { name: /^Revisiones/ }).click();
await expect(
- page.getByRole("button", { name: "Solicitar cambios" }),
+ page.getByRole("button", { name: "Pedir cambios" }),
).toBeDisabled();
await expect(
- page.getByRole("button", { name: "Aprobar y asignar XP" }),
+ page.getByRole("button", { name: /Aprobar \(\+\d+ XP\)/ }),
).toBeDisabled();
await page.getByRole("link", { name: "Premios", exact: true }).click();
await page.getByRole("button", { name: "Nuevo premio" }).click();
diff --git a/v2/e2e/mentor.spec.ts b/v2/e2e/mentor.spec.ts
index e876292..704bc6f 100644
--- a/v2/e2e/mentor.spec.ts
+++ b/v2/e2e/mentor.spec.ts
@@ -18,8 +18,8 @@ test("mentor reviews a pending submission and awards XP once", async ({ page })
.getByLabel("Comentario en línea 2")
.fill("El acumulador debe actualizarse dentro del bucle.");
await page.getByRole("button", { name: "Agregar" }).click();
- await page.getByLabel("Correctitud").check();
- await page.getByRole("button", { name: "Aprobar y asignar XP" }).click();
+ await page.getByLabel("Da la respuesta correcta").check();
+ await page.getByRole("button", { name: /Aprobar \(\+\d+ XP\)/ }).click();
await expect(page.getByText("Cola al día")).toBeVisible();
await page.getByRole("button", { name: "Ver como estudiante" }).click();
@@ -56,6 +56,22 @@ test("mentor creates and edits a configurable invitation", async ({ page }) => {
await expect(invitation.getByRole("button", { name: "Copiar" })).toBeDisabled();
});
+test("mentor overview prioritizes actions without duplicate navigation", async ({
+ page,
+}) => {
+ await loginAsMentor(page);
+ await expect(
+ page.getByRole("button", { name: /entrega espera revisión/ }),
+ ).toBeVisible();
+ await expect(
+ page.getByRole("heading", { name: "Estado de las tareas" }),
+ ).toBeVisible();
+ await expect(
+ page.getByRole("link", { name: "Resumen", exact: true }),
+ ).toHaveCount(1);
+ await expect(page.getByText("Ver más indicadores")).toBeVisible();
+});
+
test("mentor creates an assignment for selected students", async ({ page }) => {
await loginAsMentor(page);
await page.getByRole("link", { name: "Tareas", exact: true }).click();
diff --git a/v2/e2e/student.spec.ts b/v2/e2e/student.spec.ts
index 08c042c..af7e384 100644
--- a/v2/e2e/student.spec.ts
+++ b/v2/e2e/student.spec.ts
@@ -34,7 +34,7 @@ test("opens an assigned mission in two actions and runs visible tests", async ({
await page.getByRole("button", { name: "Ejecutar" }).click();
await expect(
- page.getByText("El código corre, pero aún no pasa todos los tests"),
+ page.getByText("Tu código funciona, pero hay resultados por corregir"),
).toBeVisible({ timeout: 15_000 });
await expect(page.getByText("Qué hacer ahora")).toBeVisible();
await expect(page.getByText("Compara un caso paso a paso")).toBeVisible();
@@ -68,6 +68,10 @@ test("prioritizes pending tasks and shows the mentor brief before the mission",
await expect(pending.locator(".assignment-row").first()).toContainText(
"Variables y acumuladores",
);
+ await expect(pending.locator(".assignment-row").first()).toHaveAttribute(
+ "href",
+ /mission\/la-once-de-tomatin/,
+ );
await approved.locator("summary").click();
await expect(approved).toContainText("Condiciones booleanas");
@@ -254,7 +258,7 @@ test("keeps student edits after running code opened from feedback", async ({
window.__TOMATIN_EDITOR__?.setValue(code);
}, revisedCode);
await page.getByRole("button", { name: "Ejecutar" }).click();
- await expect(page.getByText("Todos los tests pasaron")).toBeVisible({
+ await expect(page.getByText("Todo salió bien")).toBeVisible({
timeout: 15_000,
});
await expect
diff --git a/v2/src/components/AppShell.tsx b/v2/src/components/AppShell.tsx
index dc9130a..7a8479c 100644
--- a/v2/src/components/AppShell.tsx
+++ b/v2/src/components/AppShell.tsx
@@ -28,6 +28,7 @@ import {
useNavigate,
} from "react-router-dom";
import { ProfileAvatar } from "@/components/ProfileAvatar";
+import { getPendingReviews } from "@/models/reviews";
import { useClassroom } from "@/state/classroom-context";
const studentNavigation = [
@@ -81,6 +82,7 @@ export function AppShell() {
const isMentor = isActorStaff && !isStudentPreview;
const students =
snapshot?.profiles.filter((entry) => entry.role === "student") ?? [];
+ const pendingReviews = snapshot ? getPendingReviews(snapshot).length : 0;
return (
{isMentor
? "Revisa entregas, atrasos y actividad desde un solo lugar."
- : "Tareas asignadas primero; el resto del catálogo queda disponible para practicar."}
+ : "Aquí aparecen solamente las tareas que te asignó tu profesor."}