# Operación del DOFA en el retiro — guion del consultor

Versión 1.0 · 4 de septiembre de 2026
Para el Retiro 1 de FEDEF, sábado 5 de septiembre de 2026, 8:00 a 12:30.

Este documento es el guion de uso de la plataforma. Complementa:

- `docs/ESPECIFICACION_DOFA_v2.md` — qué hace el módulo y por qué (manda en caso de duda).
- `docs/ACCESO_RETIRO.md` — cómo dejar el ingreso por QR listo para la red local.
- `docs/CONTRATO_RUTAS.md` — rutas, modelos y props, para quien toque el código.

Todo lo que aquí se pide se hace desde la pantalla; no hace falta abrir la consola salvo en la
preparación de la víspera y en la sección de solución de problemas.

---

## 0. Resumen en una página

| Momento | Qué hace el consultor | Qué se ve en el video beam |
|---|---|---|
| Viernes | Cargar participantes, imprimir tarjetas, fijar `ACCESO_URL`, crear la sesión, ensayo | — |
| 8:00 | Nada en la plataforma (apertura hablada) | Presentación |
| 9:40 | Panel → **Abrir aportes**; repartir tarjetas | Monitor: QR grande y contador de aportes |
| 10:10 | Panel → **Pasar a consolidación**; Consolidar → **Consolidar con IA** | Monitor: "El facilitador está consolidando" |
| 10:20 | Revisar, editar y **Publicar y abrir calificación** | Monitor: lista de factores |
| 10:25 | (la fase ya está abierta) | Monitor: barras de avance por persona |
| 10:45 | Panel → **Abrir cruces** | Monitor: barras de avance de cruces |
| 11:05 | Panel → **Cerrar y calcular**; abrir Resultados | Monitor: MEFI, MEFE, MIME, cuadrantes, tendencias |
| 12:20 | Exportar PDF y Excel | Resultados |

Regla de oro: **el cálculo solo cuenta a quien envió**. Si alguien no alcanza a enviar, no entra
en los promedios. Se puede recalcular cuantas veces se quiera; cada cálculo guarda una versión.

---

## 1. Antes del retiro (viernes por la noche o sábado a las 7:00)

### 1.1 Levantar la plataforma

```bash
cd "C:\PROPOSITO\DEV\Estrategia FEDEF\estrategia"
docker compose -f docker/compose.yaml up -d
```

Esperar a que responda `http://localhost:8080/up`. La primera vez tarda varios minutos.

Comprobar que la plataforma quedó en modo "sala llena". Son dos ajustes que ya están en el
repositorio y que hay que verificar porque cambian el día y la noche con 15 celulares:

```bash
docker compose -f docker/compose.yaml exec -T app php -r "echo 'opcache: '.ini_get('opcache.enable_cli').PHP_EOL;"
docker compose -f docker/compose.yaml logs app | grep -c "single server"
```

El primero debe imprimir `opcache: 1`. El segundo debe imprimir `0` (ningún aviso). Si el opcache
sale en 0, falta reconstruir la imagen:
`docker compose -f docker/compose.yaml build app && docker compose -f docker/compose.yaml up -d app`.
El porqué está en `docs/CONTRATO_RUTAS.md`, sección 7.

### 1.2 Poner la llave de la IA (imprescindible para consolidar con IA)

En `.env.docker`, línea `ANTHROPIC_API_KEY`, reemplazar `sk-ant-PENDIENTE` por la llave real y
reiniciar el contenedor:

```bash
docker compose -f docker/compose.yaml restart app
```

Comprobar que quedó puesta:

```bash
docker compose -f docker/compose.yaml exec -T app php artisan tinker --execute="echo strlen(config('services.anthropic.api_key')), PHP_EOL;"
```

Debe imprimir un número largo (más de 90), no 16.

**El reinicio es obligatorio**, no basta con `php artisan config:clear`: el proceso del servidor
guarda las variables de entorno con las que arrancó, así que hasta que se reinicie el contenedor
la aplicación sigue viendo la llave vieja. (Comprobado: con la llave puesta pero sin reiniciar, la
consolidación seguía respondiendo "La llave de la IA no está configurada".)

Comprobación de que la IA responde de verdad, con **una sola llamada** al modelo:

```bash
docker compose -f docker/compose.yaml exec -T app php docker/ensayo_retiro.php --ia --participantes=3
```

**La aplicación avisa sola.** Mientras la llave siga en `sk-ant-PENDIENTE`:

- el Panel muestra una banda ámbar permanente ("La llave de la IA no está configurada"),
- la pantalla Consolidar muestra la misma banda y **deshabilita** el botón "Consolidar con IA"
  (rótulo "Consolidar con IA (sin llave configurada)"), señalando el camino manual,
- la pestaña "Lectura de IA" de Resultados deshabilita "Generar lectura" y lo explica.

Así la decisión se toma la víspera y no delante de la junta.

**Si no hay llave, el retiro se puede hacer igual**: la consolidación se escribe a mano en la
misma pantalla (sección 4.3). Conviene decidirlo antes, no en vivo.

### 1.3 Fijar la dirección de la red local

Los celulares no pueden abrir `localhost`. En el computador del consultor, `ipconfig`, tomar la
IPv4 de la red del retiro y ponerla en `.env.docker`:

```
ACCESO_URL=http://192.168.1.50:8080
```

Aplica en la siguiente petición, sin reiniciar. Comprobarlo **desde un celular** abriendo
`http://192.168.1.50:8080/acceso` antes de imprimir nada. El detalle está en `docs/ACCESO_RETIRO.md`.

**La aplicación avisa sola.** Mientras `ACCESO_URL` esté vacío o apunte a `localhost`:

- el Panel y la pantalla de Participantes muestran una banda **roja** con el texto de qué cambiar,
- el botón "Imprimir tarjetas" queda gris y **pide confirmación explícita** antes de abrir el PDF,
- el Monitor muestra el aviso junto al QR grande del video beam.

Es la casilla que más fácil se olvida a las 7 de la mañana y la que rompe el bloque de las 9:40
para los quince a la vez.

### 1.4 Borrar los usuarios de prueba y cargar la lista real

En `http://localhost:8080/participantes`:

1. Eliminar todo participante de prueba que quede en la tabla (botón Eliminar de cada fila).
2. Pegar la lista real en el cuadro de carga masiva, una persona por línea:

```
Nombre Apellido; correo (opcional); cargo; rol
Natalia Forero Duran; gerente@fedef.com.co; Gerente; participante
Ana María Pérez; ; Presidenta de la junta; participante
```

- El rol por defecto es `participante`. Solo el consultor lleva rol `consultor`.
- Sin correo se genera uno interno; no se envía nada por correo.
- Cada persona recibe un código de 6 caracteres y un enlace mágico con QR, vigentes 72 horas.
- El alfabeto del código **excluye O, 0, I y 1** para que nadie los confunda.

Verificar que la tabla muestra a todos con su código y "Vigente". La columna Estado distingue
cuatro casos: **vigente**, **en sesión** (vigente y con la sesión abierta ahora mismo en su
celular), **vencido** (tuvo código y caducó) y **sin código** (nunca se le generó; se
arregla con "Regenerar" en su fila). Quien esté "sin código" **no sale en el PDF de tarjetas**, y la
pantalla lo avisa arriba con el número de personas en esa situación.

### 1.5 Imprimir las tarjetas

Botón **Imprimir tarjetas** (o `http://localhost:8080/participantes/tarjetas.pdf`). Salen 8
tarjetas por hoja carta con nombre, cargo, código, QR y la URL corta. Imprimir, recortar y
llevar además **dos o tres tarjetas de repuesto** de personas que quizá no lleguen: sirven para
sustituir a un invitado de último momento sin volver al computador.

El PDF **excluye** a quien no tenga código y **marca en rojo** ("ACCESO VENCIDO · NO REPARTIR") a
quien lo tenga caducado, para que ninguna tarjeta inservible llegue a la mesa.

Comprobación: escanear un QR con un celular y confirmar que abre `/participar`. Después
**cerrar sesión en ese celular** para no gastar el acceso de esa persona.

### 1.6 Crear la sesión del retiro

En `http://localhost:8080/projects/1/dofa` (Panel):

1. **Nueva sesión**, nombre por ejemplo `Retiro 1 · DOFA · 5 de septiembre`.
2. Configuración recomendada (los rótulos son **los de la pantalla**, en
   Panel → Configuración → Editar):

| Parámetro (rótulo en pantalla) | Valor | De fábrica | Por qué |
|---|---|---|---|
| Factores por categoría | 7 | 7 | 28 factores calculables más las tendencias |
| Modo de cruces | individual | individual | Cada quien cruza desde su celular |
| **Limitar cruces a N** | **6** | **6** | 6 internos x 6 externos = **36 parejas por persona**. Sin límite serían 14 x 14 = **196**, seis segundos por pareja para caber en los 20 minutos del bloque: no cabe |
| Mín. aportes por categoría | 2 | **1** | Obliga a pensar sin cansar. **Viene en 1: hay que cambiarlo a mano** |
| Máx. aportes por categoría | 5 | 5 | Evita que uno solo llene la lista |
| Permitir editar tras enviar | no | no | Congela lo enviado |
| Mostrar banco de factores 2024 / Mostrar insumos | sí | sí | Da material a quien se queda en blanco |

Debajo del campo "Limitar cruces a N" la pantalla dice cuántas parejas por
persona y cuántos minutos de bloque supone la configuración actual. **Decida el
límite antes del viernes**: el conjunto de factores que se cruzan se congela al
abrir la fase de cruces, y cambiarlo después borra ese conjunto y recalcula el
top-N.

3. **Inscribir participantes**: seleccionar a todos los de la lista y guardar.

Al escribir el nombre, el campo trae una sugerencia (`Retiro 1 · DOFA`, sin la
fecha) que **se selecciona entera al hacer clic**: escriba encima sin borrar. Ese nombre acaba en el Monitor proyectado, en el PDF y
en el nombre del archivo exportado.

Importante: la sesión activa es **la última no cerrada**. Si hay sesiones viejas sin cerrar,
ciérrelas o bórrelas, porque `/participar` resuelve a la de mayor id no cerrada. Cuando haya dos o
más sin cerrar, el Panel lo avisa arriba y dice **cuál es la que están viendo los celulares**.

### 1.7 Ensayo rápido (15 minutos, la víspera)

Con la aplicación en marcha:

```bash
docker compose -f docker/compose.yaml exec -T app php docker/ensayo_retiro.php --participantes=3
```

Recorre el sábado entero por HTTP real (crea sus propios usuarios y su propia sesión, y los borra
al terminar) y debe acabar en **SIN FALLOS**. Si quiere ver también la consolidación con la IA
real, añada `--ia`; eso gasta una llamada al modelo y deja el resultado en
`docs/ejemplo_consolidacion_ia_2.json`.

Después, con un celular propio: entrar con un código, escribir un aporte y borrarlo.

**No compile los assets (`npm run build`) mientras el ensayo corre.** Durante la compilación, la
carpeta `public/build` queda a medias y cualquier página devuelve 500 ("Vite manifest not found").
Es un fallo transitorio del ensayo, no de la aplicación, pero confunde el resultado.

### 1.8 Cuánto tarda cada cosa (medido)

Medido de nuevo el 4 de septiembre de 2026 con `docker/ensayo_retiro.php --participantes=15` en el
computador del consultor, con la aplicación en Docker y **nada más corriendo**. Los tiempos de los
participantes son **en serie** (el ensayo simula a las quince personas una detrás de otra): en la
sala las peticiones llegan a la vez y el servidor las atiende en paralelo, así que la espera que
siente cada persona es bastante menor.

Se dan dos columnas porque el tamaño del ejercicio cambia el trabajo: la corrida A tuvo 28 factores
calculables y 196 cruces por persona (el máximo previsto, 7 por categoría); la corrida B, con la
consolidación real de la IA, dejó 20 factores y 96 cruces.

| Paso | A · 28 factores, 196 cruces | B · 20 factores, 96 cruces |
|---|---|---|
| Carga masiva de 15 participantes | 17,4 s | 9,7 s |
| PDF de tarjetas | 7,4 s | 3,2 s |
| Entrada de los 15 con su código | 78,9 s (\*) | 31,6 s |
| Los 15 escriben y envían 150 aportes | 72,6 s | 58,9 s |
| **Consolidación con IA (API real)** | — | **98,6 s** |
| Los 15 califican y envían | 52,4 s | 36,7 s |
| Los 15 cruzan y envían | 107,0 s | 45,1 s |
| **Calcular con 15 participantes** | **1,2 s** | **1,3 s** |
| Cerrar la sesión (recalcula) | 0,2 s | 0,2 s |
| Pantalla de resultados | 0,8 s | 0,8 s |
| Sondeo del monitor (cada 5 s) | 0,2 s | 0,3 s |
| Exportar PDF | 4,2 s | 4,0 s |
| Exportar Excel | 3,0 s | 4,5 s |

(\*) En la corrida A se estaba compilando `npm run build` al mismo tiempo, lo que dejó a un
participante sin poder entrar (500 transitorio por el manifiesto de Vite a medio escribir). En frío
la entrada de los quince tardó 31,6 s. **No compile assets durante el ensayo ni durante el retiro.**

La consolidación con IA es lo único que hace esperar de verdad: **98,6 segundos** con 150 aportes
(21.178 tokens de entrada y 8.789 de salida, modelo `claude-opus-5`), y el sistema espera hasta 5
minutos antes de darse por vencido. Ocurre durante el refrigerio, y el botón muestra un contador de
segundos con una barra animada, así que se ve que está trabajando.

---

## 2. Lista de verificación de la mañana (7:30)

Marcar una por una antes de que entre la gente:

- [ ] El computador está conectado a la red del retiro y **no se suspende** (plan de energía en alto rendimiento, tapa abierta).
- [ ] `docker compose -f docker/compose.yaml ps` muestra `app`, `db`, `redis` y `queue` en marcha.
- [ ] `http://localhost:8080/up` responde.
- [ ] El frontend está compilado y al día: el Panel **no** muestra el aviso ámbar "Falta el
      frontend compilado" ni "Hay cambios de interfaz sin compilar". Comprobación equivalente
      desde la terminal:
      `docker compose -f docker/compose.yaml exec -T app php -r "echo is_file('public/build/manifest.json') ? 'ok' : 'FALTA';"`.
      **No compile el sábado**: mientras Vite reescribe `public/build`, todas las pantallas
      responden 500 y el síntoma en la sala es "no puedo entrar con mi código".
- [ ] Desde un celular, `http://<IP>:8080/acceso` abre la pantalla del código.
- [ ] La llave de Anthropic está puesta (sección 1.2) o está decidido consolidar a mano.
- [ ] La sesión del retiro existe, está en fase **configuración** y tiene inscritos a todos.
- [ ] Las tarjetas están impresas y recortadas, con las de repuesto.
- [ ] El video beam muestra el Monitor a pantalla completa (F11) y se lee desde el fondo de la sala.
- [ ] Hay una segunda ventana con el Panel, en otra pestaña o en la pantalla del portátil.
- [ ] El wifi de la sala admite a todos los celulares (probar con dos o tres).

Las tres pantallas que se usan todo el tiempo:

| Pantalla | URL | Para qué |
|---|---|---|
| Panel | `/projects/1/dofa` | Cambiar de fase y ver quién va enviando |
| Monitor | `/projects/1/dofa/sesiones/{id}/monitor` | Lo que ve la sala en el beam |
| Consolidar | `/projects/1/dofa/sesiones/{id}/consolidar` | La consolidación con IA y la lista final |

---

## 3. Durante el retiro

Horario de la sección 13 de la especificación. El refrigerio se sirve a las 10:00 **sin detener
la sesión**.

> **Cada cambio de fase pide confirmación.** Al pulsar "Abrir aportes", "Pasar a consolidación",
> "Abrir calificación", "Abrir cruces" o "Cerrar y calcular", la plataforma muestra un diálogo
> propio (no el cuadro gris del navegador) del tipo *"¿Pasar a la fase «Aporte de factores»?"* o
> *"¿Publicar los factores (F: 5, D: 5, O: 5, A: 5, T: 4) y abrir la calificación? Se asignarán
> códigos definitivos."*. Hay que **confirmar** con el botón del diálogo (Escape lo cierra);
> si se cancela, no pasa nada y la sesión se queda donde estaba. Lo mismo ocurre al publicar los
> factores desde Consolidar.

### 8:00 · Apertura (10 min)

Nada que tocar en la plataforma. Dejar el Monitor puesto: ya muestra el QR general y sirve de
telón de fondo.

### 8:10 · Bloque 1 y 9:05 · Bloque 2 (90 min)

Exposición. Si quiere apoyarse en datos del diagnóstico, la pantalla **Insumos**
(`/projects/1/dofa/insumos`) tiene las voces del equipo, los **34 factores** del DOFA 2024 con sus
pesos, las cifras clave y las tendencias sugeridas. En la pestaña "Factores 2024", debajo de la
tabla, hay un bloque aparte con las **advertencias sobre el archivo de 2024** (no son factores:
son notas de auditoría sobre cómo se hizo aquel ejercicio).

### 9:40 · Bloque 3a · Aporte de factores (30 min)

1. Explicar las cinco categorías con un ejemplo de cada una.
2. Repartir las tarjetas.
3. **Panel → Abrir aportes.**
4. Poner el Monitor en el beam: se ve el QR grande, el contador de aportes por categoría y las
   iniciales de quien ya envió, en verde.

Qué decir mientras escriben:

> Cada uno escriba al menos dos de cada tipo. No busque la frase perfecta: la IA y yo vamos a
> depurar la redacción. Lo que importa es que esté la idea. Cuando termine, pulse "Enviar mis
> aportes".

A las 10:00 entra el refrigerio y quien va terminando se levanta. Cuando el Monitor muestre la
mayoría en verde, avisar: "dos minutos y cierro los aportes".

**Con que hayan enviado la mayoría basta**: los que falten pueden seguir escribiendo hasta que
usted cambie de fase.

### 10:10 · Consolidación con IA (15 min)

1. **Panel → Pasar a consolidación.** Los celulares muestran "El facilitador está consolidando".
2. Abrir **Consolidar**.
3. En la **columna del medio** ("Propuesta de la IA"), enlace **Parámetros**: dejar "factores por
   categoría" en 7 y, si quiere, escribir una instrucción adicional (por ejemplo: "insiste en
   separar lo interno de lo externo"). La columna de la derecha es la lista final.
4. Pulsar **Consolidar con IA**. El botón se convierte en un contador de segundos con una barra
   animada: no está congelado, está esperando al modelo.

Cuánto tarda: **unos 100 segundos** con 150 aportes (medido el 4 de septiembre contra la API real:
98,6 s, 21.178 tokens de entrada y 8.789 de salida con `claude-opus-5`); el sistema espera hasta 5
minutos antes de darse por vencido. Es el único momento del día en que hay que esperar a la máquina.

Qué decir mientras la IA trabaja (el grupo está en refrigerio):

> Mientras la inteligencia artificial agrupa lo que ustedes escribieron, aprovechen el
> refrigerio. Lo que está haciendo no es opinar: está juntando lo que dijeron con palabras
> distintas, separando lo interno de lo externo y proponiendo una redacción común. La decisión
> sigue siendo de ustedes y yo la reviso antes de que la califiquemos.

5. Cuando llegue la propuesta: **Aplicar propuesta**. Los factores pasan a la lista final.
6. Revisar la lista con la sala en pantalla:
   - Corregir la redacción haciendo clic en el texto.
   - **Fusionar (2)** si dos dicen lo mismo; **Dividir** si uno mezcla dos ideas.
   - Arrastrar para ordenar; los primeros llevarán los códigos F1, D1, O1, A1, T1.
   - Añadir desde el banco 2024 o desde los insumos si falta algo obvio. Lo que ya esté en la
     lista aparece marcado como **"Ya agregado"** y no se puede duplicar por error.
   - Si se borra un factor con la **×**, aparece un aviso con **Deshacer** durante unos segundos.
7. **Publicar y abrir calificación.** Aquí se asignan los códigos y ya no se puede cambiar la
   lista sin volver atrás.

Revisar antes de publicar, en un minuto:

- ¿Hay 7 de cada categoría (o menos, si no había material)?
- ¿Cada factor se lee como "FEDEF tiene…" o "FEDEF enfrenta…"?
- ¿Ninguno propone una acción ("mejorar la comunicación" es una acción, no una debilidad)?
- ¿Las tendencias son cambios del entorno a 3-5 años y no oportunidades puntuales?

### 10:25 · Calificación (20 min)

La fase ya quedó abierta al publicar. En el beam, el Monitor muestra una barra de avance por
persona.

Qué decir:

> Para cada factor: qué tan importante es de 1 a 10, si es mayor o menor, y qué prioridad le da.
> Se guarda solo, no hay que pulsar nada hasta el final. Al terminar marquen las tres tendencias
> que más los inquietan y pulsen "Enviar".

Son 28 factores. Quien va lento se ve en el Monitor: se le puede ayudar sin nombrarlo.

### 10:45 · Cruces (20 min)

**Panel → Abrir cruces.**

Qué decir:

> Ahora la pregunta es distinta: para cada fortaleza o debilidad, qué tanto se relaciona con cada
> oportunidad o amenaza. No es si es buena o mala: es si tienen que ver una con otra. Ninguna,
> baja, regular, media o alta. Van de a un factor interno por pantalla.

Son 196 parejas por persona: es la parte más larga. Si la sala se agota, se puede cerrar con lo
que haya: **el cálculo solo cuenta a quien envió**.

### 11:05 · Resultados en vivo (10 min)

1. **Panel → Cerrar y calcular.** El cálculo tarda unos 3 segundos con 15 personas.
2. En el beam, el Monitor pasa solo a la vista de resultados: MEFI, MEFE, el punto en la MIME,
   los cuadrantes, el mapa de calor de la cruzada y las tendencias más votadas.
3. Para el detalle, abrir **Resultados** en la otra ventana. Son **diez** pestañas: MEFI, MEFE,
   MIME, FAC, FODA cruzada, cuadrantes y ranking, tendencias, desacuerdos, lectura de IA y
   **Por participante**. Esta última es la única con datos individuales: **no proyectarla**.

Cómo leerlo en voz alta:

- **MEFI y MEFE** van de 1 a 4. Por encima de 2,5 la posición es favorable en ese eje.
- **La MIME** cruza los dos: ATAQUE (crecer y construir), RESISTA (retener y mantener) o
  DESPOSEER (cosechar o desinvertir).
- **El cuadrante dominante** de la cruzada dice de dónde salen las apuestas: FO ofensivas, FA
  defensivas, DO de mejora, DA de supervivencia. Si dos cuadrantes quedan a menos de un punto
  porcentual, la pantalla dice **"Empate técnico"** en lugar de anunciar uno solo: en ese caso las
  apuestas salen de los dos y conviene decirlo así.
- **Desacuerdos** es la pestaña más útil para la conversación: son los puntos donde el grupo no
  piensa igual. Sirven de entrada al bloque 4. La tabla trae una columna **Factor** con el
  enunciado completo, para poder leerlo en voz alta sin traducir códigos.

Si quiere una lectura escrita: **Generar lectura de IA** en la pestaña correspondiente (tarda
alrededor de un minuto y necesita la llave).

### 11:15 · Bloque 4 y 12:20 · Cierre

Ya no se toca la plataforma, salvo para volver a proyectar una pestaña de Resultados. Antes de
cerrar el día, exportar (sección 5).

---

## 4. Qué hacer si algo se tuerce

### 4.1 Alguien no puede entrar

Por orden, lo más rápido primero:

1. **Que escriba el código en mayúsculas y sin espacios.** El campo lo corrige solo, pero un
   código con "O" o "0" mal leído no entra: el alfabeto no tiene O, 0, I ni 1. Si la tarjeta se
   ve borrosa, dictarle el código.
2. **Que escanee el QR** en vez de escribirlo.
3. **Que compruebe el wifi**: si el celular está en datos móviles no llega a la dirección local.
4. **Regenerar el código**: en `/participantes`, botón **Regenerar** de esa fila. Sale un código
   nuevo que se le dicta. El anterior deja de servir.
5. **Prestarle una tarjeta de repuesto** y luego cambiarle el nombre en la tabla.

Si aparece "Too Many Requests": el límite es por minuto y compartido (Docker ve una sola IP para
toda la sala). `.env.docker` ya trae `ACCESO_INTENTOS_POR_MINUTO=120` y
`ACCESO_VISTAS_POR_MINUTO=240`, así que con quince personas **no debería aparecer**; si aparece,
suele ser porque alguien está tecleando mal el código muchas veces (hay una cubeta aparte de
**20 fallos por minuto**, `ACCESO_FALLOS_POR_MINUTO`, que protege contra adivinar códigos y se
limpia en cuanto alguien entra bien desde esa red). Esperar un minuto. Si aun así se repite, subir
`ACCESO_INTENTOS_POR_MINUTO` en
`.env.docker` (aplica en la siguiente petición).

### 4.2 A alguien se le cierra la sesión o cambia de celular

Que vuelva a `/acceso` y escriba su código otra vez. Todo lo que había guardado sigue ahí: los
aportes, las calificaciones y los cruces están ligados a la persona, no al teléfono.

El botón **Salir** de la cabecera pide confirmación y devuelve a `/acceso` (no a la pantalla de
correo y contraseña), así que un toque accidental se resuelve escribiendo el código otra vez.

El mismo código se puede usar en dos teléfonos a la vez (es lo que permite prestar una tarjeta de
repuesto), pero entonces **los dos escriben sobre las mismas respuestas**. Si presta una tarjeta,
pida a su dueño que cierre sesión antes.

### 4.3 La IA falla o tarda demasiado

Se ve un mensaje claro en rojo con el motivo (llave inválida, tiempo agotado, respuesta no
válida). No se pierde nada: los aportes siguen completos.

Opciones, en orden:

1. **Volver a pulsar Consolidar con IA.** Muchos fallos son transitorios; el sistema ya reintenta
   una vez por su cuenta.
2. **Bajar el número de factores por categoría a 5** y reintentar: menos salida, menos riesgo.
3. **Consolidar a mano**, que es el plan B de verdad y toma unos 10 minutos:
   - En la columna izquierda están todos los aportes por categoría, con su autor.
   - En la columna derecha, **Agregar factor**: escribir el texto y elegir la categoría.
   - Ir leyendo los aportes en voz alta y agrupándolos con la sala: es un ejercicio válido y a
     menudo más participativo que la propuesta automática.
   - También se puede partir del **banco 2024**: botón para traer los factores del ejercicio
     anterior y editarlos.
   - Al terminar, **Publicar y abrir calificación** igual que siempre.

No hay que avisar a los participantes: ellos solo ven "El facilitador está consolidando".

### 4.4 Hay que corregir un factor después de publicar

Se puede, pero cuesta: **Panel → Volver** a consolidación. Los votos se conservan, pero al volver
a consolidación **todas** las marcas de envío (calificación, tendencias y cruces) se limpian,
porque la lista de factores puede cambiar y lo calificado dejaría de valer. Hágalo solo si el
error es grave (un factor duplicado o mal categorizado). Un error de redacción se corrige de viva
voz.

Qué limpia cada retroceso:

| Volver a | Se limpian las marcas de |
|---|---|
| Aporte | aporte, calificación, tendencias y cruces |
| Consolidación | calificación, tendencias y cruces |
| Calificación | calificación y tendencias (**los cruces se conservan**) |
| Cruces | cruces |

Al volver a avanzar, quien tenga la fase completa **recupera su marca de envío automáticamente**:
nadie tiene que reenviar sin motivo ni pierde su voto.

### 4.5 Alguien no alcanzó a enviar

Si **ya tenía todo completo** y solo le faltó pulsar el botón, no se pierde nada: al cerrar la
fase, la plataforma marca como enviado a todo el que la tenga completa, y su voto entra en el
cálculo. Esto vale para aportes, calificación (con sus tendencias) y cruces.

Si la tenía **a medias**, no entra en el cálculo. Si quiere esperarlo, no cierre la fase todavía.
Si ya calculó y luego esa persona envía, vuelva a pulsar **Calcular**: se guarda una versión nueva
y en Resultados hay un selector de versión.

### 4.6 Hay que recalcular

> **Ojo con la lectura de IA al recalcular.** La lectura queda pegada a la versión en la que se
> generó. Si genera la lectura sobre la versión 1 y después vuelve a calcular, la versión 2 nace
> sin lectura y la pestaña aparece vacía. **No se ha perdido nada**: la pantalla avisa con un
> recuadro azul *"la versión 1 sí tiene lectura"* y un botón para verla, o puede generar una nueva
> para la versión actual (otro minuto de espera y otra llamada al modelo). Si el recálculo no
> cambió nada de fondo, lo razonable es abrir la lectura anterior.

**Panel → Calcular** las veces que haga falta, desde la fase de calificación en adelante. Cada
cálculo crea una versión con fecha y con la lista de quiénes entraron. Nada se pierde ni se pisa.

### 4.7 La plataforma va lenta

Comprobar que nadie más esté usando el computador para otra cosa pesada. Si aun así va lenta:

```bash
docker compose -f docker/compose.yaml restart app
```

Tarda unos 20 segundos y no se pierde nada: todo está en la base de datos. Los participantes solo
tienen que reintentar la última acción.

### 4.8 El video beam se queda en blanco o desactualizado

El Monitor se refresca solo cada 5 segundos, pero **se detiene si la pestaña no está visible**.
Si estuvo minimizado, vuelva a ponerlo al frente y espere cinco segundos. Si no, recargue con F5.

Por eso el Monitor debe ir en una **ventana propia** en la segunda pantalla, no como pestaña de la
misma ventana del Panel: si el facilitador cambia de pestaña, el Monitor deja de actualizarse
hasta que vuelva a ella. Lo mismo vale al revés: el Panel muestra el aviso
**"Actualización en pausa: esta pestaña no está visible"** cuando queda de fondo.

---

## 5. Después del retiro

### 5.1 Exportar

Desde **Resultados**, arriba a la derecha:

- **Exportar PDF** (unos 8 segundos): portada, factores, MEFI, MEFE, MIME dibujada, FAC, FODA
  cruzada, cuadrantes, rankings, tendencias y la lectura de IA si se generó.
- **Exportar Excel** (unos 6 segundos): hojas MEFI, MEFE, MIME, FAC INT, FAC EXT, FODA,
  TENDENCIAS y VOTOS, con la misma disposición del archivo de 2024 y **fórmulas reales** en las
  celdas calculadas, para que se pueda auditar.

Los dos archivos se descargan a la carpeta de descargas del computador del consultor con el
nombre de la sesión, la versión y la fecha del cálculo, por ejemplo
`DOFA_retiro-1-dofa-5-de-septiembre_v1_2026-09-05.pdf`. **No se guardan en el servidor**:
guárdelos en la carpeta del proyecto ese mismo día.

En la hoja VOTOS y en todo lo exportado aparecen **iniciales, nunca nombres**. La tabla por
persona solo la ve el facilitador en pantalla.

### 5.2 Qué queda en la plataforma

- La sesión queda en fase **cerrada** con todas las versiones de resultados.
- Los participantes que entren a `/participar` ven la pantalla de cierre con el resumen público
  (MIME y cuadrante dominante), sin la tabla por persona.
- Los códigos de acceso caducan a las 72 horas. Para el domingo no hay que hacer nada: las mismas
  tarjetas siguen sirviendo.

### 5.3 Para el domingo

Si el domingo se usa otra sesión (por ejemplo para apuestas o renuncias), créela desde el Panel:
al ser la de mayor id no cerrada, será la que resuelvan los celulares en `/participar`.

---

## 6. Solución de problemas (consola)

Todos los comandos se ejecutan desde `C:\PROPOSITO\DEV\Estrategia FEDEF\estrategia`.

| Síntoma | Comando |
|---|---|
| ¿Está todo en marcha? | `docker compose -f docker/compose.yaml ps` |
| La app no responde | `docker compose -f docker/compose.yaml restart app` |
| Ver el error real | `docker compose -f docker/compose.yaml logs app --tail=50` |
| Errores de la aplicación | `tail -n 50 storage/logs/laravel.log` |
| ¿Cuál es la sesión activa? | `... exec -T app php artisan tinker --execute="dd(App\Models\Dofa2Session::activaDelProyectoActivo()?->only(['id','nombre','fase']));"` |
| ¿Quién ha enviado qué? | Panel, o `... exec -T db mysql -uroot -proot_local_2026 evolucionamos_estrategia -e "SELECT user_id, aporte_enviado_en, calificacion_enviada_en, cruces_enviados_en FROM dofa2_participantes WHERE sesion_id = <id>;"` |
| Comprobar las URL del QR | ver `docs/ACCESO_RETIRO.md`, sección 2 |
| Ensayo completo | `... exec -T app php docker/ensayo_retiro.php --participantes=3` |

### Si hay que devolver una fase por consola

Solo como último recurso, y nunca con gente calificando:

```bash
docker compose -f docker/compose.yaml exec -T app php artisan tinker --execute="\
  \$s = App\Models\Dofa2Session::find(<id>); \$s->fase = 'consolidacion'; \$s->save();"
```

Es mejor usar el botón **Volver** del Panel, que además limpia los envíos y deja constancia en el
historial de fases.

---

## 7. Lo que conviene tener a mano en papel

1. La dirección de acceso escrita en grande: `http://192.168.1.50:8080/acceso`.
2. La lista de participantes con su código, por si hay que dictarlo.
3. Esta página 0 (el resumen) y la sección 4 (qué hacer si algo se tuerce).
