645 líneas. Los ADR entran porque en este repo SON documentos vivos, no registros inmutables: el 0013 tiene 5 commits, el 0009 dos. Eso se comprobó antes de decidir, no se asumió por convención general. EXCLUIDOS por ser REGISTRO o generado: docs/evidencia/ (6), el HANDOFF de la noche de KDE (1) y docs/state/ (24, se regenera solo). Reescribir un comando dentro de una evidencia la falsifica. Y el ADR 0016 se excluye de todo barrido, con un aviso adentro para el próximo que barra: habla SOBRE el renombre, así que necesita seguir diciendo 'hammer'. El barrido se lo llevó puesto y lo dejó titulado 'Renombre del sistema: takana → takana'; revertido. Congelados, verificados uno por uno con controles: /opt/hammer, /var/lib/hammer, /usr/bin/hammer, /mnt/vvv/hammer, la URL de gitea, hammer-farm.service, hammer-live-install.sh, BRIEFING-hammer.md, hammerd, hammer-recover y HAMMER_LIVE.
184 lines
9.7 KiB
Markdown
184 lines
9.7 KiB
Markdown
# 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 takana (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]].
|
||
|
||
## 2026-09-03 — verificar el escritorio SIN humano delante (gioser, TCG, sin socat)
|
||
|
||
Este runbook asumía el laptop: `DISP=gtk` para ver la ventana y `socat` para el monitor. En **gioser
|
||
no hay ninguna de las dos cosas** —es un vServer sin `/dev/kvm` y sin `socat`— y aun así se puede
|
||
verificar todo, incluido **hacer clic**. Las tres piezas:
|
||
|
||
```sh
|
||
# 1. la imagen y el rootfs viven en el VOLUMEN (/mnt/vvv está al 98%), y el STAGE también:
|
||
# sin STAGE= el install-image-efi hardlinkea de /mnt/cosecha a work/ y muere con EXDEV.
|
||
E=/mnt/cosecha/escritorios
|
||
BASE=$E/base-rootfs KDE=$E/kde-rootfs MERGED=$E/kde-qemu-rootfs \
|
||
IMG=$E/hammer-kde-qemu.img STAGE=$E/.stage-kde bash scripts/kde/qemu-desktop-image.sh
|
||
|
||
# 2. arrancar headless (cae solo a TCG: gioser no tiene KVM; Plasma pinta en ~2 min)
|
||
IMG=$E/hammer-kde-qemu.img SERIAL=work/kde-qemu-serial.log MON=work/kde-monitor.sock \
|
||
VARS=work/kde-OVMF_VARS.fd TIMEOUT=1200 DISP=none bash scripts/kde/run-qemu-desktop.sh &
|
||
```
|
||
|
||
3. el monitor de QEMU **por socket unix desde python**, que reemplaza a `socat`:
|
||
|
||
```python
|
||
import socket, time
|
||
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM); s.connect('work/kde-monitor.sock')
|
||
time.sleep(.5); s.recv(65536)
|
||
def cmd(c, p=.6):
|
||
s.sendall((c+'\n').encode()); time.sleep(p)
|
||
try: s.recv(200000)
|
||
except: pass
|
||
cmd('screendump /mnt/cosecha/escritorios/shot.ppm', 4) # el scanout REAL del guest
|
||
```
|
||
|
||
### Hacer CLIC sin ventana — y por qué el ratón es relativo
|
||
|
||
`info mice` dice `QEMU PS/2 Mouse`: **movimiento RELATIVO**, así que no hay «ir a (x,y)». La
|
||
maniobra que sí funciona es **fijar contra una esquina** y moverse desde ahí:
|
||
|
||
```python
|
||
cmd('mouse_move -3000 3000', 2) # clava el puntero en la esquina INFERIOR IZQUIERDA
|
||
cmd('mouse_move 10 -8', 1) # y desde la esquina, al lanzador del panel
|
||
cmd('mouse_button 1', .5); cmd('mouse_button 0', 8)
|
||
```
|
||
|
||
`sendkey` también anda (`sendkey alt-f2`, `sendkey k`, …) y **la combinación arranca krunner** —se ve
|
||
en el log de kwin— pero **la ventana de krunner no llegó a pintar** en dos intentos. Queda anotado
|
||
como pendiente propio, separado del bug de abajo.
|
||
|
||
### Lo que estas dos herramientas destaparon el 2026-09-03
|
||
|
||
1. **El panel salía con el reloj y nada más, y no era el panel: eran los ICONOS.** Los `.so` de
|
||
todos los applets estaban instalados; lo que faltaba era `breeze-icons`. Ver el commit
|
||
«escritorios: KDE y GNOME corrían SIN tema de iconos». Evidencia:
|
||
`../evidencia/plasma6-qemu-2026-09-03-panel-con-iconos.png` — kickoff, gestor de tareas, bandeja
|
||
(notificaciones, volumen, teclado, red), reloj y «mostrar escritorio», todos pintando.
|
||
|
||
2. **El lanzador de aplicaciones NO ABRE**, y el diálogo de error lo dice entero:
|
||
|
||
```
|
||
qrc:/qt/qml/plasma/applet/org/kde/plasma/kickoff/main.qml:191:25: Type FullRepresentation unavailable
|
||
.../Header.qml:18:1: module "org.kde.coreaddons" is not installed
|
||
```
|
||
|
||
`recipes/incoming-kde/kcoreaddons.toml` pasa `-DKCOREADDONS_USE_QML=OFF` (la cabecera lo dice:
|
||
«QML bindings / python / docs apagados»), así que el módulo QML `org.kde.coreaddons` no se
|
||
construye. Evidencia: `../evidencia/plasma6-qemu-2026-09-03-kickoff-sin-coreaddons.png`.
|
||
**`yupana radio kcoreaddons` = 71**, o sea que prenderlo es una campaña de granja, no un ticket.
|
||
|
||
**Regla que sale de las dos:** una captura donde el escritorio «pinta» NO prueba que el escritorio
|
||
funcione. El barrido barato que sí lo prueba es cruzar los `import` de los `.qml` instalados contra
|
||
los módulos QML con `qmldir` que hay en el rootfs; así salió `org.kde.coreaddons` y, de yapa,
|
||
`org.kde.kscreenlocker` y `org.kde.newstuff.core`, que también faltan.
|
||
|
||
### El arreglo, verificado con UN build (2026-09-03)
|
||
|
||
`-DKCOREADDONS_USE_QML=ON` + **un solo** `takana build kcoreaddons` (56 s) instala
|
||
`usr/lib/qt6/qml/org/kde/coreaddons/{libkcoreaddonsplugin.so,qmldir,…}`. Hidratado ESE artefacto en
|
||
el rootfs y rehecha la imagen, el menú **abre**: usuario, buscador, Favoritos / Todas las
|
||
aplicaciones, y las pestañas Aplicaciones / Lugares / Sesión
|
||
(`../evidencia/plasma6-qemu-2026-09-03-menu-abre.png`). Escribiendo `konsole` en el buscador y Enter,
|
||
la terminal arranca y corre — `uname -a` da el kernel 6.16.12 de takana y `konsole --version` da
|
||
25.04.3 (`../evidencia/plasma6-qemu-2026-09-03-konsole-uname.png`).
|
||
|
||
Es la cadena completa del escritorio por primera vez: **panel → menú → búsqueda → app → shell**.
|
||
|
||
Se probó con UN build a propósito: la cascada de 71 es de granja y no hacía falta pagarla para saber
|
||
si el arreglo era el correcto. Las 71 quedan como **deuda declarada** —`escritorio-kde 192/263`— y la
|
||
imagen de hoy corre con un `kcoreaddons` más nuevo que aquel contra el que enlazaron sus
|
||
consumidores. Eso es legítimo porque lo que cruza es un **SONAME** (misma versión, misma ABI, sólo se
|
||
suma un módulo QML); es la misma regla que decidió la promoción de pipewire. Lo que NO se puede es
|
||
hidratar dos artefactos distintos en la misma ruta.
|
||
|
||
⚠ El aviso rojo `Could not find '', starting '/bin/sh' instead` de konsole era real y NO venía de
|
||
`/etc/passwd` (que dice `/bin/sh`): konsole lee **`$SHELL`**, y este getty no es un login shell.
|
||
Arreglado exportándolo en `plasma-start-qemu.sh`.
|