Las 24 en deuda selladas, más clang18. base 52/52, cli 75/75, mirada 33/33, KDE 163/163,
sway 129/129, GNOME 119/119, COSMIC 90/90. Cero artefactos vacíos en 2103.
Las dos últimas (`cosmic-settings`, `cosmic-applets`) no cedieron al paralelismo: habían
caído con 3, 2 y 1 core. Lo que las destrabó fue MEMORIA, y la vía compatible con T9 es
zram, no swap en disco: se midió que el zram comprime a 4x real (1,9 G de páginas en
478 MB de RAM) y que los 4 GiB de `swap-zram` son sólo su default, sin justificación.
Se añadió un SEGUNDO dispositivo zram en vez de redimensionar el primero: redimensionar
exige `swapoff`, y con 1,94 G dentro y 994 MB de RAM libre eso es el escenario exacto que
volteó la máquina el 2026-08-17 —el propio script lo advierte y tiene freno—. Verificado
`backing_dev=none` en el dispositivo nuevo, que es el único agujero de zram contra T9.
`cosmic-settings` selló después con 3 cores, la misma config con la que había fallado ⇒
el paralelismo nunca fue la causa, sólo esquivaba el síntoma.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4
`targets.toml` declaraba gnome-session, gnome-settings-daemon y gdm como raíces del
perfil, mientras el encabezado de las tres recetas dice "APARCADA por diseño" desde el
2026-08-07, verificado contra el meson.build de cada tag: las tres mueren en GTK3, que es
una de las tres deudas que el frente GNOME aparcó a propósito (GTK3 / X11 / PAM).
Dos documentos del repo decían cosas opuestas, y el que se mira primero es el grafo. El
resultado era deuda FANTASMA: escritorio-gnome reportaba 124/127 con 3 en `never` para
siempre, se leía como trabajo pendiente, y el worker las reintentaba en cada ciclo. En
esta misma sesión me hizo afirmar dos veces que GNOME estaba "a 3 recetas de cerrar".
No bloquean el escritorio: gnome-shell no depende de gnome-session ni de g-s-d, ni en
build ni para arrancar. El camino vivo es mutter → gnome-shell, lanzado por arje; el
único que pedía gnome-session era gdm.
Las recetas SIGUEN en el repo con su análisis intacto. Si algún día se autora GTK3, se
vuelven a añadir a `paquetes` y el objetivo reaparece solo.
escritorio-gnome: 119/119, CIERRA.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4
project_plan es target_root.join(rel) + escribir por ruta, igual que hydrate: un symlink de
directorio dejado por una generación anterior se seguía. Reproducido — la generación 2 escribía
usr/share/pkg/archivo FUERA del root y ApplyReport salía en verde.
Con --root / no cambia nada (todo empieza por /); el caso real es , que es como se arma una imagen.
Se mide el DIRECTORIO PADRE, no el destino: un Replaced sobre un symlink que apunta afuera es
legítimo porque rename pisa el symlink en vez de escribir a través de él, y medir el destino lo
rechazaría por error. Y raiz_real() resuelve el tramo existente del root dejando pegado el que
todavía no existe, para que la comprobación valga también sobre una imagen nueva.
Dos tests, uno por dirección: el que sale falla ruidoso, el que se queda dentro (usr-merge,
temas de iconos) sigue proyectando.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ACUcwo9mZsE5ocYVE9npih
Buscando el sitio de H3 —«harkaq valida rutas a mano»— resultó que harkaq NO valida rutas a
mano: delega en Landlock. Donde no se validaba NADA era en hydrate.
Reproducido: hidratar es target_fhs.join(rel) y escribir por ruta, así que un symlink de
directorio ya puesto en el FHS se sigue. Artefacto A trae usr/share/pkg → /algún/lado (los
symlinks se replican literales, y así debe ser); al hidratar B, usr/share/pkg/archivo aterrizaba
FUERA del root y hydrate devolvía Ok(1). Con --into sobre una imagen eso es escribir en el
anfitrión diciendo que todo fue bien.
Cuánto se estaba disparando: cero. En el store hay 160 symlinks absolutos y NINGUNO apunta a un
directorio; de ~42 000 relativos ninguno sale de su artefacto. Mina desactivada, no incendio.
La comprobación va por DIRECTORIO (un canonicalize por fichero sería un realpath por entrada,
T8) y la semántica es la de RESOLVE_IN_ROOT, no la de NO_SYMLINKS: un symlink que se queda
dentro tiene que seguir andando —usr-merge /lib → usr/lib, los 22@2x → 22 de los iconos— y hay
test para cada dirección. Lo que queda de la propuesta (la versión sin carrera, con openat2 +
linkat/renameat) queda escrito con su precio: arrastra el camino de patchelf.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ACUcwo9mZsE5ocYVE9npih
El gate de SDD 25 §4.ter existía y NADIE lo corría. Un kernel reconstruido sin MEMCG volvería
a pasar inadvertido — y ese fallo no se ve del lado del desarrollo, porque el kernel de la
máquina de trabajo sí trae MEMCG: sólo se ve comprobando el artefacto.
Mismo cable que el vigía de fuentes y por la misma razón que está escrita ahí arriba: lo que
nadie refresca envejece hacia el optimismo. Ahora cada ciclo deja el veredicto en
docs/state/kernel-contract.txt y el git log lo muestra como el resto del khipu.
El fichero se escribe por temporal y sólo se mueve si tiene contenido: contract sale != 0
cuando el contrato no se cumple —y ese rojo es justo lo que hay que guardar—, pero un fichero
vacío se leería como «nada que objetar».
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ACUcwo9mZsE5ocYVE9npih
Se construyeron en gioser, no en el worker: el LXC dev.gioser.net lleva ~14 h sin ssh.
Quedan `cosmic-applets` y `cosmic-settings`, que superan el techo de memoria de la caja
INCLUSO con un solo core (7,7 G con un suelo de 2,3 G que ponen gitea y los agentes) — no
es paralelismo, es el pico de un `rustc` solo.
El método que las trajo: capar por entorno con `taskset` (nunca `-j` en la fase, que
cambiaría el ArtifactHash) bajando 3→2→1 cores, con un vigía que corta el lote si el swap
libre baja de 250 MB. Cada bajada compró recetas. El vigía cortó cuatro veces y la máquina
sobrevivió las cuatro; el LXC pasó por el mismo pico sin guardián y no volvió.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LykB7vw38b4Ck1Zij15RQ4
hammer kernel contract --sealed: 5 de 5 vigentes cumplen su perfil, exit 0. Antes eran 2 de 11.
Una Card que pide memory.max ahora encuentra el fichero en vez de dejar un warn! y correr sin
tope.
Lo medido, no lo supuesto:
- el x86_64_defconfig de 7.1 ya NO trae MEMCG=y ⇒ había que pedirlo explícito;
- MEMCG no tiene ningún depends on, así que el olddefconfig no podía tragárselo — comprobado
igual contra el .config producido, que es la regla del guardián;
- precio: +80 KiB en linux-generic (+0,49%), +84 en linux-metal, +88 en linux-metal-dual,
+80 en linux-gioser (+0,71%). Medio punto de kernel por contabilidad por unidad y presión.
Evidencia cruda en docs/evidencia/tasas-kernel-2026-08-29/contrato-h1-pagado.txt, con el
diff-back del plan de gioser sobre su config nuevo (35 cumplidos, 0 incumplidos).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ACUcwo9mZsE5ocYVE9npih