Commit Graph
2678 Commits
Author SHA1 Message Date
Sergio af548b8555 estado: cosecha granja 2026-09-13T20:03:48Z — avance del árbol KDE 2026-09-13 20:03:48 +00:00
SergioandClaude Opus 5 1fc9de6a01 espejar-repos: mostrar el error de gh y cortar ante el límite de la API
Corrida real contra gioser: los 21 repos fallaron al crearse y el guión dijo «no se pudo crear» A
SECAS, porque mandaba el stderr de `gh` a /dev/null. La causa era el LÍMITE DE LA API DE GITHUB
agotado —que se resuelve esperando— y sin el mensaje eso parecía un problema de permisos, de nombre o
del propio guión: hubo que reproducirlo a mano para enterarse de algo que la herramienta ya sabía.

Dos arreglos:

· El error de `gh` se muestra, recortado a su primera línea.
· Ante «rate limit» se CORTA en el primero: los 20 restantes van a fallar igual y cada intento gasta
  cuota. Dice a qué hora se repone (leído de `gh api rate_limit`) y recuerda que reintentar es
  seguro, porque el guión es idempotente.

No quedó estado parcial de la corrida fallida: el `pushurl` se agrega DESPUÉS de crear el repo, así
que los 21 clones siguen con su remoto original intacto. Verificado en tres de ellos.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RomoxEGZUhaT4pob1QSX5x
2026-09-13 20:03:17 +00:00
Sergio df1230d2a5 vigía de subcomandos: separar el hueco CONOCIDO del NUEVO — «44 inertes» todos los días no se lee
El vigía escribe `docs/state/subcomandos.txt` en cada ciclo del latido desde ayer, y decía
`TOTAL: 44 herramientas selladas que no se pueden invocar` a secas. Un número grande, constante y sin
explicación al lado entrena a saltearse el informe — y entonces el hueco NUEVO, que es el único que
pide acción, pasa desapercibido entre el ruido del viejo. Es la misma trampa que ya tienen resuelta
`static-audit.sh` (deuda decidida) y `--auditar-raices`.

Los 44 son todos del mismo hueco, y ahora el informe dice cuál y por qué:

    • falta el binario `cargo` (el toolchain de Rust)
      PENDIENTE DE DECISIÓN, no olvido. `cargo`/`rustc` viven hoy en el LAB y en la cadena de
      selfhost (mrustc→1.91.1), no como receta del catálogo. Empaquetarlos es una decisión de
      TOOLCHAIN —qué Rust publica la distro, y desde qué cadena— no trabajo de granja.

    TOTAL: 44 … (44 de hueco CONOCIDO, 0 NUEVAS)   ⇒ exit 0

⚠ **«PENDIENTE DE DECISIÓN» y no «deuda decidida»**, que es distinto: en el audit estático las tres
mentiras tienen un arreglo evaluado y descartado por su coste; acá nadie decidió nada todavía. La
etiqueta tiene que decir cuál de las dos cosas es, o dentro de tres meses se lee como cerrada.

El código de salida ahora refleja sólo los huecos NUEVOS. Probado con los dos controles: sacando
`cargo` de la tabla salen `44 NUEVAS` y exit 1; restaurándola, `0 NUEVAS` y exit 0.

⚠ Y el primer intento de ese control estaba MAL y daba verde: escribí `CONOCIDOS = {} or {…}` para
vaciar la tabla, y en Python `{}` es falsy ⇒ la expresión devuelve el segundo dict y la tabla seguía
llena. El control «pasaba» sin probar nada. Rehecho renombrando la clave.
2026-09-13 20:02:32 +00:00
SergioandClaude Opus 5 713128f26d mudanza: guión que le da copia FUERA a los 25 repos que sólo existen en gioser
Hace por un árbol entero lo que `scripts/espejo-setup.sh` hace por takana: `pushurl` doble sobre
`origin`, de modo que cualquier `git push origin` que ya exista empiece a espejar sin tocar ningún
script. Crea el repo en GitHub como PRIVADO.

Cuatro decisiones:

· **Por defecto NO hace nada**: imprime qué haría; hay que pedirlo con `--apply`. Crear repos y
  empujar código a un servicio externo no es algo que deba pasar por correr un script sin leerlo.
· **Varios clones del MISMO origen van a UN repo remoto.** En gioser hay cinco de
  `tawasuyu/tawasuyu`; cinco repos distintos multiplican la confusión y empujarlos todos al mismo
  `main` los haría chocar. El primario empuja normal; un secundario sólo se empuja —bajo
  `refs/heads/clon/<nombre>/*`— SI aporta historia propia, y eso se comprueba preguntándole al
  primario si ya tiene esos objetos (`cat-file -e`). Medido: los cinco tienen CERO commits que no
  estén en su remoto, así que los cuatro secundarios se saltan y se dice por qué.
· **Sólo agrega; nunca toca el `fetch` de `origin`**, que sigue siendo el canónico.
· **Lo sucio no viaja, y se dice.** Un espejo guarda historia commiteada, no el árbol de trabajo, y
  `tawasuyu` tiene 980 ficheros sin commitear. Creer que está a salvo cuando la mitad del trabajo no
  está commiteado es justo el fallo que este guión existe para evitar.

⚠ Y un criterio que escribí mal y corregí midiendo: el primario era «el clon con más commits
alcanzables», y contra los cinco de tawasuyu dio un EMPATE EXACTO en 9343 — `rev-list --all` cuenta
las refs de `origin`, que los cinco comparten, así que la métrica estaba dominada por lo común y no
medía nada. El desempate quedaba en el orden del `find` y elegía `tw-deploy` (HEAD del 6/9) sobre
`tawasuyu` (del 12/9), que es el que se está trabajando. Ahora manda la fecha del HEAD en ISO, que
distingue y ordena como texto.

Ensayo sobre gioser: 25 repos sin copia fuera ⇒ 21 a espejar, 4 saltados por redundantes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RomoxEGZUhaT4pob1QSX5x
2026-09-13 19:54:12 +00:00
Sergio 8600ba8888 qdrant: reproduce contra el protobuf de zig — 907/907 sellado, deuda 0
Tras devolver protobuf y abseil a `zig-cc`, qdrant cayó a deuda y se reconstruyó en el worker:
2 ficheros, sólo `usr/`, 70 M, `qdrant 1.19.1`. La limpieza del `/out/src` —el DESTDIR global que
heredaba el `make install` anidado de protobuf-src— aguanta el cambio de dep. REPRODUCE bit a bit.

El corpus queda en 907/907 sellado con deuda 0.
2026-09-13 19:51:43 +00:00
Sergio 057091381e estado: cosecha granja 2026-09-13T19:32:21Z — avance del árbol KDE 2026-09-13 19:32:21 +00:00
Sergio 261f1c2a61 estado: cosecha granja 2026-09-13T19:02:47Z — avance del árbol KDE 2026-09-13 19:02:47 +00:00
Sergio 2215716047 estado: cosecha granja 2026-09-13T18:32:19Z — avance del árbol KDE 2026-09-13 18:32:19 +00:00
Sergio 219594ece3 estado: cosecha granja 2026-09-13T18:02:41Z — avance del árbol KDE 2026-09-13 18:02:41 +00:00
Sergio 95a3152586 estado: cosecha granja 2026-09-13T17:32:17Z — avance del árbol KDE 2026-09-13 17:32:17 +00:00
Sergio 2cca6c3630 estado: cosecha granja 2026-09-13T17:02:08Z — avance del árbol KDE 2026-09-13 17:02:08 +00:00
Sergio 6ac8566719 estado: cosecha granja 2026-09-13T16:32:15Z — avance del árbol KDE 2026-09-13 16:32:15 +00:00
Sergio 8f507c4a67 estado: cosecha granja 2026-09-13T16:02:35Z — avance del árbol KDE 2026-09-13 16:02:35 +00:00
Sergio 7766c063ea estado: cosecha granja 2026-09-13T15:32:23Z — avance del árbol KDE 2026-09-13 15:32:23 +00:00
Sergio e56efe6c3b estado: cosecha granja 2026-09-13T15:02:37Z — avance del árbol KDE 2026-09-13 15:02:37 +00:00
Sergio 7547beb00a estado: cosecha granja 2026-09-13T14:32:15Z — avance del árbol KDE 2026-09-13 14:32:15 +00:00
Sergio 16ec87fe25 estado: cosecha granja 2026-09-13T14:02:34Z — avance del árbol KDE 2026-09-13 14:02:34 +00:00
Sergio 3851b2fd40 estado: cosecha granja 2026-09-13T13:32:16Z — avance del árbol KDE 2026-09-13 13:32:16 +00:00
Sergio f299f061b0 estado: cosecha granja 2026-09-13T13:02:35Z — avance del árbol KDE 2026-09-13 13:02:35 +00:00
Sergio 0687a4fdf6 estado: cosecha granja 2026-09-13T12:32:19Z — avance del árbol KDE 2026-09-13 12:32:19 +00:00
Sergio f35a30cf8b estado: cosecha granja 2026-09-13T12:02:59Z — avance del árbol KDE 2026-09-13 12:03:00 +00:00
Sergio 13bc744b94 estado: cosecha granja 2026-09-13T11:32:31Z — avance del árbol KDE 2026-09-13 11:32:31 +00:00
Sergio 2208e4fe09 estado: cosecha granja 2026-09-13T11:02:11Z — avance del árbol KDE 2026-09-13 11:02:11 +00:00
Sergio f54adf119b estado: cosecha granja 2026-09-13T10:32:24Z — avance del árbol KDE 2026-09-13 10:32:24 +00:00
Sergio 2074d359c5 estado: cosecha granja 2026-09-13T10:02:33Z — avance del árbol KDE 2026-09-13 10:02:33 +00:00
Sergio 184be3529e estado: cosecha granja 2026-09-13T09:32:01Z — avance del árbol KDE 2026-09-13 09:32:01 +00:00
Sergio ce875b141a estado: cosecha granja 2026-09-13T09:02:41Z — avance del árbol KDE 2026-09-13 09:02:41 +00:00
Sergio ff84f791f1 estado: cosecha granja 2026-09-13T08:31:55Z — avance del árbol KDE 2026-09-13 08:31:55 +00:00
Sergio 5832a0090a estado: cosecha granja 2026-09-13T08:02:39Z — avance del árbol KDE 2026-09-13 08:02:39 +00:00
Sergio b59edab197 estado: cosecha granja 2026-09-13T07:32:17Z — avance del árbol KDE 2026-09-13 07:32:17 +00:00
Sergio 6734d3eda5 estado: cosecha granja 2026-09-13T07:02:22Z — avance del árbol KDE 2026-09-13 07:02:22 +00:00
Sergio f1402036aa estado: cosecha granja 2026-09-13T06:31:56Z — avance del árbol KDE 2026-09-13 06:31:56 +00:00
Sergio df5976baad estado: cosecha granja 2026-09-13T06:02:02Z — avance del árbol KDE 2026-09-13 06:02:02 +00:00
Sergio 00c9d5afaf estado: cosecha granja 2026-09-13T05:31:54Z — avance del árbol KDE 2026-09-13 05:31:54 +00:00
Sergio 948fa6a284 estado: cosecha granja 2026-09-13T05:02:08Z — avance del árbol KDE 2026-09-13 05:02:08 +00:00
Sergio 460c68e100 estado: cosecha granja 2026-09-13T04:32:22Z — avance del árbol KDE 2026-09-13 04:32:22 +00:00
Sergio 2b86b8d0c3 estado: cosecha granja 2026-09-13T04:02:26Z — avance del árbol KDE 2026-09-13 04:02:27 +00:00
Sergio e28140c5b0 estado: cosecha granja 2026-09-13T03:32:09Z — avance del árbol KDE 2026-09-13 03:32:09 +00:00
Sergio eab169976e estado: cosecha granja 2026-09-13T03:02:27Z — avance del árbol KDE 2026-09-13 03:02:27 +00:00
Sergio 7ecf9d1d58 estado: cosecha granja 2026-09-13T02:31:54Z — avance del árbol KDE 2026-09-13 02:31:54 +00:00
Sergio f39a2eafc3 estado: cosecha granja 2026-09-13T02:02:41Z — avance del árbol KDE 2026-09-13 02:02:41 +00:00
Sergio 4b38af8f3f networkmanager al corpus CON WiFi y con nmcli — y los perfiles que no tenían gestor de red
networkmanager  b3:c36414ece23e322ef007d0acc7ce6f65b8b822ae55c38b38c9afa4b3eb340adb  (52 MB)

Arreglo del segundo hueco del barrido: `networkmanager` figuraba SÓLO en escritorio-kde, y desde
GNOME, COSMIC o sway no se alcanza (cola hermana). Pero promover la receta de KDE tal cual habría
sido peor que no hacerlo, y sólo se vio mirando el ARTEFACTO:

  · `-Dwifi=false`  ⇒ un gestor de red que no maneja interfaces inalámbricas. Allá es correcto
    (esa receta existe para dar libnm.so a plasma-nm y nada más); acá habría puesto en tres
    imágenes un demonio que arranca, dibuja el applet y no lista una sola red.
  · sin `nmcli`     ⇒ ni una herramienta con la que manejarlo. En sway eso es la diferencia entre
    tener red y no tenerla.

La variante del corpus cambia tres cosas, y la tercera hizo falta MEDIRLA:
  1. `-Dwifi=true`. Habla nl80211 por libnl (ya era dep) y delega el handshake WPA2 en
     `wpa_supplicant`, que desde hoy está en perfil.base ⇒ va también en [deps] runtime.
  2. `readline` en [deps] build.
  3. `-Dnmcli=true -Dreadline=libreadline`. Con sólo la dep, nmcli NO se construyó: `-Dnmcli` vale
     true de fábrica pero `-Dreadline` es un COMBO que por defecto va en `auto`, y sin decirle
     dónde mirar resolvió a «none» ⇒ meson apagó el CLI EN SILENCIO. Comprobado sobre el store.

Y `readline-shared` en runtime, cazado con provee.py sobre las NEEDED del binario: nmcli sale con
`NEEDED libreadline.so.8` y la readline canónica del corpus es sólo .a. La dep de BUILD y la de
RUNTIME son artefactos distintos — tercer caso del día tras cmus y bluez. No mueve el hash.

⚠ Se queda `-Dcrypto=null`, y es una limitación real escrita en la receta: sin cripto no valida
802.1X / WPA-Enterprise (el WiFi de una oficina). WPA2-PSK funciona porque ése lo hace el
supplicant. Encender nss o gnutls arrastra dos cadenas enormes: unidad de trabajo aparte.

── targets.toml ────────────────────────────────────────────────────────────────────────────────
  escritorio-gnome, escritorio-cosmic, escritorio-sway  += networkmanager  (+ servicio)
  escritorio-kde, escritorio-sway                       += wireplumber     (+ servicio)

⚠ networkmanager NO se declara en escritorio-kde: allá plasma-nm ya arrastra la variante de la
cola, y dos NetworkManager distintos en la misma ruta es la enfermedad de las dos glib. Que la de
KDE vaya sin WiFi es deuda del frente KDE, y queda escrita donde toca.
2026-09-13 01:38:50 +00:00
Sergio 72b9f54c19 recetas: libtool y libndp al corpus — promoción GRATIS, hash idéntico desde las dos partes
libtool  b3:5c09bff565b24c0a8edb306e0d4ca4e5e8e2a8c8e4a2b8ac047c8816b6883dcb
  libndp   b3:51be8f4336084b181e94a7f4a4178b87602cd39e975c2ddbd3125e7b782b9189

Entran como escalón para promover `networkmanager` al corpus (el barrido de perfiles midió que
GNOME, COSMIC y sway no alcanzaban ningún gestor de red: la receta vivía sólo en incoming-kde, que
desde ellos es una cola hermana).

La comprobación que decide una promoción NO es `diff` de las recetas sino `takana hash`, porque la
resolución de deps es hermano→padre y dos ficheros idénticos en colas distintas PUEDEN sellar
distinto. Acá sellan IGUAL desde las dos partes ⇒ misma dirección del store ⇒ las dos entraron por
CACHE-HIT, cero builds y cero rebuilds. (networkmanager, en cambio, sí difiere: resuelve varias
deps contra el corpus en vez de contra la cola de KDE.)

Las copias de `incoming-kde` se DEJAN donde están, a propósito: sellan en la misma dirección, así
que no hay dos artefactos ni colisión de nombre, y retirar ficheros de la cola que otro agente está
moliendo ahora mismo no es algo que este barrido tenga que hacer. Jubilarlas es trabajo del frente
KDE, el día que le convenga.
2026-09-13 01:37:26 +00:00
Sergio 0cd3e62822 libglvnd: sólo despacho de GL — muere la colisión de libEGL. Y obs-studio llevaba meses sin construir
libglvnd    b3:e27d3b2833a6aa6a6b4a4caad5ef2121e7be31a3c7ae59d0db22b01d696ffc99
  obs-studio  b3:29d95ddf50ef79692b48cae493758def564202ef81eba236b6cb279757621403

── libglvnd: se apagan egl, gles1, gles2 y headers ─────────────────────────────────────────────
La receta se escribió para la campaña completa —glvnd toma libEGL y mesa pasa a ser vendor detrás—
y la campaña NO SE HIZO: las tres mesa siguen con -Dglvnd=false. El resultado, medido en
/mnt/cosecha/escritorios/kde-rootfs ya hidratado, era el cuadro que la propia receta anunciaba:

  /usr/lib/libEGL.so.1 -> libEGL.so.1.0.0   1.440.624 B   (mesa: el driver)
  /usr/lib/libEGL.so.1.1.0                    323.144 B   (glvnd: despacho, HUÉRFANO)

Dos libEGL.so.1 distintos en la MISMA ruta, más libGLESv2.so.2 y los headers GL/, EGL/ y GLES2/
duplicados y con BYTES DISTINTOS (gl.h: 79.877 vs 80.393). Quién gana depende del orden de
hidratación y nada lo guarda.

Y no hacía falta: OBS, que es la razón de que la receta exista, NO usa glvnd en runtime.
libobs-opengl.so sale con NEEDED libEGL.so.1 y nada más, y sus indefinidos son todos egl* —ni un
gl[A-Z] sin resolver— o sea que su glad resuelve por eglGetProcAddress contra la EGL de mesa. Lo
único que glvnd le da es satisfacer el OpenGL::GL de CMake AL ENLAZAR.

Ahora sella libGLdispatch.so.0 + libOpenGL.so.0 + opengl.pc y nada más: CERO ficheros en común con
mesa. Radio medido: 1 dependiente.

⚠ Esto quita el DAÑO, no cierra el muro: libOpenGL.so.0 enlaza y en runtime sigue sin haber vendor
(no hay libEGL_mesa.so.0 ni egl_vendor.d). Cerrarlo es re-sellar las TRES mesa con -Dglvnd=true en
un movimiento, y el precio está medido: `yupana radio mesa` = 148 directos, 154 transitivos, 153
sellados que caen a deuda, las CINCO imágenes. Decisión de distro, no arreglo de paso.

── obs-studio: el cache-hit tapaba una regresión ───────────────────────────────────────────────
Al forzar su rebuild, el configure murió pidiendo `qrcodegencpp`, que no es receta de ninguna cola.
La causa NO era libglvnd. La receta dice «[source] de takana NO clona submódulos ⇒ sus directorios
llegan VACÍOS» y por eso hacía `touch plugins/obs-websocket/CMakeLists.txt`. Esa premisa dejó de
ser cierta: los submódulos YA se materializan, así que `touch` no vacía nada —sólo toca la mtime de
un fichero que existe— y el CMakeLists de verdad entra pidiendo su dependencia.

Corregido a `mkdir -p` + `: >` (truncar), que funciona con submódulos y sin ellos: la receta deja
de depender de una premisa que puede cambiarle bajo los pies. Construye y sella en el hub.
2026-09-13 01:36:36 +00:00
Sergio 424363fbdc receta: wireplumber al corpus — KDE y sway tenían pipewire y no encaminaban nada
wireplumber  b3:bd5471f00f5cbd229fcb252ceced41c35547725733708426bf7a42ea3e39a7bd

Arreglo del hueco que destapó el barrido de servicios. `pipewire` está en los cuatro escritorios y
arranca, pero se construyó con `-Dsession-managers=[]`: sin gestor de sesión no hay política de qué
es entrada, qué es salida ni qué se enlaza con qué, y el sink que ve la aplicación es `auto_null`
—el nodo de descarte—. Audio que parece vivo y no suena.

wireplumber existía en `incoming-gnome` y en `incoming-cosmic`, y desde KDE o sway NO SE ALCANZA:
una receta resuelve sibling-first y después el catálogo PADRE, nunca una cola hermana. Por eso la
copia va al corpus, que es el único sitio desde el que las cuatro imágenes la ven — el mismo
argumento por el que viven acá `mpv` y `atuq`.

Medido antes de copiar, no supuesto:
- `yupana radio wireplumber` = **0 dependientes** ⇒ esta copia no fuerza un solo rebuild ajeno.
- Las tres variantes sellan DISTINTO (gnome b3:71afcef4…, cosmic b3:7ad25184…, corpus b3:bd5471f0…).
  No es la enfermedad de las dos glib: ninguna imagen hidrata dos wireplumber, cada una toma la
  suya. Es la figura de las tres `pulseaudio`, que también se quedaron a propósito.
- Consolidar las tres en una es el trabajo siguiente y NO se hace de paso: el método está probado
  (es lo que se hizo con pipewire el 2026-09-03) pero GNOME y COSMIC están validados y cambiarles
  el artefacto de audio sin probarlos sería pagar con su imagen una limpieza que no urge.
2026-09-13 01:36:36 +00:00
Sergio 47ec0d9559 estado: cosecha granja 2026-09-13T01:33:30Z — avance del árbol KDE 2026-09-13 01:33:30 +00:00
Sergio 741a5d767c receta: bluez estático de verdad — el audit del cron vuelve a verde
bluez  b3:6036ab1585ce2af12e7596edd16709d1baa906f8c0ca816aed44957a038fbd66
  11/11 ejecutables `statically linked` · `bluetoothctl: 5.87` corre · 31 ficheros (no se perdió nada)

El sello de ayer decía `static` y salía con los ONCE ejecutables dinámicos; el audit del cron lo
marcó esa misma noche (docs/state/static-audit.txt, 2026-09-12T21:04Z) y dejó el veredicto global
en rojo: 715 honestas y las dos nuevas mintiendo. Acá se puede ser estático de verdad —el artefacto
NO trae ningún plugin .so, o sea que nadie hace dlopen (a diferencia de cmus)— así que el arreglo
es el arreglo, no una re-declaración.

Dos mitades, y la segunda no se ve venir:

1. `LDFLAGS=-all-static` en compile **Y** en install: bluez enlaza con libtool, que lee el `-static`
   del lab como «preferí los .a de libtool» y además RELINKEA al instalar.
2. `LIBS=-lncursesw`. Con -all-static el enlace de bluetoothctl corta con
   `undefined symbol: tgoto ... in archive /usr/lib/libreadline.a`: readline usa termcap y su
   readline.pc lo declara en `Requires.private: ncurses`, que **sólo se expande con
   `pkg-config --static`**. El configure de bluez busca readline con AC_CHECK_LIB, no con
   pkg-config ⇒ la transitiva nunca entra. En dinámico no se nota: la resuelve el loader.

Y se QUITA el `runtime = ["readline-shared"]` que se había añadido horas antes: hacía falta
mientras bluetoothctl era dinámico, y con el estático pasó a ser la mentira simétrica —declarar una
dep que no se usa—. No mueve el hash (las deps de runtime no entran en hash_inputs).
2026-09-13 01:15:40 +00:00
Sergio 35f83748f9 receta: cmus va link = "dynamic" — carga sus formatos por dlopen
cmus  b3:9a540d4270674ec74679dffbeed11d98796c51801663bde88e87affc041213ab

La primera versión decía `static` y era MENTIRA MEDIBLE: el audit del cron
(docs/state/static-audit.txt, medido 2026-09-12T21:04Z) la marcó — «dice static, es DINÁMICO →
libncursesw.so.6 libc.so» — y dejó el veredicto global en rojo. 715 honestas y las dos nuevas de
ayer mintiendo.

Pero el arreglo NO es hacerlo estático: **cmus no puede serlo**. El artefacto trae cinco plugins
—usr/lib/cmus/ip/{wav,cue,ffmpeg}.so y usr/lib/cmus/op/{alsa,oss}.so— y los abre por dlopen. Un
binario estático no puede abrirlos: quedaría un reproductor que no reproduce nada. Es la misma
razón por la que `sway` va dinámico (dlopea los drivers DRI de mesa).

⇒ `dynamic` es la declaración CORRECTA, no una concesión. Una declaración que el build ignora es
peor que no declarar, porque las herramientas río abajo la creen.

La prueba que decide, y cuesta dos segundos:
    find store/<hash>-<nombre> -name '*.so' | wc -l
  0 plugins → se puede y se debe ser estático.   N plugins → dynamic es lo honesto.

Comprobadas las NEEDED de los plugins contra el corpus con scripts/provee.py, que es la otra mitad:
libasound.so.2 (alsa-lib), libavformat/libavcodec/libswresample .so (ffmpeg) y libncursesw.so.6
(ncurses-shared) los publica el corpus ⇒ no hay NEEDED colgante. Las tres primeras llegan por
[deps] build; ncurses-shared va declarada en runtime desde el commit anterior.
2026-09-13 01:14:18 +00:00
Sergio 584cc128a8 docs: adenda al plan de apps — el censo, el muro de GL revisado y la respuesta a «¿Electron?»
Tres preguntas del usuario, contestadas midiendo, y dos de las mediciones CORRIGEN cosas que este
mismo fichero afirmaba.

1. CENSO: de ~50 apps muy usadas el catálogo tiene 9, y CINCO de las nueve son de KDE (o sea que
   llegan a una de las cuatro imágenes).

2. ⚠ CORRECCIÓN al «tercer defecto del método». Este documento dice, con fecha 2026-09-03, que
   ninguna cola publica libGL.so ni gl.pc. Dejó de ser cierto AL DÍA SIGUIENTE: recipes/libglvnd.toml
   es del 2026-09-04 y `provee.py --desde corpus opengl` da ✓ (libOpenGL.so.0 + opengl.pc). Y la
   corrección trae su propia corrección: la campaña quedó A MEDIAS. Las tres mesa siguen con
   -Dglvnd=false, no hay libEGL_mesa.so.0 ni egl_vendor.d, y en el rootfs KDE hidratado conviven DOS
   libEGL.so.1 distintos (mesa 1.440.624 B gana el symlink; el de glvnd, 323.144 B, queda huérfano).
   OBS —la razón de escribir libglvnd— NO la usa en runtime: libobs-opengl.so sale con NEEDED
   libEGL.so.1 y ni un gl[A-Z] indefinido, o sea que su glad resuelve por eglGetProcAddress.
   ⇒ el `opengl ✓` es verdad DE ENLACE. El muro pasó de «no enlaza» a «enlaza y no corre».

   Corolario: darktable estaba MAL clasificada como caso de GL. Su UI es GTK3+cairo; su muro es la
   cola de deps (lensfun, libgphoto2, openexr, imath, libraw, osm-gps-map, portmidi + cuatro que
   sólo viven en colas). Blender sí es el caso de GL.

3. ELECTRON: `grep -rni electron docs/ recipes/` da CERO. Nunca estuvo planeado. Y no existe un
   «Electron con base Firefox» porque Gecko no tiene API de embebido desde XULRunner (SDD 26 §1) —
   pero eso es exactamente lo que es atuq, y ya está: artefacto derivado + chrome propio +
   extensiones + host de native messaging en Rust. Falta un modo SSB, que es más barato que UN port.

   GenOffice concretamente: Apache-2.0 (salvo ee/), acepta endpoints OpenAI-compatible locales ⇒ la
   mitad de IA es una línea de config contra el llama-cpp que YA viaja en los cuatro escritorios. La
   mitad de runtime es qorpa. ⚠ Y el muro real es el MODELO: Qwen2.5-1.5B no sostiene IA agéntica
   sobre un .xlsx.

4. QUÉ REHACER, con criterio escrito: sólo cuando el bloqueo es estructural Y el valor vive en un
   protocolo o formato abierto. Pasan tres: el shell de apps sobre atuq, una bóveda de contraseñas
   (la mitad cara —la integración con el navegador— ya está construida), y un cliente Matrix si
   fractal no construye. Thunderbird es el más desaprovechado de la lista de EMPAQUETAR: es Gecko.
2026-09-13 01:10:00 +00:00
Sergio cbecd0ba12 docs: el barrido de perfiles y servicios, con su método y la política que faltaba escribir
Deja escrito lo que el barrido midió y, sobre todo, CÓMO se midió, para que el recuento se pueda
repetir en vez de re-derivar.

Lo que aporta que no estaba en ningún lado:

1. **La política «catálogo ≠ imagen».** El repo ya la aplicaba de hecho y no la había escrito, y sin
   ella «620 hojas sin perfil» se lee como deuda. No lo es: 529 son volcado crudo del importador y
   355 son herramientas Go de nube. Una receta sellada y no declarada es CATÁLOGO — se instala por
   nombre. Se vuelve deuda sólo cuando lo que falta es una CAPACIDAD.

2. **El método en tres preguntas encadenadas**, y por qué el orden importa: ¿está en algún perfil?
   → ¿podría llegar por clausura ajena (`dependientes_total>0`)? → ¿fue curada alguna vez (la
   cabecera «PUNTO DE PARTIDA» del importador)? Las hojas son el hueco; las librerías no.

3. **El triaje completo de las 91 hojas trabajadas a mano**, en seis clases que suman 91 exactas.
   Incluye las que NO se declaran de oficio y por qué: `openrc` compite con arje-zero, `uutils` y
   coreutils/grep/findutils compiten con los applets de busybox, `waterfox` es un segundo Gecko,
   y valkey/opensmtpd/step-ca/qdrant definen QUÉ CLASE de servidor es el perfil `servidor`.

4. **Dos hallazgos que no eran el objetivo del barrido:**
   - `networkmanager` existe SÓLO en incoming-kde ⇒ GNOME, COSMIC y sway no lo alcanzan. Con
     wpa_supplicant la WiFi se destraba, pero se configura a mano y el indicador de red del
     escritorio no tiene con qué hablar.
   - `ia-modelo-embeddings` no está en ningún perfil: hay motor (llama-cpp) y hay chat
     (ia-modelo-chat) en los cuatro escritorios, y NO hay búsqueda por significado. La mitad
     semántica del §6.3 de atuq no viaja.

5. **Una trampa del instrumento**, que casi hace escribir mal las listas de servicios:
   `scripts/targets.py <perfil>` imprime las RAÍCES, no la clausura. Cruzar los [[service]] contra
   esa salida dejaba fuera a pipewire y colord en GNOME, que sí están en la imagen. La clausura la
   da el campo `perfiles` de los build-state*.json.
2026-09-13 01:08:17 +00:00