# SDD 27 — Metapaquetes instalables: del rootfs hidratado al `takana install escritorio-kde` > **Estado: PROPUESTA.** Nada de lo de acá está implementado. Lo que sí está medido es el punto de > partida, y las mediciones llevan fecha 2026-09-09. Escrito a pedido del usuario mientras se > cerraban los huecos de la imagen KDE. ## 0. La pregunta Hoy sabemos construir. Sabemos hidratar un rootfs y meterlo en una imagen que arranca. Lo que no existe es **instalar un escritorio como una unidad**: hoy «KDE» es una lista dentro de un fichero del repo, no algo que un usuario pueda pedir. Y hay una pregunta previa que el usuario formuló mejor de lo que estaba escrito en ningún lado: > *el toolbox CLI es general, que sea piso userland del sistema siempre. los extras son igual > instalaciones, depende de quién instale qué.* Eso son **tres capas distintas**, y hoy el repo las mezcla en una sola lista por escritorio. ## 1. Lo medido: hoy los escritorios NO heredan la base `docs/state/targets.toml` declara un perfil `base` de **27 paquetes**: `bash`, `git`, `sudo`, `doas`, `util-linux`, `shadow`, `kbd`, `procps-ng`, `iproute2`, `iputils`, `dhcpcd`, `e2fsprogs`, `dosfstools`, `gnupg`, `ca-certificates`… El fichero ya avisa que «kde/gnome/cosmic **NO** heredan base», pero la consecuencia no estaba escrita. Medida: > **De los 27 paquetes de `base`, la clausura de `escritorio-kde` alcanza 2.** Y comprobado contra el rootfs real de la imagen KDE (`kde-qemu-rootfs`): | se busca | está | |---|---| | `bash`, `git`, `sudo`, `doas`, `dhcpcd`, `useradd`, `gpg` | **NO** | | `ip`, `mount`, `fsck` | sí, pero **son applets de busybox** (`/sbin/ip → ../bin/busybox`) | | `ssh`, `curl` | sí, de rebote: entran por la clausura de KDE, no por `base` | ⇒ **Sí: abrís el escritorio y es como si `base` no existiera.** No hay shell de verdad (busybox `sh`, no bash), no hay `sudo` ni `doas`, no hay `git`, y **no hay `dhcpcd`** — o sea que la imagen no sabe pedir una IP salvo lo que haga busybox. Lo que sí hay es el **otro** base: `arje-zero` como PID1 más busybox, que es lo mínimo para arrancar. Son dos cosas distintas con el mismo nombre coloquial: - **base de arranque** (`metal-rootfs`): arje-zero + busybox + kernel. La imagen la funde por hardlinks. Existe. - **base de userland** (`[perfil.base]`): las 27. **No la funde nadie.** Esto no es un bug de una imagen: es que la composición entre perfiles **no está definida**. ## 2. Las tres capas que hay que separar | capa | qué es | quién decide | hoy | |---|---|---|---| | **piso** | userland siempre presente: shell, red, usuarios, paquetes, `git` | la distro | existe como `[perfil.base]`, no lo hereda nadie | | **escritorio** | KDE / GNOME / COSMIC / sway y lo que los hace ser ellos | la distro | existe como perfil, es lo único que se materializa | | **extras** | lo que cada quien instala encima | el usuario | no existe como operación | Y hay una cuarta que el usuario nombró y conviene no perder: **el toolbox CLI**. Hoy hay **652 recetas selladas que ninguna imagen alcanza** — 361 Go, 214 Rust, 67 C — y son casi todas herramientas de línea de comandos. Ya construidas, ya reproducibles: **coste de build cero, sólo declararlas**. Si el toolbox es piso, va en la capa 1 y no en cada escritorio. ## 3. Un «metapaquete» ya existe, y se llama perfil `[perfil.escritorio-kde]` con sus 49 raíces **es** el metapaquete: una lista de nombres cuya clausura define qué entra. Lo que le falta para ser instalable son tres cosas concretas: 1. **Herencia.** Un perfil tiene que poder decir `hereda = ["base"]` en vez de repetir la lista. Hoy los cuatro escritorios repiten `dejavu-fonts`, `desktop-file-utils` y las `*-shared` de runtime, y ya se vio lo que pasa: se añade a uno y se olvida en los otros. 2. **Publicación.** `targets.toml` vive en el repo y es de tiempo de build. Para que el instalador lo use tiene que salir al repositorio firmado como un objeto más, igual que un `.swm`. 3. **Un verbo.** `takana install escritorio-kde` no existe: `install` resuelve **un paquete** por nombre en el índice. Instalar un perfil es resolver una LISTA y aplicar su clausura. ## 4. La decisión de fondo del instalador: reproducir o hidratar Ésta es la única pregunta que no es de implementación, y conviene decidirla antes de escribir código. **Hoy el canal de paquetes NO distribuye binarios.** `pack` produce un `.swm` —una receta de transformación sobre fuente pública— e `install` **reproduce construyendo**, con cache-hit del corpus. Es coherente con todo el diseño: lo que viaja es la receta, no el binario. - **Reproducir** un escritorio entero en la máquina del usuario son **horas** de compilación (KDE son 301 nodos; Qt y Firefox solos ya son la mayor parte de una tarde). Coherente y honesto, pero inaceptable como experiencia de instalación. - **Hidratar desde artefactos firmados** es lo que ya hace `hydrate-profile.py`: segundos, porque son hardlinks contra el store. Pero eso **es entregar binarios**, y activa entera la obligación de licencias que se cerró el 2026-09-09 (`scripts/licencias-rootfs.sh`, que veta si un paquete no declara licencia). También activa la pregunta de confianza: el ADR 0014 ya dice que el cuerpo es inmutable y direccionado por contenido, así que **el origen no necesita confianza** — lo que se firma es la raíz, no el servidor. **La salida no es elegir una: es que las dos existan y el usuario elija**, igual que el ADR 0014 hizo con los orígenes. Instalar por hidratación es el camino normal; reproducir es el camino auditable, y que exista es lo que hace verificable al primero. Lo que hay que definir es el **default** — y ahí la respuesta razonable es hidratar, porque el que quiere auditar puede reproducir cuando quiera y comparar hashes, que es exactamente lo que `selfhost-verify` ya hace. ## 5. La imagen y el instalador son el mismo problema con dos salidas Hoy hay dos caminos que hacen casi lo mismo y no se hablan: - **Imagen**: perfil → `hydrate-profile.py` → rootfs → `install-image-efi.sh` → `.img` que arranca. - **Instalador**: TUI + `base-system`, que instala sobre un disco. Si un perfil es publicable e instalable, los dos son **el mismo verbo con distinto destino**: uno escribe a una imagen, el otro a una partición. Vale la pena unificarlos antes de que diverjan más: hoy ya divergieron una vez —los `hydrate-*.sh` por escritorio contra `targets.toml`, con 21 paquetes declarados que no llegaban a la imagen de GNOME y 17 a la de COSMIC— y costó encontrarlo. ## 6. Sobre el nombre del paquete (`.swm` vs `.tkn`) `.swm` **no es residuo del renombre**: significa «Software Mutación» y describe lo que el fichero es —una mutación reproducible sobre una fuente—, no la marca. Renombrarlo a `.tkn` sería alinear marca y formato, y es defendible, pero **no lo pide ninguna inconsistencia técnica**. Si se hace, es una decisión de ADR y con la misma disciplina que el renombre de hoy: hay que mirar si la extensión entra en algún hash o en el índice del repo antes de tocarla. El verbo, en cambio, ya es el correcto: **`takana install`**. ## 7. Orden propuesto 1. ~~**Herencia entre perfiles**~~ — **HECHO el 2026-09-09**, y resultó ser una línea por perfil: el mecanismo `hereda` YA EXISTÍA en `scripts/targets.py` (transitivo, con detección de ciclos y orden preservado) y `escritorio-sway` ya lo usaba desde el 2026-08-07. Los otros tres simplemente no lo habían declarado. Ahora kde/gnome/cosmic heredan `cli`, que hereda `base`. Medido: raíces 49→96 (kde), 39→86 (gnome), 43→88 (cosmic); nodos 301→356, 204→256, 162→216; **deuda 0 en los tres** —no hubo que construir nada, ya estaba todo sellado— y **cero colisiones nuevas** al hidratar (los 28 `.hammer-tmp` son los mismos de `gmp`/`mpfr` de antes). Verificado en el rootfs: aparecen `bash`, `sudo`, `doas`, `git`, `dhcpcd`, `useradd`, `gpg`, `rg`, `fd`, `bat`, y `/sbin/ip` deja de ser el applet de busybox para ser el binario de iproute2. ⚠ `escritorio-mirada` NO hereda a propósito: es el rootfs *slim* del USB y sumarle 47 raíces contradice su razón de ser. Si algún día se quiere, es la misma línea. 2. **Decidir el piso**: qué del toolbox CLI de 652 entra en `base`. Coste de build cero. 3. **Publicar perfiles** al repositorio firmado. 4. **`takana install `**, hidratando por defecto y con `--reproduce` como camino auditable. 5. **Unificar imagen e instalador** sobre ese verbo. Los pasos 1 y 2 se pueden hacer ya y no dependen de ninguna decisión de arquitectura. ## 8. «Metapaquete», no «perfil» — y el problema real que destapa el nombre El usuario lo dijo mejor: **«perfil» suena a preset exclusivo**, y eso arrastra una suposición que nadie decidió. La pregunta que lo destapa es concreta: > *¿no voy a poder instalar KDE y mirada y GNOME al mismo tiempo, y cambiar entre ellas con un > greeter?* **En el STORE ya conviven, y no en teoría.** Medido el 2026-09-09 comparando los dos rootfs hidratados que hay en disco (`kde-rootfs` 78.934 ficheros, `gnome-rootfs` 19.955): | | | |---|---| | rutas presentes en LOS DOS | 14.455 | | …de ésas, **mismo inodo** (el MISMO artefacto del store) | **12.766** (88 %) | | …**inodo distinto** = colisión real | **1.689** (12 %) | O sea que el 88 % de lo compartido no es un conflicto: es literalmente el mismo fichero, porque el store es direccionado por contenido y los dos escritorios lo enlazan. **Lo que impide instalar dos escritorios no es el store: es PROYECTARLOS AL MISMO `/usr`.** 1.689 ficheros quieren la misma ruta con contenido distinto y gana el último que se proyecte — el mismo cuadro que `targets.toml` ya documenta para las dos poppler y que se vio hoy con `gmp`/`mpfr` dejando 28 `.hammer-tmp`. Y las colisiones no son misteriosas: `libuuid.so.1.3.0`, `dbus-daemon`, `gdbus`, `gapplication`, `/etc/dbus-1/*.conf`… Salen de que **cada cola tiene su propia `glib` y su propio `dbus`**. Son recetas distintas con el mismo soname. ⇒ Hay **dos caminos**, y no son excluyentes: 1. **Bajar las colisiones**: unificar lo que no tiene por qué estar duplicado (una sola `glib`, un solo `dbus`). Ataca la causa y además hace más chicas las imágenes. Es trabajo de catálogo. 2. **No proyectar a un `/usr` único**, que es lo que el [SDD 18](18-wawafs-store-vivo.md) ya propone: *«activar un nodo = montar su composefs como `/usr`»*. Con eso cada escritorio es una VISTA compuesta y las 1.689 colisiones dejan de existir por construcción — no hay un `/usr` compartido que aplastar. El greeter encaja solo: el arranque por GRAFO del ADR 0010 ya elige qué clausura activar, y `mirada-greeter` existe. Elegir escritorio en el greeter = elegir qué vista montar. **Corolario para el nombre**: si un escritorio es una vista montable y no un preset del sistema, entonces `metapaquete` es la palabra correcta y `perfil` la equivocada — instalás tres y elegís al arrancar, igual que en cualquier distro. Renombrar la clave de `targets.toml` es barato en concepto y caro en llamadores (build-state, drenar, hydrate-profile, vigia-imagen, seed-graph); vale como decisión de ADR, con el mismo cuidado que el renombre de `hammer`→`takana`: mirar antes si la palabra entra en algún hash o en el índice del repo. ⚠ Y una consecuencia de orden: **el punto 1 del plan (herencia) no cambia por esto, pero el punto 5 sí**. Unificar imagen e instalador sobre un `/usr` proyectado es construir sobre el supuesto de que sólo hay un escritorio a la vez. Antes de unificarlos conviene decidir si el destino es un FHS plano o una vista composefs, porque es la diferencia entre «instalás uno» y «instalás los tres». ## 9. Herencia hace DOS trabajos distintos, y sólo uno es herencia La herencia del §7.1 contesta *«¿qué **contiene** este metapaquete?»*. El usuario preguntó otra cosa: > *¿voy a poder ejecutar un kate desde mirada, o kate está para KDE y no se hereda?* Eso es *«¿qué **puede correr** en este sistema?»*, y hoy se confunde con lo anterior porque hay un solo mecanismo. ### `kate` no es «de KDE» técnicamente — lo es sólo por empaquetado Medido el 2026-09-09 sobre la clausura de `recipes/incoming-kde/kate.toml`: - **110 recetas** en total. - Lo único que suena a Plasma son `kwindowsystem`, `plasma-activities` y `plasma-wayland-protocols` — y **las tres son librerías**, no el shell. La última es literalmente XML de protocolo. - **No aparece `plasmashell`, ni `kwin`, ni `plasma-workspace`.** ⇒ kate necesita Qt6 + KF6 + un compositor Wayland. Mirada **tiene** compositor. Que hoy no se pueda ejecutar desde mirada no es una limitación técnica: **es que no está instalado**. Coste medido de tenerlo ahí: la clausura de `escritorio-mirada` son 41 nodos, la de kate 110, y **24 ya están** ⇒ habría que sumar **86**, que es esencialmente traerse Qt6 y KF6. Y ese precio es el mismo desde mirada que desde sway: no lo cobra KDE, lo cobra Qt. ### Las tres clases, y sólo la primera es herencia | clase | qué es | ¿se hereda? | |---|---|---| | **piso** | `base` + `cli` | **sí** — todo sistema lo tiene (hecho en §7.1) | | **escritorio** | `plasmashell`, `kwin`, `breeze`, `powerdevil`, `kscreen` | **no, y no tiene sentido**: son la implementación de *ser* KDE. Correr `kwin` desde mirada no significa nada, mirada ya tiene compositor | | **aplicaciones** | `kate`, `okular`, `dolphin`, `gwenview`, `ark`, `spectacle`… | **no se heredan: se INSTALAN**. Hoy están dentro del metapaquete del escritorio, y ahí está el error de clasificación | ### La prueba de que la distinción ya existe sin estar nombrada `mpv`, `atuq`, `swayimg` y `libnotify` **están declaradas en los CUATRO escritorios** — repetidas, no heredadas. `zathura` en tres, `foot` en dos. O sea que el repo **ya trata las apps distinto de `kwin`**, sólo que copiando la línea en cada perfil en vez de decirlo. Y el mecanismo también existe a medias: esas cuatro viven en el CORPUS y no en una cola, con el comentario explícito de que es «justamente para poder listarse en las cuatro». Falta el último paso. ### Propuesta Que `escritorio-kde` sea **el escritorio** —shell, compositor, tema, ajustes, energía— y que las apps salgan a metapaquetes propios: `kate` suelto, o agrupadas en algo tipo `kde-apps`, instalables desde cualquier sistema. Con eso la pregunta del usuario se contesta sola: takana install kate # desde mirada, desde sway, desde donde sea trae sus 86 recetas faltantes y funciona, **sin instalar Plasma**. ⚠ Y esto se lleva bien con el §8: si un escritorio es una VISTA montable y las apps son metapaquetes aparte, entonces «tengo KDE y GNOME instalados y elijo en el greeter» y «uso kate dentro de mi sesión de GNOME» dejan de ser dos problemas distintos. Son el mismo: qué clausura se compone para esta sesión. **Coste**: mueve unas 20 declaraciones de `targets.toml` y no toca ni una receta ni un artefacto — es reclasificar, no reconstruir. No se hizo todavía porque es decisión de diseño, no de limpieza.