# OBSERVATIONS — Sprint 8

> 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 7 cerrado el 2026-07-07.** Ver reflexiones completas en `STRATEGIC_DIRECTION.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

*(vacío)*

---

## Hallazgos resueltos durante el sprint

*(vacío — sprint recién abierto)*

---

## 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)

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

---

## Aprendizajes de Sprint 7 relevantes para Sprint 8

> Cosecha de método — decisiones y patterns emergentes de Sprint 7 que informan cómo trabajar en Sprint 8.

### Race condition en roles: `isProfileLoaded` como guard

`buildAuthUser()` asigna `platformRole: 'guest'` heurísticamente (por dominio de email) antes de que `syncProfileFromDB` complete. El rol correcto llega ~200ms después. Cualquier UI condicionada por rol que renderice antes de ese sync muestra el estado incorrecto.

**Patrón validado:** `isProfileLoaded: boolean` en AuthContext — se pone en `true` solo después de que `syncProfileFromDB` completa. Componentes que dependen del rol deben esperar `isProfileLoaded` antes de renderizar contenido rol-dependiente.

**Aprendizaje para Sprint 8:** cualquier componente nuevo que condicione su contenido por `platformRole` debe incluir `isProfileLoaded` como prerequisito en su spec de implementación.

### JOIN vs fetch separado: orgName en getById

Fetch separado en `useEffect` para obtener el nombre de la org en `WorkspacePage` fue frágil: race conditions entre `currentProcess` cargando y el efecto, resets de estado al desmontar, y respuesta en array cuando `.maybeSingle()` esperaba objeto. El síntoma (botón mostrando "Biblioteca" en lugar de "Solar Banco") requirió ~8 iteraciones de diagnóstico.

**Fix definitivo:** JOIN en `getById()` con `select('*, org:organizations!org_id(name)')`. El dato llega embebido en el proceso — sin async adicional, sin estado local, sin race condition.

**Aprendizaje para Sprint 8:** cuando un componente necesita datos relacionados de otra tabla para display, preferir JOIN en el repositorio sobre fetch separado en el componente. Los fetches separados en `useEffect` con datos del store como dependencia son estructuralmente frágiles.

### Dos sistemas paralelos de "cliente" → consolidar en Sprint 8

`process_groups`, `clientName` (texto libre) y `org_id` intentaban modelar el mismo concepto ("a qué cliente pertenece el proceso") desde tres ángulos distintos. La confusión generó bugs de UX (back button, agrupación en biblioteca) y deuda conceptual.

**Decisión tomada:** Sprint 8 consolida en `organizations → areas → processes`. Ver `STRATEGIC_DIRECTION.md` → "Consolidación del modelo de cliente".

### Diagnóstico por DOM observable > teorización de librerías

El bug del freeze de perfil (Sprint 5, confirmado resuelto en Sprint 6) y el bug del back button (Sprint 7) compartieron el mismo patrón: múltiples iteraciones de diagnóstico teórico sin resolver → un dato observable del runtime (HTML del DOM, Network tab, respuesta de request) colapsó el espacio de hipótesis en 1 paso.

**Aprendizaje consolidado:** ante bug de UI que persiste 2+ fixes teóricos, pedir el dato observable antes de seguir. Específicamente: HTML del elemento, Network tab con el request real, o `console.log` del valor en runtime.
