# LRU_HANDOFF · handoff vivo

> Fichero: `LRU_HANDOFF_VIVO.md` · documento vivo sin sufijo de sesión · inaugurado en s204 (D-s204-D)
> Régimen: se **regenera entero** al cierre de cada sesión. Histórico en el git de este fichero + línea mecánica por sesión en `LRU_BITACORA_SESIONES_VIVO.md` §B. El corpus de handoffs con sufijo (s55→s203·s204) quedó congelado como archivo de consulta.
> Vive **solo en disco** (no se sube al Project · D-s204-F) · Claude lo lee vía MCP al arrancar, después de `LRU_ESTADO.md`.

---

# Handoff s251 → s252

> Cierre de s251 · 2026-08-08 · sesión de **materialización doble + banco en vivo**: Bc2 (panel único + OTA local, 0.251.1) y Bc3 (vigilante-péndulo + gating NET_WDT, 0.251.2) del plano de rescate clásico, con Manuel en banco durante la sesión — flasheo local por AP desde móvil y disparo automático del vigilante a los 5 min, ambos en verde a la primera. Enmiendas E1-E6 al destilado s249 (opción C arbitrada: editar el sufijado). TD-s250-1 resuelta de propina.
> Coherencia al cierre: ESTADO + MAPA L5 + pie ARRANQUE + este fichero concuerdan en **s251**.

## Qué entró

1. **Bc2 · 0.251.1** (git-cl `0274571` + fix `86d5cc6`): `portal1.c/h` — panel embebido espejo del S3 sin Pantalla (Estado/WiFi/OTA, página estática ~6,2 KB en flash), `/wifi` GET con **escaneo asíncrono** (mgos_wifi_scan + respuesta desde el callback — el bloqueante de la S3 no vale en el event loop de mongoose), POST join/connect (join escribe la habitual y salva), `/ota` **multipart streaming** (E3 — mongoose bufferiza el POST crudo entero; `cdefs MG_ENABLE_HTTP_STREAMING_MULTIPART:1` de cinturón), `/confirm`, `/capport`, catch-all 302; **wifi-setup-web-ui retirada** de mos.yml. `ota1`: `ota1_local_begin/write/end/abort` sobre las tripas de siempre, flag `resc` → **rescue_pending** (ventana 5 min broker-O-Confirmar + AP al boot con **sondeo E4**: STA con IP→APSTA, sin IP ~15 s→AP-solo congelando), `ota1_confirm_local`, `ota1_is_pending_verify`, **otalog v2 `via`** (blob v1 descartado — magic bumpeado, arbitrado en sesión).
2. **Bc3 · 0.251.2** (git-cl `63a8b6e`): vigilante-péndulo en `ap1.c` — tick mgos de 5 s (sin los workers de la S3: el event loop principal ya es donde vive mgos_wifi_setup_*), NORMAL→RESCATE→REINTENTO→NORMAL con inhibiciones (user_off = `wifi.sta.enable:false` · AP manual ajeno · Ap.Off externo→REINTENTO · TTL congelado con clientes); perillas `rescueN/T/M/H` en `handler_mqtt_cfg1` (defaults 5/10/3/2 · `rescueN:0` off · sin persistir); **gating NET_WDT** en `net_wdt_cb` (D-s249-D: péndulo fuera de NORMAL o clientes → el contador no corre; también durante flasheo local); campo `vig` aditivo en from/status y en el JSON del panel.
3. **Enmiendas al destilado s249** (disco + Project · §11 nuevo E1-E6): E1 secreto fijado (D-s250-A), E2 congelación STA huérfana (s250c), E3 multipart, E4 sondeo del AP al boot de rescate, E5 mina provision, E6 otalog v2. Cabecera y pie marcan «enmendado en s251».
4. **Choque de banco curado en caliente**: primer build falló — `json_escape` local chocaba con el de frozen (otra firma) → renombrada `p1_json_esc`.

## Banco s251 (placa real · todo en verde)

- **Flancos GPIO27** con `pull_up` ✔ → **TD-s250-1 resuelta** (era el pull-down por defecto, no cableado). Corta=swid2 intacta ✔ · larga 3 s→AP maestra `adminble` ✔.
- **Cadena rescate manual**: AP-solo (STA huérfana congelada) → asociación → panel → escaneo 19 redes → join → APSTA → broker → PWA ✔.
- **Flasheo local por AP desde móvil** ✔: multipart 1.358.160 B → app_1 (`flash v? via=local`), respuesta JSON, reboot, `broker o Confirmar en 300 s`, sondeo E4 → **APSTA** (STA tenía IP), `valid v? via=mqtt`. La `v?` es lo esperado (la página no manda `?ver=`; PWA/curl sí pueden).
- **Vigilante** ✔: placa huérfana (habitual falsa) → a los **5 min** `[vig] RESCATE: AP derivada arriba` → móvil por derivada → portal → red real → broker → PWA. **NET_WDT congelado** durante el rescate (sin reboot a los 600 s) ✔.

## Para arrancar s252

1. Arranque estándar (lecturas MCP + auto-sesión + check 4 puntos).
2. **Opciones** (Manuel arbitra):
   - **A · Cerrar el banco Bc2+Bc3** (el camino a la flota): Bc2 — `valid via=portal` (Confirmar sin broker) · rollback provocado · `to/otalog` en PWA · OTA por broker con manifiesto local · trigger de boot (botón sujeto al reset — con pull-up ya no salta solo) · Ap.On camino APSTA · heap. Bc3 — péndulo completo sin asociarse (perillas rápidas `{"rescueN":1,"rescueT":2,"rescueM":1,"rescueH":1}`) · **rotación multi-red con sta1** (`mos config-set wifi.sta1.*`) · `rescueN:0` → NET_WDT guardián único a los 10 min. **Al pasar: TD-s235-1 muere → OTA de flota clásica desbloqueada (TD-s234-1, urgente por la mina provision).**
   - **B · Preparar la OTA de flota**: publicar 0.251.2 al manifiesto (gen-manifest) + deploy boxdin + escalonado (SOLO tras A).
   - **C · Otro frente**: rebanada S3 de D-s249-F · réplica móvil (TD-s247-2) · banco P1-P6 · TD-s248-1 · pintar `vig` en la PWA (campo ya viaja).
3. **Contexto de banco**: la clásica de mesa quedó en **0.251.2** (app_1 activo tras el flasheo local, hermano app_0 con 0.251.1), conectada a `almeria1` y visible en la PWA; el vigilante puede estar aún cerrando su ciclo (TTL→REINTENTO→NORMAL) si el móvil siguió asociado. El manifiesto local publica 0.251.1 (`rpc1cl-0_251_1.bin` + sha); 0.251.2 sin publicar.
4. **Guardas**: NO desplegar `firmware.json` a boxdin hasta cerrar el banco (TD-s235-1) · las perillas del vigilante no persisten (reboot → 5/10/3/2).

## Pendiente en la máquina de Manuel (no bloqueante)

- Heredados: rebuild + deploy `dist` de pwa6 a boxdin + Unregister SW (el desplegado no lleva la utilidad clave de rescate) · regenerar `index.html` desde `index.md` + redeploy · `git init` de `rpc1`/`blink1` · borrar `C:\esp32\01_factory\_to_delete\` · retained huérfano `s3/.../from/status` · Animate s221 · bitácora §B backfill (s239-s251) + catálogo anillo 2 (s246-s249).

---

build al cierre de s251: **rpc1cl 0.251.2** en la clásica de mesa (Bc2+Bc3 completas · git-cl `63a8b6e` · árbol limpio) · **s3_lcd35 intacto en 0.246.3** · **pwa6**: destilado s249 enmendado + manifiesto local con 0.251.1 + cierre de docs · commits vía MCP. Frente s252 = **cerrar banco Bc2/Bc3 → desbloquear OTA de flota | preparar flota | otro frente — Manuel arbitra**.

Histórico del cierre anterior (s250): utilidad PWA «clave de rescate» + Bc1 en banco (vuelta completa de rescate cerrada por primera vez, secreto D-s250-A fijado).
