> 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: el umbral son 4 — y mostrar el diálogo NO limpia el contador, como este documento decía
Medido en los dos lados, partiendo del perfil en 2 y con tres fases más en un arranque: el que
encuentra 2 guardado PINTA (y queda en 3); el que encuentra 3 lo sube a 4, compara 4 > 3 y abre el
diálogo (y queda en 4); el siguiente queda en 5 y vuelve a abrir el diálogo. O sea que la
comparación va DESPUÉS del incremento del propio arranque: contando desde la última corrida que
terminó bien, son cuatro arranques interrumpidos seguidos y el quinto lanzamiento ya no abre el
navegador.
`toolkit.startup.last_success` vale lo mismo en las tres fases (1789494795, el arranque de la última
corrida sana): el contador sube mientras esa marca no se mueve. Con las dos cifras juntas, un
contador que no cambió deja de ser ambiguo entre «no subió» y «subió y se limpió».
⚠ Y eso refuta una atribución que yo había escrito ayer y que estaba en tres sitios: mostrar el
diálogo NO limpia el contador (k2 lo dejó en 4, k3 en 5). Queda retirada del SDD y del comentario
del arnés. La desaparición del 16 entre las 17:12 y las 17:20 pasa a ser un hecho SIN explicación
medida, con dos candidatas escritas y ninguna dada por buena — y una de ellas es mía y fea: todas
las corridas que pintaron llevaban `--crashes 0` pinneado, que es el valor por DEFECTO, y un pref
igual al default no se persiste. El «ausente» puede ser eso y no una limpieza. Queda dicho cómo se
cierra: dejar el contador en 2 SIN pinnearlo, correr hasta que pinte y leerlo después.
Un discriminador que salió gratis: `ATUQ-EXIT=137` es «la matamos» (128+9) y `ATUQ-EXIT=0` es «se
fue sola» por el diálogo. El código de salida contesta lo que una captura no podía.
Medido por la otra sesión del frente (work/umbral-1.txt), con la predicción escrita antes de mirar.
diff --git a/docs/26-atuq-envoltorio-gecko.md b/docs/26-atuq-envoltorio-gecko.md
index 8f155c6e..4a5b7d05 100644
--- a/docs/26-atuq-envoltorio-gecko.md
+++ b/docs/26-atuq-envoltorio-gecko.md
@@ -2127,9 +2127,9 @@ sola cosa: `toolkit.startup.recent_crashes`, fijado en el `user.js` del perfil (
| **B** 17:44 | fijado en **16** | ✗ nada en 300 s · `set_title("Open atuq in Troubleshoot Mode?")` · `ATUQ-EXIT=0` |
⚠ **Y una honestidad que cambia la fuerza del argumento:** en la corrida A el `--crashes 0` fue un
-**no-op** —el contador ya no estaba en `prefs.js`, porque Gecko lo BORRA después de mostrar el
-diálogo—, así que A sola no prueba nada: prueba tanto «lo arregló el 0» como «el perfil ya estaba
-limpio». **La que prueba la causa es B**, que lo pone de vuelta y rompe de vuelta. Una sola dirección
+**no-op** —el contador ya no estaba en `prefs.js`, y **por qué no estaba sigue sin explicación
+medida** (ver más abajo: mostrar el diálogo NO lo limpia)—, así que A sola no prueba nada: prueba
+tanto «lo arregló el 0» como «el perfil ya estaba limpio». **La que prueba la causa es B**, que lo pone de vuelta y rompe de vuelta. Una sola dirección
habría sido una correlación con suerte.
##### ⚠⚠ La serie de `primera-pintura.json` está CONTAMINADA, y por el propio andamiaje
@@ -2160,20 +2160,51 @@ distinguía:
incrementa» de «sólo después de uno interrumpido», que es la diferencia entre culpar al kill y
culpar al arranque que no llegó a terminar.
-⚠ **Lo que sigue sin medir es el BORDE**, y se dice para que no se lea como medido: el diálogo aparece
-cuando el contador vale más que `max_resumed_crashes`, pero no está comprobado si la comparación se
-hace **antes o después** del incremento de ese mismo arranque — o sea si el diálogo sale en el
-arranque que EMPIEZA valiendo 3 (compara después de sumar) o en el que empieza valiendo 4 (compara lo
-guardado). Las dos dan «cuatro arranques interrumpidos seguidos» como respuesta práctica, y
-distinguirlas importa sólo para poder decir el número sin inventarlo. Se mide cruzando el umbral en
-vivo, que es lo que está en curso.
+##### El borde, medido en los dos lados: **3 guardado no alcanza, 4 sí**
+
+Partiendo del perfil en 2, tres fases más en un arranque (las dos primeras matadas antes de pintar):
+
+| fase | antes | después | qué ventana abrió | `ATUQ-EXIT` |
+|---|---|---|---|---|
+| k1 | 2 | 3 | **el navegador** — `set_title("atuq")`, `set_min_size(638, 120)` | 137 (la matamos) |
+| k2 | 3 | **4** | **el diálogo** — `set_title("Open atuq in Troubleshoot Mode?")`, `min_size(117, 37)` | 0 |
+| k3 | 4 | **5** | el diálogo otra vez | 0 |
+
+⇒ **la comparación es DESPUÉS de sumar**: el arranque que encuentra 3 guardado lo sube a 4, compara
+4 > 3 y abre el diálogo; el que encuentra 2 pinta. Contando desde la última corrida que terminó bien,
+eso son **cuatro arranques interrumpidos seguidos, y el quinto lanzamiento ya no abre el navegador**.
+
+Y la otra mitad del cálculo lo confirma sin ambigüedad: `toolkit.startup.last_success` vale
+**1789494795 en las tres fases** —congelado en el arranque de la última corrida sana—. El contador
+sube mientras `last_success` no se mueve; con las dos cifras juntas, un contador que no cambió deja
+de ser ambiguo entre «no subió» y «subió y se limpió».
+
+⚠⚠ **Y eso REFUTA algo que este documento afirmaba dos secciones más arriba: mostrar el diálogo NO
+limpia el contador.** k2 lo dejó en 4 y k3 en 5 — dos corridas consecutivas con diálogo y ninguna
+limpieza. Entonces la desaparición del 16 entre las 17:12 y las 17:20 **no tiene explicación
+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.
+
+**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
+distingue «la mataron» de «se fue sola» sin mirar nada más — que es justo lo que el §6.10.terdecies
+no podía distinguir de una captura.
Qué se hizo con eso, en vez de borrar el fichero:
- **el contador viaja con cada medición**: `recent_crashes_antes`, `recent_crashes_despues` y
`recent_crashes_fijado` son campos de cada corrida de `docs/state/primera-pintura.json`. Antes y
- después porque Gecko lo limpia al mostrar el diálogo: sin el «después», la corrida siguiente parece
- arreglarse sola y la anterior parece intermitente;
+ después porque el número cambia DENTRO de la corrida —lo escribe el arranque, no el kill— y porque
+ sin el «después» no se puede encadenar una corrida con la siguiente, que es lo que convirtió esto
+ en una serie legible;
- **el vigía las APARTA y lo dice**: `scripts/vigia-imagen.py` saca de la tasa las corridas con el
contador > 3 y, para las 21 anteriores al campo, informa que **no se pueden clasificar** en vez de
contarlas como buenas. Un denominador que se marca, no que se borra.
@@ -2237,10 +2268,11 @@ con el árbol de fuentes, pero con la mitigación ya puesta. Dos consecuencias:
`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.
- Dos cosas más de esa corrida: `recent_crashes_despues` salió **ausente** —la corrida que pinta
- LIMPIA el contador, que es el mecanismo visto desde el otro lado y explica el «se arregla sola»
- sin ninguna hipótesis— y el `xulstore` quedó igual: **una corrida sana no ensucia lo que el perfil
- recuerda**.
+ 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
+ «la corrida que pinta limpia el contador» y **hay que no leerlo así** — esa corrida llevaba
+ `--crashes 0` pinneado, o sea el valor por DEFECTO, y un pref igual al default no se persiste. El
+ «ausente» puede ser eso y no una limpieza.
### 6.11 Y ahora la pregunta que faltaba: ¿REPRODUCE? (2026-09-07)
diff --git a/docs/state/primera-pintura.json b/docs/state/primera-pintura.json
index 7f53c290..bd299302 100644
--- a/docs/state/primera-pintura.json
+++ b/docs/state/primera-pintura.json
@@ -1,112 +1,5 @@
{
"corridas": [
- {
- "medido": "2026-09-14T16:17:13Z",
- "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-14T16:26:43Z",
- "imagen": "/mnt/cosecha/takana-cosmic-qemu.img",
- "segundos_primera_pintura": 184,
- "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,
- "pantalla": "desconocida (una sola captura)"
- },
- {
- "medido": "2026-09-14T16:39:48Z",
- "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-14T16:48:45Z",
- "imagen": "/mnt/cosecha/takana-cosmic-qemu.img",
- "segundos_primera_pintura": 199,
- "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,
- "pantalla": "desconocida (una sola captura)"
- },
- {
- "medido": "2026-09-14T17:03:19Z",
- "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-14T17:18:52Z",
- "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-14T17:34:16Z",
- "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-14T17:51:50Z",
"imagen": "/mnt/cosecha/takana-cosmic-qemu.img",
@@ -475,6 +368,139 @@
"recent_crashes_fijado": 16,
"recent_crashes_antes": null,
"recent_crashes_despues": 16
+ },
+ {
+ "medido": "2026-09-15T17:56:31Z",
+ "imagen": "/mnt/cosecha/takana-cosmic-qemu.img",
+ "segundos_primera_pintura": 195,
+ "pantalla": "gpu0",
+ "pantallas_fotografiadas": 1,
+ "presupuesto_s": 420,
+ "ventana_s": 300,
+ "cadencia_s": 60,
+ "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": 16,
+ "recent_crashes_despues": null
+ },
+ {
+ "medido": "2026-09-15T18:04:44Z",
+ "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": null,
+ "recent_crashes_despues": null
+ },
+ {
+ "medido": "2026-09-15T18:06:05Z",
+ "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": null,
+ "recent_crashes_despues": 1
+ },
+ {
+ "medido": "2026-09-15T18:07:24Z",
+ "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": 1,
+ "recent_crashes_despues": 2
+ },
+ {
+ "medido": "2026-09-15T18:13:42Z",
+ "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:15:02Z",
+ "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": 3,
+ "recent_crashes_despues": 4
+ },
+ {
+ "medido": "2026-09-15T18:16:18Z",
+ "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": 4,
+ "recent_crashes_despues": 5
}
]
}
diff --git a/scripts/cosmic/atuq-en-imagen.py b/scripts/cosmic/atuq-en-imagen.py
index 07c46191..b176d9cd 100755
--- a/scripts/cosmic/atuq-en-imagen.py
+++ b/scripts/cosmic/atuq-en-imagen.py
@@ -255,13 +255,21 @@ def main():
"que es la única forma de subirle el nivel de log sin recompilar")
ap.add_argument("--crashes", type=int, metavar="N",
help="fija `toolkit.startup.recent_crashes` del perfil del usuario antes de "
- "lanzar: 0 lo limpia, >3 reproduce el diálogo de Modo de resolución de "
- "problemas. Sólo tiene efecto con --as-user")
+ "lanzar: 0 lo limpia, 4 o más reproduce el diálogo de Modo de resolución "
+ "de problemas (medido: con 3 guardado todavía pinta, porque el arranque "
+ "suma ANTES de comparar). Sólo tiene efecto con --as-user. ⚠ 0 es el valor "
+ "por DEFECTO y un pref igual al default no se persiste: si lo que querés "
+ "medir es quién limpia el contador, NO lo pinnees")
ap.add_argument("--xulstore", metavar="ANCHOxALTO",
help="agrega una SEGUNDA fase en el mismo arranque con `xulstore.json` sembrado "
"(p. ej. 1152x720): la ventana arranca con un tamaño YA PERSISTIDO. Es el "
"control del 117x70 — si con semilla sale grande, lo que falla es que nadie "
"le da tamaño en el primer arranque")
+ ap.add_argument("--repeat", type=int, metavar="N",
+ help="corre N fases IDÉNTICAS en el mismo arranque. Con `--wait` corto (60 s, o "
+ "sea antes de que pinte) mide el contador de caídas: cada fase lee "
+ "`recent_crashes` ANTES de lanzar, así que la serie 0,1,2… dice cuánto suma "
+ "un arranque interrumpido — y si no sube, el envenenamiento vino de otro lado")
ap.add_argument("--out", default=os.path.join(RAIZ, "work/atuq-imagen"))
a = ap.parse_args()
@@ -400,8 +408,12 @@ def main():
# que CADA corrida fallida puede sumar uno: el instrumento degrada el sujeto y
# la tasa medida deja de ser del producto. Sin este número impreso, una corrida
# no se puede interpretar.
- volcado = ser.cmd("grep -E 'toolkit.startup.(recent_crashes|max_resumed)|"
- "browser.sessionstore.max_resumed' %s/prefs.js" % d, 60)
+ # ⚠ `last_success` VA EN EL MISMO VOLCADO. Es la otra mitad del cálculo: sin
+ # él, un `recent_crashes` que no se movió es ambiguo entre «no subió» y «subió y
+ # lo limpió el gancho de cierre», que son conclusiones opuestas sobre la misma
+ # cifra.
+ volcado = ser.cmd("grep -E 'toolkit.startup.(recent_crashes|max_resumed|"
+ "last_success)|browser.sessionstore.max_resumed' %s/prefs.js" % d, 60)
print(volcado.strip())
estado["recent_crashes_antes"] = leer_contador_de_caidas(volcado)
else:
@@ -455,8 +467,12 @@ def main():
línea de orden del shell del serial y ahí se mata la sesión entera (medido en el hub,
sale 144 y lo que sigue no corre).
"""
+ # ⚠ `-9` A PROPÓSITO. Un `kill` a secas le da a Gecko su apagado ordenado, y un
+ # apagado ordenado es EXACTAMENTE la variable bajo prueba: lo que hace este arnés al
+ # terminar es matar la VM entera, que no avisa. Con `-KILL` la fase siguiente
+ # encuentra el mismo estado que encontraría tras una corrida matada de verdad.
ser.cmd("for p in /proc/[0-9]*; do grep -q atuq $p/comm 2>/dev/null && "
- "kill ${p#/proc/}; done; true", 60)
+ "kill -9 ${p#/proc/}; done; true", 60)
time.sleep(8)
salida = ser.cmd("for c in /proc/[0-9]*/comm; do cat $c 2>/dev/null; done | grep -c atuq")
# El serial hace ECO de la orden, así que la respuesta es la ÚLTIMA línea que sea un
@@ -477,10 +493,14 @@ def main():
fases = [("base", None)]
if a.xulstore:
fases.append(("semilla-%s" % a.xulstore, a.xulstore))
+ if a.repeat:
+ # N fases iguales: lo que varía entre ellas no es la configuración sino el ESTADO que
+ # deja la anterior en el perfil, que es justo lo que se quiere medir.
+ fases = [("k%d" % i, None) for i in range(1, a.repeat + 1)]
for fase, semilla in fases:
print("\n===== FASE «%s» =====" % fase, flush=True)
- if semilla:
+ if fase != fases[0][0]:
matar_al_navegador()
perfil_d = perfil_de_la_fase(semilla)
log_atuq = "/var/log/cosmic/atuq-%s.log" % fase
@@ -545,10 +565,11 @@ def main():
rc[0] = 1
if perfil_d and a.as_user:
- # ⚠ EL ESTADO FINAL ES PARTE DE LA PRUEBA. Gecko BORRA el contador después de
- # mostrar el diálogo, así que un perfil envenenado se ve limpio en cuanto se
- # lo mira DESPUÉS: sin este segundo volcado, la corrida siguiente parece
- # «arreglada sola» y la anterior parece intermitente. Se lee con el navegador
+ # ⚠ EL ESTADO FINAL ES PARTE DE LA PRUEBA: el número cambia DENTRO de la
+ # corrida —lo escribe el ARRANQUE al encontrar el anterior sin terminar, no el
+ # kill— así que sin el «después» no se puede encadenar una corrida con la
+ # siguiente, que es lo que convierte esto en una serie legible (medido:
+ # 2 → 3 → 4 en tres fases de un mismo arranque). Se lee con el navegador
# todavía vivo, o sea que refleja el último volcado de prefs de Gecko.
volcado = ser.cmd("grep -E 'toolkit.startup.recent_crashes' %s/prefs.js || "
"echo '(el pref no está: arranque sin caídas pendientes)'"