> 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…
fix(distro): el .zip SÍ se podía abrir — `libarchive` estaba sellado y sólo lo declaraba KDE
Mi censo marcaba «archivos comprimidos ajenos» 5/5 ausente, con este argumento: «no se puede abrir
un .zip, un .7z ni un .rar — `libzip` es una BIBLIOTECA, no el comando». Cierto para `libzip`, y
**falso como conclusión**: `libarchive` estaba SELLADO desde antes y trae `bsdunzip`, `bsdtar`,
`bsdcpio` y `bsdcat` — declarado únicamente en `escritorio-kde`, así que las otras nueve imágenes no
podían abrir un adjunto por un paquete ya construido.
MEDIDO ejecutándolo, con un zip deflate con subdirectorio, antes de escribir esto:
bsdunzip -o x.zip extrae y conserva el árbol ✓
bsdtar -xf x.zip ídem ✓
bsdtar -a -cf x.zip … CREA un zip que python zipfile abre y verifica ✓
⇒ `libarchive` entra a `cli`, o sea a los cuatro escritorios y a `servidor`. Clausura 10 de 10
verificada.
Y el censo gana `CUBIERTOS`, que es lo simétrico de `MUROS`: el renglón falta POR NOMBRE y la
capacidad está, medida. **No absuelve el hueco** —un script ajeno que invoque `unzip` sigue
fallando, y el censo hace bien en contarlo, porque mide equivalencia por nombre— pero cambia el
presupuesto de «no hay camino» a «faltan los alias», que es otra cosa y mucho más barata. Es la
misma figura que `agetty` cubriendo a `getty`. Sólo entra lo verificado EJECUTANDO, no lo que
upstream promete: 7z y rar quedan sin medir y sin afirmar.
De paso, lo medido sobre los métodos de entrada —el siguiente hueco de la lista— por si alguien lo
retoma: **no hay muro estructural.** `mirada-compositor` registra `TextInputManagerState` y
`InputMethodManagerState` (`setup.rs:600-602`), o sea `zwp_text_input_v3` y `zwp_input_method_v2`.
Y fcitx5 con `ENABLE_X11=Off` + `ENABLE_ENCHANT=Off` se quita cinco deps (xcb-imdkit,
xcb-util-keysyms, xcb-util-wm, libxkbfile, enchant2). Lo que queda bloqueando son dos promociones de
cola a corpus —`extra-cmake-modules` e `iso-codes`, hoy en `incoming-kde`, y una receta del corpus
no alcanza una cola hermana— más los motores por idioma, que son recetas aparte. Es una campaña de
media docena, no una receta, y está scopeada.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
diff --git a/docs/state/distro-huecos.json b/docs/state/distro-huecos.json
index fba81ad4..81346a66 100644
--- a/docs/state/distro-huecos.json
+++ b/docs/state/distro-huecos.json
@@ -3,31 +3,33 @@
{
"categoria": "escritura del mundo",
"faltan": [
- "noto-fonts-cjk",
- "noto-fonts-emoji",
- "noto-fonts",
"noto-fonts-extra"
],
"items": [
{
- "estado": "falta",
+ "estado": "tiene-y-viaja",
"nombre": "noto-fonts-cjk",
"parientes": []
},
{
- "estado": "falta",
+ "estado": "tiene-y-viaja",
"nombre": "noto-fonts-emoji",
"parientes": []
},
{
- "estado": "falta",
+ "estado": "tiene-y-viaja",
"nombre": "noto-fonts",
"parientes": []
},
{
"estado": "falta",
"nombre": "noto-fonts-extra",
- "parientes": []
+ "parientes": [
+ "noto-fonts",
+ "noto-fonts-cjk",
+ "noto-fonts-emoji"
+ ],
+ "pista": "nombre parecido en el catálogo (verificar, NO es equivalencia)"
}
],
"porque": "las únicas fuentes del corpus son dejavu y su nerd: sin estas, la distro muestra cuadraditos en chino, japonés, coreano, árabe, hindi, tailandés y emoji"
@@ -404,11 +406,15 @@
],
"items": [
{
+ "cubierto_por": "libarchive",
+ "cubierto_porque": "bsdunzip -o x.zip extrae y conserva el árbol — probado con un zip deflate con subdirectorio el 2026-10-19",
"estado": "falta",
"nombre": "unzip",
"parientes": []
},
{
+ "cubierto_por": "libarchive",
+ "cubierto_porque": "bsdtar -a -cf x.zip … crea un zip que python zipfile lee y verifica — probado el 2026-10-19",
"estado": "falta",
"nombre": "zip",
"parientes": []
@@ -429,7 +435,7 @@
"parientes": []
}
],
- "porque": "no se puede abrir un .zip, un .7z ni un .rar — un adjunto cualquiera queda cerrado. `libzip` es una BIBLIOTECA, no el comando"
+ "porque": "⚠ EL ARGUMENTO DE ESTA FILA ERA FALSO Y LO MEDÍ DESPUÉS: decía «no se puede abrir un .zip» porque `libzip` es una biblioteca y no el comando. Cierto para libzip — y falso como conclusión: `libarchive` estaba SELLADO y trae `bsdunzip`/`bsdtar`, verificados con un zip real en lectura Y escritura. Se declaró en `cli` el 2026-10-19. Lo que falta son los ALIAS (`unzip`, `zip`) para que un script ajeno que los invoque no falle, y 7z/rar sin medir"
},
{
"categoria": "imprimir de verdad",
@@ -1365,12 +1371,12 @@
"porque": "decisión abierta: son herramientas de operar OTRA cosa"
}
],
- "en_alguna_imagen": 601,
- "recetas_alcanzables": 1375,
+ "en_alguna_imagen": 604,
+ "recetas_alcanzables": 1378,
"resumen": {
- "falta": 152,
+ "falta": 149,
"tiene-sin-viajar": 3,
- "tiene-y-viaja": 15
+ "tiene-y-viaja": 18
},
"schema": "takana-censo-distro/1"
}
diff --git a/docs/state/targets.toml b/docs/state/targets.toml
index 0b81645f..fd5911f6 100644
--- a/docs/state/targets.toml
+++ b/docs/state/targets.toml
@@ -407,6 +407,25 @@ paquetes = [
# con razón también, porque mira el store LOCAL. Las dos fuentes eran ciertas y medían cosas
# distintas, y yo leí la contradicción como «falta construirlo».
"typst",
+ # ── ABRIR UN .ZIP, QUE CREÍAMOS QUE NO SE PODÍA (2026-10-19) ─────────────────────────────────
+ # `censo-distro.py` marcaba «archivos comprimidos ajenos» 5/5 ausente, con el argumento de que
+ # `libzip` es una BIBLIOTECA y no el comando. Cierto para `libzip` — y FALSO como conclusión:
+ # **`libarchive` estaba sellado y trae `bsdunzip`, `bsdtar`, `bsdcpio`, `bsdcat`**, y sólo se
+ # declaraba en `escritorio-kde`. O sea que las otras nueve imágenes no podían abrir un adjunto
+ # por un paquete que ya estaba construido.
+ #
+ # MEDIDO con un zip de verdad (deflate, con subdirectorio) antes de escribir esto:
+ # bsdunzip -o x.zip extrae y conserva el árbol ✓
+ # bsdtar -xf x.zip ídem ✓
+ # bsdtar -a -cf x.zip ... CREA un zip que python zipfile lee ✓
+ #
+ # ⚠ Los binarios NO se llaman `unzip` ni `zip`, así que un script ajeno que invoque esos nombres
+ # sigue fallando y el censo sigue contándolos como huecos — hace bien: mide equivalencia por
+ # NOMBRE. Lo que cambia es que la CAPACIDAD está, y eso baja el hueco de «no hay camino» a
+ # «faltan los alias». Es la misma figura que `agetty` cubriendo a `getty` con otro nombre.
+ # ⚠ No se midió 7z ni rar: libarchive los soporta en lectura según upstream, pero sin un fichero
+ # de prueba no lo afirmo.
+ "libarchive",
]
[perfil.escritorio-mirada]
diff --git a/scripts/censo-distro.py b/scripts/censo-distro.py
index 35be0906..5c460879 100755
--- a/scripts/censo-distro.py
+++ b/scripts/censo-distro.py
@@ -83,8 +83,11 @@ CHECKLIST = {
# ── CAPACIDADES ENTERAS SIN NINGÚN CAMINO ───────────────────────────────────────────────────
'archivos comprimidos ajenos': (
- 'no se puede abrir un .zip, un .7z ni un .rar — un adjunto cualquiera queda cerrado. '
- '`libzip` es una BIBLIOTECA, no el comando',
+ '⚠ EL ARGUMENTO DE ESTA FILA ERA FALSO Y LO MEDÍ DESPUÉS: decía «no se puede abrir un .zip» '
+ 'porque `libzip` es una biblioteca y no el comando. Cierto para libzip — y falso como '
+ 'conclusión: `libarchive` estaba SELLADO y trae `bsdunzip`/`bsdtar`, verificados con un zip '
+ 'real en lectura Y escritura. Se declaró en `cli` el 2026-10-19. Lo que falta son los ALIAS '
+ '(`unzip`, `zip`) para que un script ajeno que los invoque no falle, y 7z/rar sin medir',
['unzip', 'zip', 'p7zip', '7zip', 'unrar']),
'imprimir de verdad': ('cups solo no imprime: los filtros y los drivers son otro paquete',
['cups', 'cups-filters', 'ghostscript', 'gutenprint', 'hplip']),
@@ -156,6 +159,18 @@ CHECKLIST = {
}
+# ── CAPACIDAD YA CUBIERTA CON OTRO NOMBRE ──────────────────────────────────────────────────────
+# Lo simétrico de `MUROS`: el renglón falta POR NOMBRE y la capacidad SÍ está, medida. No absuelve
+# el hueco —un script que invoque `unzip` sigue fallando, y el censo hace bien en contarlo— pero
+# cambia el presupuesto de «no hay camino» a «faltan los alias», que es otra cosa y mucho más
+# barata. Sólo entra lo verificado ejecutando, no lo que upstream promete.
+CUBIERTOS = {
+ 'unzip': ('libarchive', 'bsdunzip -o x.zip extrae y conserva el árbol — probado con un zip '
+ 'deflate con subdirectorio el 2026-10-19'),
+ 'zip': ('libarchive', 'bsdtar -a -cf x.zip … crea un zip que python zipfile lee y verifica '
+ '— probado el 2026-10-19'),
+}
+
# ── POR QUÉ ESTÁ CADA HUECO: receta ausente ≠ capacidad ausente ─────────────────────────────────
# «Falta la receta» y «la distro no publica eso» son dos cosas con presupuestos distintos, y el
# censo mentía por omisión al contarlas juntas. Sólo entran acá los muros MEDIDOS, con el dato que
@@ -222,6 +237,8 @@ def main():
i['pista'] = 'nombre parecido en el catálogo (verificar, NO es equivalencia)'
if i['nombre'] in MUROS:
i['muro'], i['muro_porque'] = MUROS[i['nombre']]
+ if i['nombre'] in CUBIERTOS:
+ i['cubierto_por'], i['cubierto_porque'] = CUBIERTOS[i['nombre']]
print('== qué le falta a la distro para usarse (checklist de JUICIO, estado MEDIDO) ==')
print(' recetas alcanzables: %d · de ellas en alguna imagen: %d'
@@ -237,6 +254,11 @@ def main():
print(' — PISTAS: falta, pero hay un nombre parecido (verificar; NO es equivalencia):')
for n, p in rev:
print(' %-20s ~ %s' % (n, ', '.join(p)))
+ cub = [(i['nombre'], i['cubierto_por']) for f in filas for i in f['items'] if i.get('cubierto_por')]
+ if cub:
+ print(' — CAPACIDAD YA CUBIERTA con otro nombre (falta el alias, no el camino):')
+ for n, q in cub:
+ print(' %-20s lo hace %s' % (n, q))
con_muro = [(i['nombre'], i['muro']) for f in filas for i in f['items'] if i.get('muro')]
if con_muro:
print(' — MUROS MEDIDOS (no es que falte la receta: la distro no publica eso):')