tawasuyu

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1181Shell 82Rust 62Markdown 521515 Definiciones

gnome: la primera extensión del catálogo — blur-my-shell v72, instalada Y activa

La imagen de GNOME traía la CÁSCARA: el shell sabe cargar extensiones —`ui/extensionSystem.js` va
en el gresource sin opción que lo apague y su gschema sellado trae `enabled-extensions`— pero no
había ninguna que cargar. Esta es la primera, y fija el patrón para las otras ~1400.

⚠ NO HIZO FALTA TLS, que era la conclusión fácil del análisis de ayer. glib-networking sólo lo pide
BAJARLAS desde extensions.gnome.org con el descargador del shell. Empaquetada, una extensión se
instala como cualquier receta y no toca la red.

LA FUENTE ES EL REPO DEL AUTOR, NO EL ZIP DE EGO, por dos razones y las dos medidas:
  1. hammer no sabe abrir un zip: el fetch extrae con `tar -x` y GNU tar contesta «This does not
     look like a tar archive». Ninguna receta del corpus usa .zip.
  2. Y aunque lo abriera, el zip de EGO es un ARTEFACTO que construye EGO desde este mismo repo.
     Pinear el zip es pinear el binario de un tercero; pinear el commit es pinear el código.
El tag v72 es el que EGO sirve para shell 48 —preguntado a su API, no supuesto— y el metadata.json
declara ['46','47','48','49','50']. ⚠ Eso hay que preguntarlo por extensión: nixpkgs va por GNOME
50 y hay extensiones que ya sólo declaran el major nuevo.

SIN `gnome-extensions pack`, que es lo que usa el Makefile de upstream y es el CLI que nuestra
receta del shell apaga (-Dextensions_tool=false; encenderlo costaría gnome-autoar y re-hashear
gnome-shell entero). No hace falta: `pack` sólo arma un zip que después alguien descomprime, y lo
que el shell lee es un DIRECTORIO. El layout no se inventó — se leyó del zip de EGO v72, que es la
salida de ese mismo `pack`, y el artefacto sellado se comparó contra él: **entradas idénticas, ni
sobras ni faltantes**, 45 .mo compilados.

⚠ INSTALADA ≠ ACTIVA, y esto es lo que hace que la receta sirva. El shell sólo carga lo que esté en
`org.gnome.shell enabled-extensions`: sin eso el artefacto sella, el fichero está en la imagen y NO
PASA NADA al arrancar — el mismo cuadro de «sellado ≠ instalado» que este repo ya se comió con
foot, mpv y libnotify, un escalón más abajo. Se resuelve con un override de GSettings, que cambia
el DEFAULT y deja ganar al dconf del usuario que no la quiera.
PROBADO DE VERDAD, no deducido: se compiló el directorio de esquemas del shell con el override
puesto (`glib-compile-schemas`, exit 0 y stderr vacío — que hay que mirar, porque sale 0 aunque
RECHACE un esquema) y después `gsettings get org.gnome.shell enabled-extensions` devolvió
['blur-my-shell@aunetx'].

⚠ TRAMPA ANOTADA PARA LA SEGUNDA: `enabled-extensions` es un ARRAY y el override lo escribe ENTERO.
Dos recetas con su propio override no se suman — gana la que compile última y la otra queda
instalada y muerta, sin error. Cuando llegue la segunda, la lista pasa a un solo sitio.

Y una corrección sobre la licencia, que casi firmo mal: el LICENSE es el texto del GPLv3, y su
apéndice «How to Apply» CONTIENE la frase «either version 3 … or any later version» siempre, así
que grepearla ahí no distingue -only de -or-later (la trampa que la memoria del repo ya tenía
escrita). La evidencia buena es el README del commit pineado: «This program is distributed under
the terms of the GNU General Public License, version 3 or later». El árbol JS no lleva cabecera de
licencia en ningún fichero.

Va de RAÍZ en escritorio-gnome por la lección de `foot` que targets.toml ya aprendió tres veces.
El perfil queda 183/183 listo con 25 raíces, deuda 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCt3ettR4Z7b6wPCBmbvEV

8c2cb10414aed405304c2e896fcbc9f9448a886b · por Sergio · (hace 1 mes) · padre 49e65d147 · ver el árbol en este commit

Delta semántico

Ninguna definición cambió: el cambio es de texto, documentación o datos.

4 archivos · +167 −14

diff --git a/docs/state/build-state-gnome.json b/docs/state/build-state-gnome.json
index 0e94f7ef..83e02025 100644
--- a/docs/state/build-state-gnome.json
+++ b/docs/state/build-state-gnome.json
@@ -1,16 +1,16 @@
 {
  "schema": "hammer-build-state/1",
  "totals": {
-  "recipes": 920,
-  "nodes": 922,
-  "sealed": 920,
+  "recipes": 921,
+  "nodes": 923,
+  "sealed": 921,
   "ajeno": 2
  },
  "by_class": {
   "ajeno": 2,
   "c": 272,
   "go": 362,
-  "gui": 47,
+  "gui": 48,
   "kernel": 6,
   "rust": 233
  },
@@ -21,7 +21,7 @@
    "ajeno": 2
   },
   "incoming-gnome": {
-   "sealed": 63
+   "sealed": 64
   }
  },
  "by_profile": {
@@ -36,9 +36,9 @@
    "sealed": 80
   },
   "escritorio-gnome": {
-   "raices": 24,
-   "clausura": 182,
-   "sealed": 182
+   "raices": 25,
+   "clausura": 183,
+   "sealed": 183
   },
   "escritorio-mirada": {
    "raices": 17,
@@ -5360,7 +5360,7 @@
     "escritorio-kde",
     "escritorio-sway"
    ],
-   "dependientes_total": 103
+   "dependientes_total": 104
   },
   "gh": {
    "iname": "gh",
@@ -5992,7 +5992,7 @@
    "perfiles": [
     "escritorio-gnome"
    ],
-   "dependientes_total": 42
+   "dependientes_total": 43
   },
   "glib-introspected": {
    "iname": "glib-introspected",
@@ -6245,6 +6245,30 @@
    ],
    "dependientes_total": 0
   },
+  "gnome-shell-extension-blur-my-shell": {
+   "iname": "gnome-shell-extension-blur-my-shell",
+   "version": "72",
+   "link": "dynamic",
+   "compiler": "zig-cc",
+   "deps": [
+    "gettext-tiny",
+    "glib",
+    "libffi",
+    "pcre2",
+    "zlib"
+   ],
+   "cls": "gui",
+   "queue": "incoming-gnome",
+   "foreign": false,
+   "hash": "b3:6b39a579c1d58e333c9c1d27875ba015705a340b883638afcde166fd6e6ac9d9",
+   "state": "sealed",
+   "blocked_by": [],
+   "unblocks": 0,
+   "perfiles": [
+    "escritorio-gnome"
+   ],
+   "dependientes_total": 0
+  },
   "gnupg": {
    "iname": "gnupg",
    "version": "2.4.9",
@@ -10065,7 +10089,7 @@
     "escritorio-mirada",
     "escritorio-sway"
    ],
-   "dependientes_total": 109
+   "dependientes_total": 110
   },
   "libffi-shared": {
    "iname": "libffi-shared",
@@ -13824,7 +13848,7 @@
     "escritorio-kde",
     "escritorio-sway"
    ],
-   "dependientes_total": 81
+   "dependientes_total": 82
   },
   "pcre2-shared": {
    "iname": "pcre2-shared",
@@ -18967,7 +18991,7 @@
     "escritorio-mirada",
     "escritorio-sway"
    ],
-   "dependientes_total": 112
+   "dependientes_total": 113
   },
   "zlib-ng": {
    "iname": "zlib-ng",
diff --git a/docs/state/drenaje.json b/docs/state/drenaje.json
index 80c8a1b3..da2cb9ac 100644
--- a/docs/state/drenaje.json
+++ b/docs/state/drenaje.json
@@ -31,7 +31,7 @@
   },
   "escritorio-gnome": {
    "grafo": "docs/state/build-state-gnome.json",
-   "nodos": 182,
+   "nodos": 183,
    "en_deuda": 0,
    "ondas": 0,
    "profundidad": 0,
diff --git a/docs/state/targets.toml b/docs/state/targets.toml
index 0aebd8e5..08451521 100644
--- a/docs/state/targets.toml
+++ b/docs/state/targets.toml
@@ -429,6 +429,20 @@ paquetes = [
   # resuelve en RUNTIME leyendo el `index.theme` del padre, así que el padre tiene que estar
   # INSTALADO. Desde hoy se resuelve contra el corpus (misma receta, mismo hash).
   "adwaita-icon-theme", "hicolor-icon-theme",
+  # ── EXTENSIONES DEL SHELL ────────────────────────────────────────────────────────────────────
+  # ⚠ Añadida el 2026-09-09: esta imagen traía la CÁSCARA de GNOME y ni una extensión. No es un
+  # detalle estético — GNOME manda un shell deliberadamente mínimo y el ecosistema lo completa por
+  # acá; sin ninguna, el escritorio es lo que el proyecto entrega y nadie usa tal cual.
+  # El shell SÍ sabe cargarlas sin nada más: `ui/extensionSystem.js` va en el gresource sin opción
+  # que lo apague y su gschema sellado trae `enabled-extensions`. Lo que faltaba era que hubiera
+  # alguna, y va de RAÍZ por la lección de `foot` que este fichero ya aprendió tres veces.
+  # ⚠ NO hace falta glib-networking ni TLS: eso sólo lo pide BAJARLAS desde extensions.gnome.org
+  # con el descargador del shell. Empaquetada, se instala como cualquier receta.
+  # La receta se construye desde el REPO del autor (tag v72), no desde el zip de EGO: hammer extrae
+  # con `tar -x` y GNU tar no lee zip, y además el zip es un artefacto que construye EGO a partir
+  # de ese mismo repo. El layout instalado se verificó CONTRA ese zip: idéntico, sin sobras ni
+  # faltantes.
+  "gnome-shell-extension-blur-my-shell",
 ]
 
 [perfil.escritorio-cosmic]
diff --git a/recipes/incoming-gnome/gnome-shell-extension-blur-my-shell.toml b/recipes/incoming-gnome/gnome-shell-extension-blur-my-shell.toml
new file mode 100644
index 00000000..2464414c
--- /dev/null
+++ b/recipes/incoming-gnome/gnome-shell-extension-blur-my-shell.toml
@@ -0,0 +1,115 @@
+# blur-my-shell 72 — PRIMERA extensión de GNOME Shell del catálogo, y la que fija el patrón.
+#
+# ══ POR QUÉ EXISTE ═════════════════════════════════════════════════════════════════════════════
+# GNOME manda a propósito una cáscara mínima y el ecosistema la completa con extensiones. Sin
+# ninguna empaquetada, nuestra imagen de GNOME es esa cáscara: el shell SÍ sabe cargarlas
+# —`ui/extensionSystem.js` va en el gresource sin opción que lo apague, y su gschema sellado trae
+# `enabled-extensions`— pero no hay ninguna que cargar.
+#
+# ══ LA FUENTE ES EL REPO DEL AUTOR, NO EL ZIP DE extensions.gnome.org ══════════════════════════
+# EGO publica un `.zip` por versión con URL inmutable, que parecía la fuente obvia. Dos razones
+# para no usarlo:
+#   1. **hammer no lo sabe abrir.** El fetch extrae con `tar -x` (fetch.rs:581) y GNU tar no lee
+#      zip — comprobado: «This does not look like a tar archive». Ninguna receta del corpus usa
+#      .zip. Soportarlo sería tocar el fetcher y sumarle una herramienta al host.
+#   2. **Y aunque lo abriera, no es la fuente.** El zip de EGO es un ARTEFACTO que construye EGO a
+#      partir de este mismo repo. Pinear el zip es pinear el binario de un tercero; pinear el
+#      commit es pinear el código del autor, que es lo que hace el resto del corpus.
+# El tag `v72` es el que EGO sirve para shell 48: verificado preguntándole
+# (`extension-info/?uuid=blur-my-shell@aunetx&shell_version=48` → version 72) y confirmado en el
+# `metadata.json` del propio zip, que declara shell-version ['46','47','48','49','50'].
+# ⚠ Eso hay que preguntarlo por extensión, no asumirlo: nixpkgs va por GNOME 50 y hay extensiones
+# que ya sólo declaran el major nuevo.
+#
+# ══ SE INSTALA A MANO Y NO CON `gnome-extensions pack` ═════════════════════════════════════════
+# El `make build` de upstream llama a `gnome-extensions pack`, que es el CLI `extensions-tool` del
+# propio gnome-shell — y nuestra receta del shell va con `-Dextensions_tool=false`. Encenderlo
+# costaría una receta nueva (gnome-autoar) y re-hashear gnome-shell entero.
+# No hace falta: `pack` sólo arma el zip que después alguien descomprime. Lo que el shell lee es un
+# DIRECTORIO en /usr/share/gnome-shell/extensions/<uuid>/, así que se copia el árbol directamente.
+# El layout no se inventó: se leyó del zip de EGO v72, que es la salida de ese mismo `pack` —
+# `src/*` va a la raíz, `resources/icons`→`icons/`, `resources/ui`→`ui/`, más metadata.json y
+# LICENSE.
+#
+# ⚠ El zip de EGO **no trae `gschemas.compiled`** (verificado): trae el .xml y quien instala
+# compila. Por eso `glib-compile-schemas` va en el install y `glib` en [deps] — sin eso la
+# extensión carga y muere al abrir sus preferencias, que es el fallo que no se ve al sellar.
+name    = "gnome-shell-extension-blur-my-shell"
+version = "72"
+# licencia: el README del commit pineado lo dice con todas las letras — «This program is distributed
+# under the terms of the GNU General Public License, version 3 or later». ⚠ La evidencia NO es el
+# fichero LICENSE: ahí sólo está el texto del GPL, y su apéndice «How to Apply» contiene la frase
+# «either version 3 … or any later version» SIEMPRE, así que grepearla da positivo aunque el
+# proyecto sea -only. Y el árbol JS no lleva cabecera de licencia en ningún fichero (verificado).
+license = "GPL-3.0-or-later"
+
+[source]
+repo   = "https://github.com/aunetx/blur-my-shell"
+commit = "444df605b34529dfab7be77d0f434bf54a6dd4cc"  # tag v72 (ADR 0006: commit fijo, nunca HEAD)
+
+[build]
+compiler = "zig-cc"
+target   = "x86_64-linux-musl"
+link     = "dynamic"
+
+[build.phases]
+# No hay nada que compilar: son JS, XML de esquema y catálogos de traducción.
+configure = "true"
+compile   = "true"
+install = '''
+set -e
+UUID="blur-my-shell@aunetx"
+D="/out/usr/share/gnome-shell/extensions/$UUID"
+mkdir -p "$D"
+
+# 1. El árbol, con la MISMA forma que produce `gnome-extensions pack` (leída del zip de EGO v72).
+cp -r src/. "$D/"
+cp metadata.json LICENSE "$D/"
+cp -r resources/icons "$D/icons"
+cp -r resources/ui    "$D/ui"
+
+# 2. El esquema: se copia el .xml Y se compila. El shell abre las preferencias con
+#    Gio.SettingsSchemaSource.new_from_directory, que necesita el gschemas.compiled.
+mkdir -p "$D/schemas"
+cp schemas/*.gschema.xml "$D/schemas/"
+glib-compile-schemas "$D/schemas"
+
+# 3. Traducciones: un .mo por idioma, nombrado por el UUID (así lo busca el shell).
+for po in po/*.po; do
+  lang="$(basename "$po" .po)"
+  mkdir -p "$D/locale/$lang/LC_MESSAGES"
+  msgfmt -o "$D/locale/$lang/LC_MESSAGES/$UUID.mo" "$po"
+done
+
+# 4. INSTALADA ≠ ACTIVA. El shell sólo carga las extensiones que estén en la clave
+#    `org.gnome.shell enabled-extensions`, así que sin esto el artefacto sella, el fichero está en
+#    la imagen y NO PASA NADA al arrancar — el mismo cuadro de «sellado ≠ instalado» que este repo
+#    ya se comió con foot, mpv y libnotify, un escalón más abajo.
+#    Se hace con un override de GSettings, que cambia el DEFAULT sin tocar la config del usuario
+#    (quien no la quiera la apaga y su dconf gana). El `gnome-start-qemu.sh` corre
+#    `glib-compile-schemas` sobre este directorio en el primer arranque, así que el override entra.
+#
+#    ⚠ TRAMPA PARA LA SEGUNDA EXTENSIÓN: `enabled-extensions` es un ARRAY y esto lo escribe ENTERO.
+#    Si mañana otra receta instala su propio override para la misma clave, no se suman: gana el
+#    fichero que compile último (orden alfabético) y la otra extensión queda instalada y muerta,
+#    sin error. Cuando llegue la segunda, la lista pasa a un solo sitio que las liste a todas.
+mkdir -p /out/usr/share/glib-2.0/schemas
+cat > /out/usr/share/glib-2.0/schemas/60_hammer-extensiones.gschema.override <<OVR
+[org.gnome.shell]
+enabled-extensions=['$UUID']
+OVR
+
+# 5. Guardián barato: si el árbol quedara vacío o sin metadata, el artefacto sellaría igual y el
+#    fallo aparecería recién al arrancar el escritorio (regla 3 de CLAUDE.md — un vacío llega hasta
+#    el final diciendo que todo fue bien).
+test -s "$D/metadata.json"
+test -s "$D/extension.js"
+test -s "$D/schemas/gschemas.compiled"
+grep -q '"48"' "$D/metadata.json"   # falla ruidoso si un bump de versión deja de soportar shell 48
+grep -q "$UUID" /out/usr/share/glib-2.0/schemas/60_hammer-extensiones.gschema.override
+'''
+
+[deps]
+# `glib` por glib-compile-schemas y `gettext-tiny` por msgfmt: las dos son herramientas del
+# sandbox, no librerías que la extensión enlace (no enlaza nada: es JavaScript).
+build = ["glib", "pcre2", "libffi", "zlib", "gettext-tiny"]