Files
inq-roi-simulador-web/OBSERVATIONS.md

7.7 KiB
Raw Blame History

OBSERVATIONS — Sprint 5

Hallazgos descubiertos durante el sprint actual. Este archivo se vacía al cerrar el sprint: los hallazgos se promocionan a TECH_DEBT.md o BACKLOG.md, o quedan resueltos.

Sprint 4 cerrado el 2026-06-18. Observaciones archivadas — ítems migrados a BACKLOG.md y TECH_DEBT.md.


Convención de etiquetas

  • [CURRENT-SPRINT] — Se resuelve en este sprint
  • [DEFERRED-TECH-DEBT] — Se va a TECH_DEBT.md al cerrar el sprint
  • [DEFERRED-BACKLOG] — Se va a BACKLOG.md al cerrar el sprint
  • [RESOLVED] — Resuelto durante el sprint, archivar al cierre

Hallazgos activos

[RESOLVED] Etapa 1 — Workspace loading fix + carry-over skeleton

Estado: OK formal del director — 2026-06-19. Fix principal: process-store.ts y useReportData.ts usaban getSession() sin timeout; reemplazados inicialmente por getSessionSafe(). Error Boundary + estado error inline con retry button agregados. ⚠️ Corrección histórica (Etapa 4E): getSessionSafe() fue identificado como contraproducente y eliminado completamente. Usaba Promise.race con un timeout que abandonaba la Promise interna de getSession(), dejando operaciones huérfanas ocupando el processLock indefinidamente. El fix correcto fue lockAcquireTimeout: 30000 en supabase.ts + eliminación de getSessionSafe() en todos los archivos. El código actual NO usa getSessionSafe(). Carry-over a Etapa 2: WorkspaceSkeleton.tsx fue creado pero el spinner del router-level guard (TanStack Router) intercepta antes de que el componente monte. El skeleton no aparece en la práctica. Corregir en Etapa 2 como Fix 0 (bajo esfuerzo). SupabaseAuthService.ts: su getSession() directo documentado como excepción intencional (necesita el objeto sesión real, no es barrera descartable). Sin callers activos. Ver TECH_DEBT.md para el ítem pendiente.


Hallazgos resueltos durante el sprint

[RESOLVED] Etapas 3 + 3B — Heatmap gradiente + toggle + persistencia

Estado: OK formal del director — 2026-06-19. Entregado: gradiente 4 stops (#10b981→#f59e0b→#f97316→#ef4444), modos percentile/minmax, useHeatmapMode hook con localStorage, HeatmapModeToggle, leyenda PDF 4 stops, zoom controls movidos a bottom-left. Lección operativa: Dokploy con Autodeploy desactivado requiere git push origin main explícito antes de validar en producción. Los commits a65bec4 y e8a4a1b estaban locales sin pushear — Dokploy desplegaba Etapa 2 mientras se validaba Etapa 3. La validación fallida fue contra código desactualizado, no contra bugs reales.

[RESOLVED] Etapa 2 — Zoom BPMN fix + controles + skeleton

Estado: OK formal del director — 2026-06-19. Fixes: fit-viewport 'auto' agregado (una línea), zoom-in/zoom-out en esquina inferior derecha (Lucide icons, 1.2x factor, límites 0.1x4x), skeleton wired correctamente en WorkspacePage (guard isLoading simple sin !currentProcess). Carry-over a Etapa 3: controles de zoom solapan el logo bpmn.io (esquina inferior derecha). Fix: mover a esquina inferior izquierda (left: 12 en lugar de right: 12). Una línea CSS.


[RESOLVED] Etapa 3 — Heatmap gradiente 4 stops + persistencia de modo + zoom position

Estado: pendiente OK formal del director. Fixes Etapa 3:

  • colors.ts: gradiente continuo verde→amarillo→naranja→rojo (interpolación genérica N-stops), modos 'percentile'/'minmax' reemplazan 'relative'/'absolute'
  • useHeatmapMode.ts (hook nuevo): persiste preferencia en localStorage con lazy initializer en useState
  • ReportPage.tsx: reemplaza useState<HeatmapMode>('relative') por useHeatmapMode()
  • BpmnCanvas.tsx: zoom-in/zoom-out movidos de right:12 a left:12 (evita solapar logo bpmn.io)
  • PDF: leyenda de 4 stops con interpolación. Tests: 528 Vitest verdes. E2E recalibrados con distancia euclidiana.

Fixes Etapa 3B verificados (incluidos en Etapa 3):

  • Fix 1 (repintado de canvas al cambiar toggle): mode ya estaba como dependencia del useEffect en HeatmapCanvas.tsx desde el MVP. El bug fue observado durante implementación intermedia; resuelto con los renombres de Etapa 3.
  • Fix 2 (persistencia localStorage): useHeatmapMode() con lazy initializer correcto; ReportPage usa el hook.
  • Fix 3 (zoom position): left: 12 en BpmnCanvas.tsx.

[RESOLVED] Etapa 4 — Recursos por proceso + perfil empresa + fix freeze ProfileSheet

Estado: OK formal del director — 2026-06-23.

Entregado:

  • ResourceCatalogPage: columna "Procesos" con conteo de procesos que usan cada recurso. resource-repo.ts expone getProcessCountsByResourceId() y getProcessesByResourceId() para carga on-demand.
  • Perfil de usuario: campo company en tabla users (Supabase), campo en ProfileSheet, visible en dropdown AppHeader.
  • Fix || vs ?? en cadena de propagación de name: buildAuthUser, getUserFromStorage, syncProfileFromDB, AuthContext useEffect — evita que Google OAuth con full_name: "" deje el botón Guardar deshabilitado.

Bug crítico resuelto — freeze de UI al guardar perfil (12 commits, 2026-06-23):

Dos causas independientes bajo el mismo síntoma ("la app se congela"):

  1. Contención de processLock: supabase.from().update() en ProfileSheet adquiría el lock vía getSession() interno, bloqueando otras queries de la página. Fix: reemplazo por fetch() nativo con token leído de localStorage (supabase.auth.token), sin pasar por el cliente Supabase.

  2. @radix-ui/react-remove-scroll no limpiaba pointer-events:none del body: al cerrar el Sheet, el cleanup de Radix no corría porque el re-render de AuthContext (disparado por updateUser) interrumpía la animación de cierre. document.body.style.pointerEvents = 'none' quedaba permanente, bloqueando toda la UI excepto el canvas BPMN (que fija pointer-events: all en su propio SVG). Fix: wrapper Sheet en src/components/ui/sheet.tsx con useEffect que observa el prop open y limpia el body 400ms después del cierre si no hay otro dialog abierto.

Lección operativa (cosechada a methodology/): ante un bug de UI que persiste tras 2+ fixes teóricos basados en lectura de código, pedir evidencia observable directa (DOM, Network, consola) antes de continuar. El diagnóstico definitivo llegó de un dato: document.body.style.pointerEvents = 'none'. Ver INFORME_ETAPA_4_FREEZE_PERFIL.md para cronología completa.

Archivos modificados:

  • src/auth/SupabaseAuthService.ts|| en buildAuthUser y syncProfileFromDB
  • src/auth/AuthContext.tsx|| en getUserFromStorage y useEffect de sync
  • src/components/ProfileSheet.tsx — fetch nativo, optimistic close, defer updateUser 350ms
  • src/components/ui/sheet.tsx — wrapper defensivo con cleanup de pointer-events
  • src/lib/supabase.tslockAcquireTimeout: 30000, eliminación de getSessionSafe()
  • src/store/library-store.ts, src/store/process-store.ts, src/features/report/useReportData.ts — eliminación de getSessionSafe()

Hallazgos diferidos (promocionar al cerrar sprint)

(vacío)


Notas operativas

  • Los hallazgos resueltos quedan acá hasta el cierre del sprint. Al cerrar, se archiva o purga.
  • Los hallazgos sin resolver se promocionan a TECH_DEBT.md o BACKLOG.md según corresponda.
  • Este archivo NO contiene roadmap futuro ni deuda histórica — solo hallazgos del sprint en curso.

Cierre del sprint (checklist)

Cuando el sprint cierre, ejecutar:

[ ] Verificar que todos los items [CURRENT-SPRINT] están RESOLVED
[ ] Mover items [DEFERRED-TECH-DEBT] a TECH_DEBT.md (si no están ya)
[ ] Mover items [DEFERRED-BACKLOG] a BACKLOG.md (si no están ya)
[ ] Archivar o purgar este archivo
[ ] Crear OBSERVATIONS.md vacío para el sprint siguiente