docs: runbook para relanzar el escritorio KDE en QEMU
Cómo relanzar (run-qemu-desktop.sh), verificar sin ojos humanos (screendump por el monitor QEMU + STATUS del serial), reconstruir la imagen, y la tabla de los 7 fixes que lo hacen andar + los gotchas de operación (serial stale, pkill auto-mata, OVMF VARS stale → TianoCore). Para relanzar/verificar, no rediagnosticar. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Delta semántico
Ninguna definición cambió: el cambio es de texto, documentación o datos.
1 archivos · +89 −0
diff --git a/docs/runbooks/kde-qemu-desktop.md b/docs/runbooks/kde-qemu-desktop.md
new file mode 100644
index 00000000..907f1a4e
--- /dev/null
+++ b/docs/runbooks/kde-qemu-desktop.md
@@ -0,0 +1,89 @@
+# Runbook — relanzar el escritorio KDE Plasma 6 en QEMU
+
+Plasma 6 renderizado 100% por software (QPainter + llvmpipe) sobre `virtio-gpu`, en la cadena
+soberana de hammer (LLVM 18 + mesa desde fuente). Sin GPU real. Cerrado 2026-07-20 tras resolver
+5 bugs estructurales + 2 de cursor (ver [[kde-metal-qemu-desktop]] en memoria y `git log` del frente
+`kde/qemu:`). Este runbook es sólo para **relanzar y verificar**, no para rediagnosticar.
+
+## Relanzar (caso normal — la imagen ya existe)
+
+```sh
+cd ~/hammer
+# la ventana gtk necesita el X del laptop (Xwayland de mirada):
+DISPLAY=:0 GDK_BACKEND=x11 TIMEOUT=1800 DISP=gtk bash scripts/kde/run-qemu-desktop.sh
+```
+
+- Abre una ventana gtk con el virtio-gpu. Bootea UEFI → kernel → arje-zero → Plasma pinta solo (~30-45s).
+- `TIMEOUT=1800` = auto-kill a los 30 min (omitir para dejarlo indefinido; matarlo a mano con el kill de abajo).
+- `DISP=none` = headless (sólo serial, para diagnóstico sin ventana ni interferir con mirada).
+- Toda la config que lo hace funcionar (los 7 fixes) vive en `scripts/kde/plasma-start-qemu.sh`, que se
+ hornea en la imagen. No hace falta setear nada a mano.
+
+## Verificar sin mirar la ventana (oráculo screendump)
+
+La ventana gtk **se congela si mirada reinicia su Xwayland** (QEMU sigue vivo por dentro). Para ver el
+scanout REAL del guest, independiente de la ventana:
+
+```sh
+cd ~/hammer
+printf 'screendump %s/shot.ppm\n' "$PWD" | socat - unix-connect:work/qemu-monitor.sock
+magick shot.ppm /tmp/shot.png # y abrir /tmp/shot.png ; luego: rm shot.ppm
+```
+
+Salud por el serial (no necesita la ventana):
+
+```sh
+grep -a 'STATUS +' work/qemu-desktop-serial.log | tail -3 # kwin=1 plasmashell=1 = vivo
+grep -ac 'código 139' work/qemu-desktop-serial.log # crashes de kwin (÷3: cada línea sale x3)
+```
+
+## Matar / cerrar
+
+```sh
+pkill -KILL -f 'qemu-sys[t]em-x86_64 -machine q35' # el [t] evita auto-matar el propio comando
+```
+
+## Reconstruir la imagen (si se tocó una receta KDE, mesa/llvm, o plasma-start)
+
+```sh
+cd ~/hammer
+bash scripts/kde/qemu-desktop-image.sh # funde base+kde-rootfs, inyecta llvmpipe/musl, hornea plasma-start
+# necesita en store/: *-mesa-llvmpipe, *-llvm18, y los rootfs work/{metal-rootfs,kde-metal-rootfs}
+```
+
+Rebuild ~40s (host-side, hardlinks + artefactos ya sellados; **no** compila nada). Luego relanzar.
+
+## Los 7 fixes que lo hacen andar (por si algo regresa)
+
+Todos en `plasma-start-qemu.sh` salvo `-vga none` (en `run-qemu-desktop.sh`):
+
+| Fix | Sin él |
+|---|---|
+| `GBM_ALWAYS_SOFTWARE=1` | segfault al init (virtio sin 3D tratado como HW → vtable NULL) |
+| `KWIN_DRM_USE_MODIFIERS=0` | negro total (virtio rechaza `AddFB2WithModifiers` con EINVAL) |
+| `KWIN_DRM_DEVICES=<card virtio>` | doble output (efifb+virtio) rompe buffers (redundante con `-vga none`) |
+| `KWIN_COMPOSE=Q` (QPainter) | kwin segfaltea en el rasterizador llvmpipe (`lp_rast_clear_color`) |
+| `-vga none` | **pantalla clavada en TianoCore** (VGA-std por defecto + simpledrm roban el scanout) |
+| `XCURSOR_THEME=breeze_cursors` + `kcminputrc` | `Failed to load cursor theme "default"` (cursor invisible) |
+| `KWIN_FORCE_SW_CURSOR=1` | cursor aparece/desaparece (plano HW de virtio no se presenta) |
+
+## Gotchas de operación
+
+- **Lectura STALE del serial:** no se trunca hasta que el run-script arranca QEMU (tras el rebuild ~40s).
+ Un `until grep 'escritorio arriba'` matchea el run ANTERIOR. Esperá un marcador único del run nuevo:
+ `rm -f work/qemu-monitor.sock` antes de lanzar y `until [ -S work/qemu-monitor.sock ]; do sleep 2; done`.
+- **`pkill -f qemu...` se auto-mata** (el patrón matchea el propio comando) → usar siempre `qemu-sys[t]em`.
+- **"Se queda en TianoCore" tras varios relanzamientos:** el `work/qemu-desktop-OVMF_VARS.fd` persistente
+ acumula boot entries stale → `rm -f work/qemu-desktop-OVMF_VARS.fd` (el run-script lo recrea limpio).
+- **Serial triplicado:** cada línea sale ×3 (`say` tee a console+ttyS0). "139: 3" = 1 crash real.
+- El escritorio queda sólo con wallpaper+panel; sin discos/energía reales (no hay udisksd/upowerd en el
+ rootfs) ni efectos GL pesados (llvmpipe no los soporta). Es esperado, no un fallo.
+
+## Prerrequisitos
+
+- `work/hammer-kde-qemu.img` (la imagen; si falta, reconstruir arriba).
+- OVMF: `/usr/share/edk2/x64/OVMF_CODE.4m.fd` + `OVMF_VARS.4m.fd`.
+- Herramientas host: `qemu-system-x86_64`, `socat`, `magick` (ImageMagick) para el screendump.
+- Para la ventana gtk: sesión gráfica del laptop viva (`DISPLAY=:0`). Headless (`DISP=none`) no la necesita.
+
+Relacionado: memoria [[kde-metal-qemu-desktop]], [[frente-escritorio-kde]], [[arranque-grafo-mirada]].