> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…
atuq: la tasa con perfil sano es +97 y +98 s — y PINTAR NO ES TERMINAR el arranque
Cuatro arranques fríos en serie, el perfil partiendo del 5 que dejó la corrida del umbral:
S1 pin 0 antes 5 después 1 el navegador ✓ +97 s
S2 sin pin antes 1 después 2 el navegador ✓ +98 s
S3 sin pin antes 2 después 3 (matada a los 60 s)
S4 sin pin antes 3 después 4 EL DIÁLOGO ✗ en 420 s
Tres cosas:
· la tasa, por fin con perfil sano: dos corridas independientes y pegadas, +97 y +98 s, contra los
+123/+195/+197/+204 de antes. Con el anfitrión descargado el mismo artefacto pinta en la mitad del
tiempo ⇒ el número es de la máquina y la carga tanto como del producto, y se publica con sus
condiciones;
· el umbral se reprodujo solo y en otra secuencia: S4 arrancó con 3, sumó a 4 y abrió el diálogo —
segunda medición independiente del mismo borde, esta vez identificando la ventana por `min_size`
y no por el título (que está traducido, así que un grep por «Troubleshoot Mode» en una imagen en
castellano no engancha y su ausencia se lee como la conclusión contraria);
· ⚠ y una corrida que PINTA no limpia el contador: S2 pintó y dejó 2. Más todavía,
`toolkit.startup.last_success` vale lo mismo en las CUATRO (1789494795, las 17:53) ⇒ el gancho de
cierre no corrió ni una vez, ni en las que pintaron. Pintar no es terminar de arrancar.
Entonces «quién limpia el contador» SIGUE SIN MEDIR, y el propio documento decía que esta serie lo
cerraría: no lo cierra, y queda escrito así. Hace falta una corrida que deje al navegador terminar
de arrancar y salir limpio.
Lo más caro es para el instrumento: con `--until-paint` cada corrida suma uno, pinte o no, así que
una serie se rompe sola a la cuarta — que es lo que pasó ayer sin que nadie lo viera. El arnés ahora
AVISA cuando el contador está en 3 («esta corrida va a abrir el diálogo, no el navegador») y la
receta para una serie queda escrita: pinnear `--crashes 0` en cada corrida, que resetea la base
(S1 lo muestra partiendo de 5).
También cae una candidata mía, con un cero que viene con control (medido por la otra sesión): el pref
no tiene default en este build, así que fijarlo en 0 SÍ se persiste y el «ausente» no era el pin.
diff --git a/docs/26-atuq-envoltorio-gecko.md b/docs/26-atuq-envoltorio-gecko.md
index 4a5b7d05..4e593af0 100644
--- a/docs/26-atuq-envoltorio-gecko.md
+++ b/docs/26-atuq-envoltorio-gecko.md
@@ -2185,13 +2185,65 @@ limpieza. Entonces la desaparición del 16 entre las 17:12 y las 17:20 **no tien
medida**, y la atribución «Gecko lo borró al mostrarlo» se retira. Dos candidatas, las dos sin
comprobar: que el `prefs.js` se perdiera en el kill (cuando se lo leyó con `debugfs` figuraba de 0
bytes, y ese volcado no es fiable — es la lección del párrafo de `debugfs`), o que un arranque que
-TERMINA sí lo limpie, que es lo que hace upstream pero que acá no se puede atribuir: **todas las
-corridas que pintaron llevaban `--crashes 0` pinneado, o sea el valor por defecto, y un pref igual al
-default no se persiste**. El «ausente» de esas corridas puede ser eso.
-
-La medición que lo cierra, y que sale gratis de la serie sana: dejar el contador en 1 o 2 **sin
-pinnearlo**, correr hasta que pinte y leerlo después. Si pasa a ausente, limpia el arranque que
-termina; si sigue en 2, no limpia nada y lo del 16 fue el fichero.
+TERMINA sí lo limpie, que es lo que hace upstream.
+
+⚠ Hubo una tercera candidata, mía, y **está descartada con un cero que viene con control**: «el
+`--crashes 0` fija el valor por DEFECTO y un pref igual al default no se persiste, así que el
+“ausente” prueba el pin y no una limpieza». No: `toolkit.startup.recent_crashes` **no tiene default
+en este build**, y por eso un 0 puesto a mano sí se escribe. Tres lugares del artefacto sellado lo
+dicen y el cuarto es el que convierte a los otros en evidencia:
+
+ greprefs.js (omni de toolkit) → 0 líneas con «toolkit.startup»
+ browser/omni.ja defaults/preferences/*.js → 0 líneas con «recent_crashes»
+ libxul.so, strings «sMirror_toolkit_startup*» → 0 ⇒ no es pref de StaticPrefList
+ libxul.so, strings «sMirror_browser_crashReporter*» → 2 ⇐ EL CONTROL, que TENÍA que dar positivo
+
+Los dos primeros ceros no valen solos, y el primero es el ejemplo de por qué: `greprefs.js` da cero
+porque ahí no vive **ningún** `toolkit.startup.*`, no porque el pref no exista. Un `grep` que
+devuelve 0 puede ser una ausencia o un sitio equivocado, y las dos se ven igual; lo único que las
+separa es un patrón hermano que tenga que dar positivo en el mismo fichero. (Y una distinción que se
+parece a otra y no lo es: el binario lee ese pref con un **0 de respaldo en el sitio del `GetInt`**,
+que no es un default registrado y no evita que el valor se escriba.)
+
+##### La serie sana — y lo que refuta: **pintar no es TERMINAR**
+
+Cuatro arranques FRÍOS en serie, el perfil partiendo del 5 que dejó la corrida del umbral, con
+`--until-paint` salvo la tercera (matada a los 60 s a propósito):
+
+| corrida | pin | antes | después | ventana | primera pintura |
+|---|---|---|---|---|---|
+| **S1** 18:27 | `--crashes 0` | 5 | 1 | el navegador | ✓ **+97 s** |
+| **S2** 18:33 | — | 1 | 2 | el navegador | ✓ **+98 s** |
+| **S3** 18:38 | — | 2 | 3 | (matada a los 60 s) | — |
+| **S4** 18:50 | — | 3 | 4 | **el diálogo** (`min_size(117, 37)`, título Troubleshoot) | ✗ en 420 s |
+
+Tres cosas, y la tercera no la esperaba nadie:
+
+1. **el número de la tasa, por fin con perfil sano: +97 s y +98 s**, dos corridas independientes y
+ pegadas —contra los +123, +195, +197 y +204 de antes—. Con el anfitrión más descargado el mismo
+ artefacto pinta en la mitad de tiempo, o sea que el número de esta serie es de **la máquina y la
+ carga tanto como del producto**: se publica con sus condiciones o no se publica;
+2. **el umbral se reprodujo solo, en otra secuencia y sin buscarlo**: S4 arrancó con 3 guardado,
+ sumó a 4 y abrió el diálogo. Es la segunda medición independiente del mismo borde, y esta vez la
+ ventana se identificó por `min_size` y no por el título;
+3. ⚠⚠ **y una corrida que PINTA no limpia el contador.** S2 pintó y dejó el 2; S1 pintó y dejó 1.
+ Más todavía: `toolkit.startup.last_success` vale **1789494795 en las cuatro corridas** —la marca
+ del arranque de las 17:53— o sea que **el gancho de cierre no llegó a correr ni una sola vez**,
+ incluso en las que pintaron. Pintar no es terminar el arranque.
+
+⇒ **la pregunta de quién limpia el contador sigue SIN medir**, y el §6.10.terdecies decía que esta
+serie la iba a cerrar. No la cierra: ninguna corrida nuestra llegó nunca al gancho, así que las dos
+candidatas del 16 siguen vivas y hace falta una corrida que deje al navegador **terminar de
+arrancar** (y salir limpio) para preguntárselo.
+
+**Y la consecuencia para el instrumento es lo más caro de la serie:** con `--until-paint`, **cada
+corrida suma uno**, pinte o no pinte. Cuatro corridas envenenan cualquier perfil, así que una serie
+larga se rompe sola a la cuarta — que es exactamente lo que había pasado ayer sin que nadie lo viera.
+Dos formas de convivir con eso, las dos escritas en el arnés: **pinnear `--crashes 0` en cada corrida
+de una serie** (S1 muestra que el pin funciona incluso partiendo de 5: resetea la base y el
+incremento del arranque la deja en 1, lejos del borde), o dejar que el navegador llegue al gancho de
+cierre, que cuesta más tiempo de VM del que cuesta medir la pintura. Y mientras tanto el arnés
+**avisa** cuando el contador está en 3: la corrida siguiente va a abrir el diálogo y no el navegador.
**Un discriminador que salió gratis y sirve para siempre:** el `ATUQ-EXIT` de una fase que matamos es
**137** (128+9) y el de una corrida que se fue sola por el diálogo es **0**. El código de salida
@@ -2266,7 +2318,13 @@ con el árbol de fuentes, pero con la mitigación ya puesta. Dos consecuencias:
**De ahí sale el discriminador barato entre las dos ventanas**, y vale para cualquier corrida
futura: el navegador pide `set_min_size(638, 120)` —después (690, 172)— y
`set_max_size(16332, 16332)`; el diálogo pide `set_min_size(117, 37)` y `set_max_size(348, 16332)`.
- Con mirar el `min_size` se sabe cuál abrió, sin leer el título.
+ Con mirar el `min_size` se sabe cuál abrió, **y hay que mirar ése y no el título**: `set_title`
+ también las separa pero está TRADUCIDO, así que en una imagen en castellano el `grep` por
+ «Troubleshoot Mode» deja de enganchar y su ausencia se lee como «no salió el diálogo» — la
+ conclusión contraria a la verdadera. El `min_size` es la misma pregunta hecha a un número. (Y el
+ `348` del diálogo sale de su propio Fluent: `troubleshoot-mode-window .style = max-width: 400px`.
+ Una cadena de localización decidiendo geometría, que es por qué el 117×70 no se parecía al tamaño
+ de nada.)
Dos cosas más de esa corrida: el `xulstore` quedó igual ⇒ **una corrida sana no ensucia lo que el
perfil recuerda**; y `recent_crashes_despues` salió **ausente**, que en su momento se leyó como
diff --git a/docs/state/primera-pintura.json b/docs/state/primera-pintura.json
index bd299302..6531e83b 100644
--- a/docs/state/primera-pintura.json
+++ b/docs/state/primera-pintura.json
@@ -1,67 +1,5 @@
{
"corridas": [
- {
- "medido": "2026-09-14T17:51:50Z",
- "imagen": "/mnt/cosecha/takana-cosmic-qemu.img",
- "segundos_primera_pintura": null,
- "presupuesto_s": 420,
- "ventana_s": 480,
- "cadencia_s": 30,
- "lanzamiento": "perfil del usuario",
- "video": "vga+virtio-gpu (dos DRM)",
- "mem_mb": 2560,
- "vcpus": 2,
- "acel": "tcg",
- "guion": "scripts/cosmic/atuq-en-imagen.py",
- "pantallas_fotografiadas": 1
- },
- {
- "medido": "2026-09-14T18:10:43Z",
- "imagen": "/mnt/cosecha/takana-cosmic-qemu.img",
- "segundos_primera_pintura": null,
- "presupuesto_s": 420,
- "ventana_s": 480,
- "cadencia_s": 30,
- "lanzamiento": "perfil del usuario",
- "video": "vga+virtio-gpu (dos DRM)",
- "mem_mb": 2560,
- "vcpus": 2,
- "acel": "tcg",
- "guion": "scripts/cosmic/atuq-en-imagen.py",
- "pantallas_fotografiadas": 1
- },
- {
- "medido": "2026-09-14T18:25:53Z",
- "imagen": "/mnt/cosecha/takana-cosmic-qemu.img",
- "segundos_primera_pintura": null,
- "presupuesto_s": 420,
- "ventana_s": 480,
- "cadencia_s": 30,
- "lanzamiento": "perfil del usuario",
- "video": "vga+virtio-gpu (dos DRM)",
- "mem_mb": 2560,
- "vcpus": 2,
- "acel": "tcg",
- "guion": "scripts/cosmic/atuq-en-imagen.py",
- "pantallas_fotografiadas": 1
- },
- {
- "medido": "2026-09-14T18:54:22Z",
- "imagen": "/mnt/cosecha/takana-cosmic-qemu.img",
- "segundos_primera_pintura": 312,
- "presupuesto_s": 420,
- "ventana_s": 480,
- "cadencia_s": 40,
- "lanzamiento": "perfil del usuario",
- "video": "vga+virtio-gpu (dos DRM)",
- "mem_mb": 2560,
- "vcpus": 2,
- "acel": "tcg",
- "guion": "scripts/cosmic/atuq-en-imagen.py",
- "pantallas_fotografiadas": 2,
- "pantalla": "vga0",
- "nota": "la ventana apareció en vga0 mientras gpu0 seguía mostrando el escritorio sin navegador"
- },
{
"medido": "2026-09-14T19:14:09Z",
"imagen": "/mnt/cosecha/takana-cosmic-qemu.img",
@@ -501,6 +439,82 @@
"recent_crashes_fijado": null,
"recent_crashes_antes": 4,
"recent_crashes_despues": 5
+ },
+ {
+ "medido": "2026-09-15T18:27:01Z",
+ "imagen": "/mnt/cosecha/takana-cosmic-qemu.img",
+ "segundos_primera_pintura": 97,
+ "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": 5,
+ "recent_crashes_despues": 1
+ },
+ {
+ "medido": "2026-09-15T18:33:05Z",
+ "imagen": "/mnt/cosecha/takana-cosmic-qemu.img",
+ "segundos_primera_pintura": 98,
+ "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": null,
+ "recent_crashes_antes": 1,
+ "recent_crashes_despues": 2
+ },
+ {
+ "medido": "2026-09-15T18:38:38Z",
+ "imagen": "/mnt/cosecha/takana-cosmic-qemu.img",
+ "segundos_primera_pintura": null,
+ "pantalla": null,
+ "pantallas_fotografiadas": 1,
+ "presupuesto_s": 420,
+ "ventana_s": 60,
+ "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": null,
+ "recent_crashes_antes": 2,
+ "recent_crashes_despues": 3
+ },
+ {
+ "medido": "2026-09-15T18:50:31Z",
+ "imagen": "/mnt/cosecha/takana-cosmic-qemu.img",
+ "segundos_primera_pintura": null,
+ "pantalla": null,
+ "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": null,
+ "recent_crashes_antes": 3,
+ "recent_crashes_despues": 4
}
]
}
diff --git a/scripts/cosmic/atuq-en-imagen.py b/scripts/cosmic/atuq-en-imagen.py
index b176d9cd..df58d881 100755
--- a/scripts/cosmic/atuq-en-imagen.py
+++ b/scripts/cosmic/atuq-en-imagen.py
@@ -416,6 +416,15 @@ def main():
"last_success)|browser.sessionstore.max_resumed' %s/prefs.js" % d, 60)
print(volcado.strip())
estado["recent_crashes_antes"] = leer_contador_de_caidas(volcado)
+ # ⚠ EL AVISO QUE FALTABA. Medido el 2026-09-15: el arranque que encuentra el
+ # anterior sin terminar SUMA UNO y compara DESPUÉS, así que con 3 guardado esta
+ # corrida abre el diálogo de Modo de resolución de problemas y no el navegador —
+ # y como el arnés mata la VM antes del gancho de cierre, CADA corrida suma.
+ # Una serie se rompe sola a la cuarta; por eso se dice acá y no en el post-mortem.
+ previo = estado["recent_crashes_antes"]
+ if previo is not None and previo >= 3 and a.crashes is None:
+ print(" ⚠⚠ contador en %d: ESTA corrida va a abrir el DIÁLOGO, no el "
+ "navegador. Para medir la pintura, pasá --crashes 0" % previo)
else:
d = "/tmp/perfil"
ser.cmd("rm -rf /tmp/perfil && mkdir -p /tmp/perfil")