Files
inq-roi-simulador-web/sprints/sprint-5/BRIEF.md
Marcos Benítez a2763ab755
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
Sprint 5. Etapa 1.
2026-06-19 15:31:03 -03:00

12 KiB
Raw Blame History

Sprint 5 — BRIEF

InQ ROI — Sprint de UX polish + quick wins Inicio: 2026-06-19 Foco: experiencia del usuario, mejoras visuales, features de alto impacto/bajo esfuerzo


Contexto

Sprint 4 fue un refactor arquitectural completo (IndexedDB → Supabase, auth, recursos globales). El producto está estable y en uso interno. Sprint 5 vuelve al rebalanceo normal: 60-70% features de producto, 10-15% infra/deuda técnica.

Sin features de gran escala (historial de simulaciones, compartir con guests). Solo mejoras que suman experiencia real.


Etapas

Etapa 1 — Fix crítico: workspace loading

Problema: Al navegar desde la biblioteca a un proceso, el workspace se queda cargando indefinidamente. La pantalla solo carga correctamente después de refrescar la página manualmente.

Diagnóstico a confirmar: probable race condition entre useEffect de carga del proceso y disponibilidad del usuario autenticado. El processId llega por route params antes de que el store tenga el usuario listo, y el query a Supabase se dispara con un contexto incompleto o se omite silenciosamente.

Alcance:

  • Diagnosticar el flujo completo: WorkspacePageuseProcess hook → process-repo.getById() → render
  • Identificar dónde el guard de auth interactúa mal con la carga del proceso
  • Corregir sin introducir flickering ni doble render
  • El workspace debe cargar al primer intento, sin refresh

Criterios:

  • Navegar desde la biblioteca a cualquier proceso carga el workspace en el primer intento
  • Sin errores en consola durante la navegación
  • El estado de loading muestra un skeleton o spinner visible (no pantalla en blanco)
  • Tests Vitest verdes (sin regresiones)
  • Validación visual del director

Etapa 2 — Fix + mejora: zoom BPMN

Problema: El botón de fit-viewport actual posiciona el diagrama pegado al borde superior, sin padding. Además no hay controles de zoom explícitos.

Alcance:

Fix fit-viewport:

  • Corregir canvas.zoom('fit-viewport') para que el diagrama quede centrado con padding uniforme (sugerido: 40px en todos los bordes)
  • bpmn-js expone canvas.zoom('fit-viewport', true) y opciones de padding — usar la API correcta

Controles de zoom (versión wow):

  • Botón "+" (zoom in) y "" (zoom out) en el canvas
  • Botón de reset/fit (ícono de encuadre) — corrige el bug actual + sirve de reset
  • Posición: esquina inferior derecha del canvas, sin tapar el diagrama
  • Estilo: botones cuadrados de 32px, fondo blanco semitransparente, borde sutil, ícono Tabler
  • No interferir con el zoom por scroll/pinch que ya funciona

Íconos sugeridos: ti-zoom-in, ti-zoom-out, ti-focus-2 (para fit)

Criterios:

  • Fit-viewport centra el diagrama con padding uniforme (no clip al borde)
  • Botones +//fit visibles en el canvas
  • +/ hacen zoom in/out incremental (factor 1.2x por click)
  • Fit resetea a la vista centrada
  • Los controles no aparecen encima de los paneles laterales
  • Tests Vitest verdes
  • Validación visual del director

Etapa 3 — Heatmap con gradiente continuo + toggle de modo

Problema actual: el heatmap usa 3 buckets discretos (verde/amarillo/rojo) con colores fijos. Sin matices intermedios, sin gradiente.

Alcance:

Escala de color continua: Reemplazar la lógica de 3 buckets por una función de interpolación de 4 stops:

0.0 → #10b981 (verde)
0.33 → #f59e0b (amarillo)
0.67 → #f97316 (naranja)
1.0  → #ef4444 (rojo vivo)

Implementar en src/lib/colors.ts como intensityToColor(normalized: number): string usando interpolación lineal en RGB entre stops consecutivos.

Dos modos de normalización:

percentile (default): cada actividad se posiciona según su rango relativo entre todas las actividades del proceso. No sufre distorsión por outliers.

minmax: (costo - mínimo) / (máximo - mínimo). Refleja valores absolutos pero se comprime con outliers.

Persistencia del modo: guardar la preferencia en localStorage (key: heatmap-mode). Default: percentile.

Toggle en UI:

  • Un toggle compacto en el panel del reporte o en la barra de herramientas del workspace
  • Label: "Escala de color: Relativa (percentil) / Absoluta (min-max)"
  • Tamaño pequeño, no protagonista — es una preferencia técnica, no el flujo principal

Dónde aplica el heatmap:

  • Nodos del canvas BPMN (overlay de color en actividades)
  • Tabla del reporte web (fondo de celdas de costo)
  • PDF: usa los mismos valores calculados pero sin el toggle (renderiza el modo activo al exportar)

Recalibrar E2E de píxeles: los tests que verifican colores del canvas BPMN necesitan actualizar sus umbrales/valores esperados para la nueva escala. Identificar los specs afectados y corregirlos.

Criterios:

  • El gradiente muestra transiciones suaves (no saltos abruptos de verde a rojo)
  • Modo percentil: actividades distribuidas a lo largo de la escala incluso con outliers
  • Modo min-max: outlier extremo domina la escala (comportamiento esperado)
  • Toggle funciona y persiste entre sesiones
  • PDF exporta con el modo activo al momento de la exportación
  • Tests E2E de heatmap recalibrados y verdes
  • Tests Vitest verdes (nueva función intensityToColor con tests unitarios)
  • Validación visual del director

Etapa 4 — Ver procesos por recurso + campo empresa en perfil

Dos features pequeñas en una etapa.

Feature A — Ver procesos asociados a un recurso:

En ResourceCatalogPage (/recursos), cada fila de la tabla debe mostrar cuántos procesos usan ese recurso.

  • Nueva columna "Procesos" en la tabla: muestra un badge con el número (ej: 3 procesos)
  • Si es 0: muestra "—" con color muted
  • Si es > 0: el badge es clickeable y expande una lista de los procesos (nombre + link directo al workspace)
  • La expansión puede ser inline (fila expandible) o un popover/tooltip al hover
  • Dato: query a activity_resource_assignments agrupado por resource_id, con JOIN a processes para el nombre
  • Esto complementa la protección de borrado existente — ahora el usuario ve qué proceso usa el recurso antes de intentar eliminarlo

Feature B — Campo empresa en perfil de usuario:

  • Nueva columna company text en tabla users de Supabase (nullable, sin default)
  • Migración: ALTER TABLE users ADD COLUMN IF NOT EXISTS company text;
  • UI: en el dropdown del AppHeader (donde aparece nombre y email), agregar una línea con la empresa si está definida
  • Edición: agregar un botón "Editar perfil" en el dropdown que abre un Sheet con campos editables: nombre y empresa (email es de solo lectura — viene de Google OAuth)
  • La empresa se muestra también en la tabla de la biblioteca si hay espacio (opcional, decidir con validación visual)

Criterios:

  • Columna "Procesos" visible en /recursos con conteo correcto
  • Click en el badge con conteo > 0 muestra la lista de procesos con links funcionales
  • Columna company creada en Supabase sin romper datos existentes
  • El dropdown del AppHeader muestra la empresa si está definida
  • Sheet de edición de perfil guarda nombre y empresa en Supabase
  • Tests Vitest verdes
  • Validación visual del director

Etapa 5 — Columna "Eficiencia de automatización"

Contexto: la tabla de comparación (ComparisonTable) hoy muestra costo AS-IS, costo TO-BE, ahorro y probabilidad. Le falta una métrica que permita rankear actividades por valor de automatización — no solo quién ahorra más en valor absoluto, sino qué actividades ofrecen el mejor retorno por peso invertido.

Métrica:

eficiencia = (ahorro$ × probabilidad) / tiempo_ejecucion_minutos

Alternativa si no hay inversión por actividad: usar ahorro$ × probabilidad como proxy simple (ahorro esperado ponderado). Decidir en implementación cuál es más interpretable para un consultor.

Alcance:

  • Nueva columna "Eficiencia" en ComparisonTable del reporte web
  • Valor = ahorro esperado ponderado por probabilidad de automatización
  • Ordenar la tabla por esta columna por defecto (mayor eficiencia primero) — con posibilidad de cambiar el orden haciendo click en el header
  • Versión wow: barra de progreso inline de ancho relativo (la actividad más eficiente = 100%, las demás proporcionales). Mismo estilo que las barras del heatmap
  • Tooltip en el header de la columna explicando la fórmula
  • Si isAutomatable = false: mostrar "—" (em dash), igual que columna Ahorro

En PDF:

  • Incluir la columna en la tabla de comparación del PDF si entra sin truncamiento
  • Si no entra, omitirla (el PDF ya es denso) — decidir en validación visual

Criterios:

  • Columna visible en el reporte web con valores correctos
  • Actividades no automatizables muestran "—"
  • Orden por defecto: mayor eficiencia primero
  • Click en header reordena la tabla
  • Barra de progreso proporcional visible
  • Tooltip en header con explicación de la fórmula
  • Cálculo tiene tests unitarios en Vitest
  • Validación visual del director

Etapa 6 — Limpieza técnica

6a — E2E: reescribir specs Dexie → Supabase

  • export-pdf.spec.ts y validate-dod-etapa4.spec.ts inyectan datos vía Dexie/IndexedDB, que fue eliminado en Sprint 4
  • Reescribir fixtures para usar el test user martin.bernal@inquality.com.py via Supabase
  • Limpiar datos de test después de cada corrida (usar afterAll con service_role_key)

6b — E2E: fix flakiness "Guardar cambios"

  • 3 specs fallan intermitentemente por timing: Playwright no encuentra el botón en estado habilitado
  • Fix: await page.waitForSelector('[data-testid="save-btn"]:not([disabled])') o equivalente
  • Agregar data-testid="save-btn" al botón en ActivityPanel.tsx si no existe

6c — Limpieza de BACKLOG y documentación

  • Marcar como [RESOLVED] en BACKLOG.md: "Indicador de simulación desactualizada", "Edición inline de proceso/cliente", "Controles de zoom BPMN" (resueltos en Sprints 2/3 y Etapa 2 de este sprint)
  • Actualizar STRATEGIC_DIRECTION.md con cierre de Sprint 4 (pendiente desde sesión anterior)
  • Vaciar OBSERVATIONS.md y preparar encabezado para Sprint 5
  • Marcar como [RESOLVED] en TECH_DEBT.md los ítems resueltos en esta etapa

Criterios:

  • export-pdf.spec.ts y validate-dod-etapa4.spec.ts verdes en CI con Supabase real
  • 3 specs flaky del botón "Guardar" estables
  • npm run test — mantener o superar conteo anterior de Vitest
  • npx playwright test — 0 specs permanentemente rojos
  • BACKLOG, TECH_DEBT, STRATEGIC_DIRECTION y OBSERVATIONS actualizados
  • Validación del director sobre el estado de los archivos

Distribución del sprint

Área Etapas %
Features de producto / UX 1, 2, 3, 4, 5 ~83%
Infraestructura / deuda técnica 6 ~17%
PDF (toca en Etapa 3 y 5, sin etapa dedicada)

Dentro del rango válido del rebalanceo (60-70% web, 10-15% infra). PDF sin etapa dedicada — aceptable este sprint dado que Sprint 4 no tocó PDF.


Qué NO entra en Sprint 5

  • Historial de simulaciones / múltiples simulaciones por proceso
  • Implementación real de setShared() (diferida hasta primer guest)
  • Keycloak / migración de auth
  • Modo offline / PWA
  • i18n
  • Export Excel
  • Gateway OR inclusivo

Definition of Done del sprint

  • 6 etapas con OK formal del director (validación visual de cada una)
  • npm run build limpio
  • npm run lint sin warnings
  • Tests Vitest: mantener o superar conteo de Sprint 4
  • Tests E2E: 0 specs permanentemente rojos
  • CHECKLIST_ENTREGA.md ejecutado antes de cada entrega de etapa
  • OBSERVATIONS.md con hallazgos del sprint al cierre
  • STRATEGIC_DIRECTION.md actualizado con Sprint 4 y 5