diff --git a/docs/26-atuq-envoltorio-gecko.md b/docs/26-atuq-envoltorio-gecko.md index cc2ba4e6..b6274e0c 100644 --- a/docs/26-atuq-envoltorio-gecko.md +++ b/docs/26-atuq-envoltorio-gecko.md @@ -2247,11 +2247,39 @@ el navegador después del primer cuadro. ⇒ **pintar no alcanza; sobrevivir un rato después de pintar, sí.** Y explica A sin anomalía: A también siguió viva minutos después del primer cuadro, porque los volcados por el serial tardan. -⚠ **Lo que de esto NO está medido**, y se dice antes de que la tabla dé a entender otra cosa: si ese -mismo arranque además **selló** el éxito. El volcado del «después» sólo grepeaba el contador, así que -de `cierre-1` hay la limpieza y no el sello — **ahora `last_success` va en los dos volcados y se -guarda con la medición**, que es lo que faltaba para no tener que repetir la corrida. Si el sello se -mueve, es un gancho que sella y limpia a la vez; si no, son dos. +**Y el sello viaja con la limpieza: es UN gancho, no dos.** El «antes» de la corrida siguiente trae +`last_success = 1789498722 = 18:58:42 UTC`, que es la hora de **arranque** de `cierre-1`: el mismo +arranque que limpió el contador escribió el sello. (Ese volcado sólo grepeaba el contador y se +resolvió en el instrumento en vez de dejarlo como nota: `last_success` va ahora en los DOS volcados y +se guarda en la medición, `last_success_antes` / `_despues`.) + +##### ⚠ El reloj es el del LANZAMIENTO, no el de la pintura — y el piso que sale de ahí + +Leyendo el perfil en CADA captura (`--watch-prefs`), la traza de una corrida arrancada a las +19:12:17: + +| captura | `last_success` en disco | `recent_crashes` | +|---|---|---| +| +30 s · +64 s · +100 s | 18:58:42 (el de la corrida anterior) | 0 | +| **+137 s** ██ primera pintura | **19:12:17 (el suyo)** | **ausente** | +| +167…+433 s | 19:12:17 | ausente | + +⇒ el sello llega al disco **entre +100 s y +137 s desde el lanzamiento**. Y S1 —que parecía la +excepción— lo **acota por abajo de forma independiente**: sus propios ficheros dicen que vivió +**100 s** desde el lanzamiento (primer cuadro a +97 s, conversión a PNG tres segundos después) y no +selló. Dos corridas distintas, el mismo intervalo. + +**Si el reloj fuera el de la pintura, S1 tendría que haber sellado** —pintó a +97 s y siguió unos +segundos— y no lo hizo. Con el reloj del lanzamiento encaja todo sin excepciones: S1 pintó pronto y +murió a los 100 s; `cierre-1` pintó a +120 y vivió 480; A pintó a +195 y vivió los minutos de los +volcados; la de arriba selló a los ~+120 pintara cuando pintara. + +⚠ **Y la consecuencia es contraintuitiva, y es la que muerde: cuanto MÁS RÁPIDO pinta, más fácil es +envenenar el perfil**, porque `--until-paint` corta antes. La serie que se rompió a la cuarta se +rompió por eso — no por ser larga, por ser rápida. La regla está en el arnés y no en el runbook: +`PISO_SELLO = 180` (margen sobre la cota alta de 137), `--until-paint` no corta antes de ese piso y +dice por qué sigue esperando. El comentario lleva los dos números medidos al lado, porque **un piso +que se lee como elegido lo baja el próximo que lo vea**. ⚠ **Y el 16 sigue sin explicación, con una contradicción medida encima**: desapareció en una corrida que fue diálogo + `ATUQ-EXIT=0`, y las fases k2/k3 del umbral fueron diálogo + `ATUQ-EXIT=0` también diff --git a/docs/state/primera-pintura.json b/docs/state/primera-pintura.json index f0000831..06354695 100644 --- a/docs/state/primera-pintura.json +++ b/docs/state/primera-pintura.json @@ -1,21 +1,5 @@ { "corridas": [ - { - "medido": "2026-09-14T19:23:09Z", - "imagen": "/mnt/cosecha/takana-cosmic-qemu.img", - "segundos_primera_pintura": 175, - "pantalla": "gpu0", - "pantallas_fotografiadas": 1, - "presupuesto_s": 420, - "ventana_s": 480, - "cadencia_s": 30, - "lanzamiento": "perfil del usuario", - "video": "virtio-gpu solo (-vga none)", - "mem_mb": 2560, - "vcpus": 2, - "acel": "tcg", - "guion": "scripts/cosmic/atuq-en-imagen.py" - }, { "medido": "2026-09-14T19:34:16Z", "imagen": "/mnt/cosecha/takana-cosmic-qemu.img", @@ -518,6 +502,25 @@ "recent_crashes_fijado": 0, "recent_crashes_antes": 4, "recent_crashes_despues": null + }, + { + "medido": "2026-09-15T19:19:34Z", + "imagen": "/mnt/cosecha/takana-cosmic-qemu.img", + "segundos_primera_pintura": 137, + "pantalla": "gpu0", + "pantallas_fotografiadas": 1, + "presupuesto_s": 420, + "ventana_s": 420, + "cadencia_s": 30, + "lanzamiento": "perfil del usuario", + "video": "virtio-gpu solo (-vga none)", + "mem_mb": 2560, + "vcpus": 2, + "acel": "tcg", + "guion": "scripts/cosmic/atuq-en-imagen.py", + "recent_crashes_fijado": 0, + "recent_crashes_antes": null, + "recent_crashes_despues": null } ] } diff --git a/scripts/cosmic/atuq-en-imagen.py b/scripts/cosmic/atuq-en-imagen.py index 2c1ee7ce..d2281439 100755 --- a/scripts/cosmic/atuq-en-imagen.py +++ b/scripts/cosmic/atuq-en-imagen.py @@ -50,6 +50,23 @@ SMP = os.environ.get("SMP", "2") # `screendump` de QMP fotografía UN dispositivo y hay que poder pedir cada uno por su nombre: con dos # salidas, el compositor puede poner la ventana en la que la captura por defecto NO muestra, y eso se # ve exactamente igual que «la ventana no aparece». +# Segundos desde el lanzamiento del navegador antes de los cuales NO se puede matar la VM sin +# envenenar el perfil: el sello del arranque (`last_success` + borrado de `recent_crashes`) aparece +# en disco entre +100 s y +137 s (medido 2026-09-15, `work/cuanto-1.txt`). 180 deja margen sobre la +# cota alta; es un piso del INSTRUMENTO y no una medida del producto. +# ⚠ EL PISO DEL SELLO, Y EL NÚMERO QUE LO JUSTIFICA — si esto se lee como elegido, el próximo que +# lo vea lo baja. Gecko da por bueno un arranque un rato DESPUÉS DEL LANZAMIENTO (no de la primera +# pintura) y ahí escribe `toolkit.startup.last_success` y limpia `recent_crashes`. Medido el +# 2026-09-15, leyendo el perfil en cada captura, y acotado por dos corridas independientes: +# +# el sello NO estaba a los +100 s (la corrida S1 vivió 100 s desde el lanzamiento y no selló) +# el sello YA estaba a los +137 s (la corrida `cuanto-1`: last_success pasó a su propia hora) +# +# ⇒ el hito cae entre +100 y +137 s, y el 180 es margen sobre la cota alta. Y la consecuencia es +# contraintuitiva: **cuanto más rápido pinta, MÁS fácil es envenenar el perfil**, porque +# `--until-paint` corta antes. Una serie sin este piso se rompe sola a la cuarta corrida. +PISO_SELLO = int(os.environ.get("PISO_SELLO", "180")) + DOS_PANTALLAS = os.environ.get("VGA") == "1" VGA_ARGS = (["-vga", "none", "-device", "VGA,id=vga0"] if DOS_PANTALLAS else ["-vga", "none"]) PANTALLAS = ["gpu0", "vga0"] if DOS_PANTALLAS else ["gpu0"] @@ -576,8 +593,21 @@ def main(): if primera is None and px and px > 100_000: primera = t print(f" +{t}s ██ PRIMERA PINTURA — {px} px de la página EN {donde}{vigilancia}", flush=True) - if a.until_paint and not a.watch_prefs: + # ⚠ NO SE CORTA ANTES DEL SELLO, Y ESTO ES MEDIDO (2026-09-15). Gecko + # marca el arranque como bueno —escribe `toolkit.startup.last_success` y + # BORRA `recent_crashes`— y eso llega al disco entre los +100 s y los +137 s + # desde el lanzamiento (`work/cuanto-1.txt`, leyendo el perfil en cada + # captura). El reloj es el del ARRANQUE, no el de la pintura: `cierre-1` + # pintó a +120 s y selló, y la S1 de la serie pintó a +97 s, se cortó con + # `--until-paint` y dejó el contador en 1. Cortar en la pintura mata la VM + # antes del sello, y CADA corrida así suma uno: cuatro y el perfil abre el + # diálogo en vez del navegador. El piso es la diferencia entre medir el + # producto y medir el daño que hace el instrumento. + if a.until_paint and not a.watch_prefs and t >= PISO_SELLO: break + if a.until_paint and t < PISO_SELLO: + print(f" (sigo hasta +{PISO_SELLO}s: antes de eso el arranque no está " + f"sellado y matar la VM envenena el perfil)", flush=True) else: vivos = ser.cmd("for c in /proc/[0-9]*/comm; do cat $c 2>/dev/null; done | grep -c atuq") v = vivos.splitlines()[1].strip() if len(vivos.splitlines()) > 1 else "?"