runbook cosmic: el cuarto escritorio, escrito mientras se hace
Deja asentado por qué COSMIC no se parece a KDE ni a GNOME (no hay torre de C
debajo: la primera receta salió estática y con cero NEEDED), la tabla de lo que
se hereda gratis de mirada/GNOME, el pin en lockstep epoch-1.5.0, y los seis
gotchas medidos — entre ellos que start-cosmic es bash de verdad (mapfile, [[ ]],
${!var}) y que bash no lo pide ningún [deps], así que a la imagen no lo trae
nadie por accidente.
Y el porqué del orden de ataque, que NO es el orden de arranque: cosmic-bg antes
del panel para que «pinta el fondo pero no el panel» separe la capa de UI del
transporte.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Semantic delta
No definition changed: this change is text, documentation or data.
1 files · +116 −0
- docs/runbooks/cosmic-desktop.md +116 −0
diff --git a/docs/runbooks/cosmic-desktop.md b/docs/runbooks/cosmic-desktop.md
new file mode 100644
index 00000000..7478d131
--- /dev/null
+++ b/docs/runbooks/cosmic-desktop.md
@@ -0,0 +1,116 @@
+# Runbook — COSMIC, el cuarto escritorio
+
+Estado al 2026-08-03: **campaña abierta.** Tres piezas selladas (`cosmic-session`, `cosmic-icons`,
+`cosmic-bg`) y el compositor en construcción. Este documento se escribe mientras se hace, no después.
+
+COSMIC es el escritorio de System76, en Rust sobre **smithay** (compositor) e **iced/libcosmic**
+(clientes). Es el cuarto de hammer, tras [mirada](mirada-usb-nvidia.md),
+[KDE Plasma 6](kde-qemu-desktop.md) y [GNOME](gnome-qemu-desktop.md).
+
+## Por qué NO se parece a los dos anteriores
+
+KDE y GNOME costaron lo que costaron por la misma razón: una torre de C con Qt o
+glib/GObject/introspección debajo, donde cada capa se paga entera antes de ver un píxel. COSMIC no
+tiene esa torre. La primera receta —`cosmic-session`— salió **a la primera y sin una sola dep en C**:
+ELF estático, cero `NEEDED`.
+
+Lo que sí hereda es lo que ya está pago:
+
+| lo que COSMIC necesita | de dónde sale | costo |
+|---|---|---|
+| las deps en C de smithay (drm, gbm, seat, input, udev, xkb, pixman) | `mirada-compositor`, que ya es un compositor smithay de este lab | **cero** — misma lista |
+| `libdisplay-info` + `hwdata` | copiadas byte a byte de la cola GNOME | **cero** — mismo hash, artefacto ya sellado |
+| `bash`, `dbus-run-session`, `hicolor-icon-theme`, mesa-llvmpipe | corpus | cero |
+| el andamiaje de arranque en QEMU (`run-qemu-desktop.sh`, base rootfs, console-getty, screendump) | campañas KDE/GNOME | cero |
+
+La deuda propia que sí trae, y que ninguna de las otras campañas tocó, es la del **unwinder de la std
+de rustc** cuando el enlace no es estático — la misma que ya está documentada para las recetas Cargo
+del corpus.
+
+## El pin es de la SUITE, no de cada paquete
+
+COSMIC versiona **todos** sus repos en lockstep con el tag `epoch-N`. Comprobado repo por repo: los
+doce componentes están en `epoch-1.5.0`.
+
+**No mezclar epochs entre piezas.** Comparten protocolos propios (`cosmic-protocols`) y el formato de
+configuración (`cosmic-config`); un desajuste ahí no da error de compilación, da un escritorio que
+arranca y no se entiende consigo mismo — que es mucho más caro de diagnosticar.
+
+## La cola
+
+`recipes/incoming-cosmic/`, aislada (otro agente comparte el repo; nunca `git add -A`).
+
+Las deps se resuelven **hermano → padre**: desde `incoming-cosmic/` se ven las recetas de
+`recipes/`, pero **no** las de `incoming-gnome/` ni `incoming-kde/`. Por eso `libdisplay-info` y
+`hwdata` entran copiadas. Y copiar es gratis de verdad, no «casi»: el ArtifactHash no depende de la
+ruta de la receta, así que un fichero idéntico con deps que resuelven a lo mismo da **el mismo hash**
+⇒ cache hit sobre el artefacto que ya existe. Se verificó antes de copiar (`b3:260f0519`,
+`b3:bdc36cf9`), no después.
+
+## Qué levanta la sesión, y por lo tanto el orden de ataque
+
+`cosmic-session/src/main.rs` es la lista autoritativa —el mismo método que cerró la capa JS de GNOME:
+*leé el fichero donde el programa declara lo que arranca, no lo descubras de a uno*:
+
+```
+cosmic-comp → cosmic-notifications · cosmic-panel · cosmic-app-library
+ → cosmic-launcher · cosmic-workspaces · cosmic-osd · cosmic-bg · cosmic-idle
+```
+
+Más `cosmic-settings-daemon` y `xdg-desktop-portal-cosmic` fuera de esa lista.
+
+| pieza | estado | hash |
+|---|---|---|
+| `cosmic-session` | ✅ sellado | `b3:81f02351` |
+| `cosmic-icons` | ✅ sellado (671 SVGs) | `b3:94d06f77` |
+| `cosmic-bg` | ✅ sellado | `b3:1ecca9c1` |
+| `cosmic-comp` | 🔨 en construcción | — |
+| el resto | pendiente | — |
+
+**El orden no es el de la lista de arranque.** `cosmic-bg` va antes que el panel a propósito: habla
+Wayland con `smithay-client-toolkit` y **no toca libcosmic ni iced**, mientras que panel, launcher,
+osd y workspaces son todos clientes de iced. Con el fondo sellado, «pinta el fondo pero no el panel»
+separa la capa de UI del transporte; sin él, las dos preguntas llegan juntas.
+
+## Gotchas medidos (no previstos)
+
+1. **`cargo rustc --` exige UN target.** La fase compile del lab pasa flags tras el `--`, y cualquier
+ paquete con binario + lib + ejemplos corta con «extra arguments to `rustc` can only be passed to
+ one target». Se arregla con `flags = ["--bin", "<nombre>"]`. Le pasa a cosmic-comp y a cosmic-bg
+ (workspace con `config/`), y le va a pasar a casi todos: **ponelo desde el principio.**
+2. **`start-cosmic` es bash de verdad, no sh.** Usa `mapfile`, `[[ ]]` y expansión indirecta
+ `${!var}`; con el busybox del rootfs no arranca. `bash` ya está en el corpus, pero **tiene que
+ entrar en la imagen** — y no lo pide ningún `[deps]`, así que no lo va a traer nadie por accidente.
+ Lo mismo con `dbus-run-session` (de `dbus`), que es lo que el script exec-uta al final.
+3. **`rust-toolchain.toml` con `channel = "1.93"` es inerte acá** — es una perilla de rustup, y el
+ sandbox tiene el rustc de Alpine (1.96) pelado. Conviene saberlo antes de «arreglarlo».
+4. **`cosmic.desktop` existe DOS veces** (en cosmic-session y en cosmic-comp) con contenido distinto
+ y en la misma ruta. El de cosmic-comp es el de la «bare session» y apunta a `/usr/bin/cosmic-service`,
+ que vive en la rama de systemd que acá no va. Se instala **sólo** el de cosmic-session; si entraran
+ los dos, quién gana depende del orden de hidratación y el que pierde es el bueno.
+5. **`libsystemd` no es systemd.** La feature `default = ["systemd"]` de cosmic-comp trae el crate
+ `libsystemd`, que es una **reimplementación en Rust** del protocolo, no un binding a la C. Y
+ `logind` habla `org.freedesktop.login1`, que acá lo sirve `arje-logind-compat`. No hay que apagar
+ nada: el nombre de la feature es el del protocolo, no el del programa que lo contesta.
+6. **Las features de smithay que asustan no cuestan deps de build**: `backend_vulkan` (crate `ash`),
+ `backend_x11` (`x11rb` con `dl-libxcb`) y `xwayland` cargan todo por **dlopen**. Son deuda de
+ RUNTIME —libxcb y vulkan-loader viven hoy sólo en la cola KDE—, no un muro de compilación.
+
+## Cómo se construye
+
+```sh
+cd ~/hammer
+./target/release/hammer --store store hash recipes/incoming-cosmic/<pieza>.toml # dry-run, ~2ms
+./target/release/hammer build recipes/incoming-cosmic/<pieza>.toml --store store
+```
+
+## Lo que falta, en orden
+
+1. Cerrar `cosmic-comp`. Es el gate: sin compositor no hay escritorio que probar.
+2. El primer cliente de iced (`cosmic-panel`), que es la pregunta abierta de verdad — libcosmic con
+ `winit`/`wgpu` puede pedir más de lo que pide cosmic-bg.
+3. `cosmic-settings-daemon`, `cosmic-launcher`, `cosmic-app-library`, `cosmic-notifications`,
+ `cosmic-osd`, `cosmic-workspaces-epoch`, `cosmic-idle`.
+4. Imagen QEMU con `bash` + `dbus-run-session` + `hicolor-icon-theme`, y **validar CON PANTALLA**
+ (`DISP=gtk` + `screendump`, contar colores distintos) — regla heredada de KDE y GNOME.
+5. `xdg-desktop-portal-cosmic` y `cosmic-greeter`, que son de la etapa siguiente.