Commit Graph
1676 Commits
Author SHA1 Message Date
Sergio c719fe211a estado: cascada de kirigami reconstruida — 39/39 al hash nuevo, cero fallos
El arreglo del no-determinismo de kirigami movió su ArtifactHash (41eea38e… →
a72b1626…) y con él el de todo lo que cuelga: 37 dependientes directos, 39
transitivos (entran `frameworkintegration` y `plasma5support` por vía indirecta).

Reconstruidas las 39 en orden topológico y con UN solo `flock -o` para toda la
tanda. Comprobado aparte del log: para las 39 existe `store/<hash-de-hoy>-<nombre>`.
Las gordas: kwin 3027s, plasma-workspace 1958s, okular 810s, kirigami-addons 816s.

⚠ A mitad de tanda, `kirigami-addons` y `kdf` murieron con «No space left on
device» — y es otra vez la trampa de siempre: NO eran recetas rotas. El disco de
`/mnt/vvv` estaba al 100%. Las dos reconstruyen bien con sitio libre.

Dos cosas se arreglaron a raíz de eso:
  · `poda-fuentes.sh` con su suelo de 24 h liberaba CERO, porque los 30 árboles
    eran todos de hoy — la lección de `cache-ci-no-envejece` otra vez: un guardián
    calibrado a una escala que el dato nunca alcanza no protege. Con `--horas 1`
    y luego `--horas 0` se recuperaron 14 G.
  · la tanda ahora poda el árbol de CADA receta al terminarla (sólo el suyo: las
    deps son compartidas, borrarlas en vuelo es el ADR 0012). Con eso
    `work/sources` se mantuvo en 54-71 M durante el resto de la cascada en vez de
    crecer sin freno.

El `never: 1` que aparece en el grafo KDE es `minga`, una receta nueva de otro
agente, sin perfil y ajena a esta cascada.
2026-09-14 20:41:34 +00:00
Sergio 5257726d64 estado: cosecha granja 2026-09-14T20:32:59Z — avance del árbol KDE 2026-09-14 20:33:00 +00:00
SergioandClaude Opus 5 70a76aedcb ⚠ la comprobación que faltaba: DOS commits se habían quedado en el gitea viejo
Comparados los 845 refs de los dos lados, repo por repo. Dos diferencias: una esperada
(`sergio/takana` main, el nuevo por delante con los commits del cutover — fast-forward verificado)
y una que NO: `tawasuyu/tawasuyu` tenía en el viejo `b69008eb` (freebsd) y `02a9535f` (shuma,
**19:48**), quince minutos DESPUÉS del snapshot final.

Por qué: el gitea viejo había resucitado por OpenRC y un cliente con el DNS cacheado (el CNAME
anterior tenía TTL 600) lo empujó a gioser aunque el autoritativo ya dijera la caja. Hacían falta
las dos condiciones a la vez.

Recuperados con un push del ref exacto desde el clon local; la UI del nuevo ya muestra `02a9535f`.
Segunda pasada: 845/845 y una sola diferencia, la esperada. En metadatos, `action` tenía tres filas
posteriores al snapshot (los mismos dos repos) y CERO issues/comentarios/releases.

El orden para el resto de la mudanza: bajar el TTL ANTES del corte · apagar el origen de verdad (los
dos supervisores) ANTES de tocar el DNS · comparar refs después, siempre · y dejar el origen apagado
un rato antes de borrarlo, precisamente para poder comparar.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Tf9T4vGzsMoT7eS8YzMFn
2026-09-14 20:13:08 +00:00
SergioandClaude Opus 5 dc0927a028 cerrar el intermedio: el gitea viejo apagado DE VERDAD, el :22 cerrado y los datos respaldados
⚠ EL GITEA VIEJO HABÍA VUELTO A ARRANCAR. Media hora después del corte, gioser servía otra vez en
:3002. `arjectl list-units` ya no lo mostraba —el stop de arje seguía en pie— y el proceso tenía
ppid ≠ 1: lo levantó **OpenRC**, que lo tenía en el runlevel `default`. Dos supervisores para el
mismo servicio, y parar uno no para el otro. Antes del corte pasaba lo contrario: `rc-service stop`
decía «already stopped» con el proceso vivo, porque quien lo tenía era arje. La pregunta no es
«¿está parado?» sino «¿QUIÉN lo tiene?», y hay que responderla dos veces.
Arreglado con `rc-update del gitea default` + `rc-service gitea stop`.

El origen deja de servir git: los tres bloques salen del Caddyfile de gioser (con respaldo,
`validate` y `reload`) y quedan 16; control inmediato de que no rompí lo demás —`sergio.gioser.net`
y `hifas.gioser.net` siguen en 200—. `gitea.gioser.net` pasa a A → la caja.

El `:22` cerrado sin perder el acceso: administración en **22022**, git por SSH en **2345**, y el 22
en `Connection refused`. La secuencia es la única segura: añadir el puerto nuevo → reiniciar →
ENTRAR por él → sólo entonces quitar el 22. Verificado en ese orden, y el clone por 2345 sigue.

🧨 Y lo que apareció al mirar: **los datos del gitea nunca estuvieron respaldados**.
`respaldo-storagebox.sh` cubre el STORE de artefactos, no `/var/lib/gitea` — los 44 repos vivían en
una sola copia. La mudanza no lo empeoró, pero lo vuelve urgente porque gioser se borra. Hecho hoy
desde la caja: snapshot de la DB con el servicio vivo + rsync a `u647150:gitea/` (1,7 G).

⚠ Al Storage Box se entra por el puerto **23**: el 22 da SFTP restringido y contesta «Permission
denied (publickey,password)», que se lee como «no tengo la clave» teniendo la clave perfecta.

Pendiente: que ese respaldo sea periódico — un renglón en el cron de la caja.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Tf9T4vGzsMoT7eS8YzMFn
2026-09-14 20:03:50 +00:00
Sergio 920d276b45 estado: cosecha granja 2026-09-14T20:03:29Z — avance del árbol KDE 2026-09-14 20:03:29 +00:00
SergioandClaude Opus 5 69526768b7 CUTOVER: el gitea sirve desde la caja nueva — TLS válido, HTTPS y SSH, supervisado por arje
`git.gioser.net` y `git.tawasuyu.net` responden **200 con TLS válido desde 2.29.29.217**, `git clone`
funciona por HTTPS **y** por SSH:2345, y `gitea` + `caddy` corren supervisados por `arje-zero`. El
gitea de gioser está parado. Es el primer servicio real que deja la máquina que se va a borrar.

Mudanza INCREMENTAL: los DNS de gioser son casi todos `CNAME → www`, así que mover `www` habría
mudado quince dominios cuyos backends siguen allá. Se convirtió sólo `git` (las dos zonas) de CNAME
a A propio con TTL 60 — reversible en un minuto.

Cinco cosas que sólo se aprenden haciéndolo:

· **Parar el origen no es `rc-service gitea stop`**: dice «already stopped» con el proceso vivo, y
  matarlo no alcanza — lo revive arje-zero, que lo tiene como card `openrc-gitea` con Restart y
  **9001 reinicios** en el contador. Se paró con `arjectl stop openrc-gitea` (el arjectl que
  construimos hoy, hablando con el arje de gioser), y para eso hubo que extraer su card del genesis
  y escribirla en `cards.d` — que es justo el hueco del §6.12.
· **El token de `hcloud` también gestiona el DNS** (Cloud API unificada, `/v1/zones`); la API vieja
  `dns.hetzner.com/api/v1` redirige a la consola web. Y un `PUT` sobre el rrset no puede cambiar el
  TIPO: hay que DELETE del CNAME y POST del A.
· **ACME falló primero contra gioser** (502) porque el challenge salió antes de que propagara el
  DNS. Con el DNS al día, `arjectl restart caddy` → certificate obtained successfully.
· **La identidad SSH se muda con el servicio**: `REMOTE HOST IDENTIFICATION HAS CHANGED` hasta que
  se copiaron las claves de host de gioser a la caja. Así los clones existentes no notan nada; el
  precio es limpiar el known_hosts propio del `:22` de administración.
· El `sshd` del producto escucha sólo en `:22` ⇒ el git por SSH necesitó `Port 2345` y que el
  usuario `gitea` tenga shell real (su authorized_keys fuerza `command="gitea serv …"`).

`caddy` gana su `[[service]]` (con guarda del Caddyfile, HOME propio para los certificados de ACME
—o cada reinicio pediría certificados nuevos y se comería el límite de emisión— y la nota de por qué
corre como root) y el perfil lo arranca.

Consecuencia para la granja: las 23 recetas que clonan por `https://git.tawasuyu.net/…` **ya apuntan
a la caja**. Comprobado: el worker resuelve 2.29.29.217 y `git ls-remote` responde.

Revertir, si hiciera falta: `arjectl start openrc-gitea` en gioser y los dos `git` de vuelta a CNAME.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Tf9T4vGzsMoT7eS8YzMFn
2026-09-14 19:53:09 +00:00
Sergio e5fefa35d2 estado: cosecha granja 2026-09-14T19:33:51Z — avance del árbol KDE 2026-09-14 19:33:51 +00:00
Sergio 2238913a4e estado: cosecha granja 2026-09-14T19:03:35Z — avance del árbol KDE 2026-09-14 19:03:35 +00:00
SergioandClaude Opus 5 4d77d232d3 la mudanza sin terceros: las fuentes de tawasuyu por HTTPS público, y el orden del cutover
Tres cosas, y las tres quitan vueltas.

1. NO HACE FALTA NINGUNA CREDENCIAL EN EL WORKER, Y TAMPOCO UN USUARIO NUEVO

`tawasuyu/tawasuyu` y `sergio/takana` son repos PÚBLICOS en el gitea. Las 23 recetas que apuntaban a
`gitea@git.tawasuyu.net` (SSH, que exige la clave que es el SSH de todo) pasan a
`https://git.tawasuyu.net/…`. La URL es locator y NO entra en `hash_inputs` (ADR 0013): hecho con
control antes/después, **ningún ArtifactHash se movió**. Medido en el worker: `git clone --mirror
--filter=blob:none` + `git archive` extrae el árbol (155 M) **sin una sola credencial**.

Un usuario propio en gitea sólo haría falta para un repo PRIVADO; hoy ninguna receta usa uno. Si
mañana hace falta, es una cuenta de máquina con acceso al repo que toque — nunca la clave personal.

De paso, tres recetas decían «HUB-ONLY: el worker secretless recibe Connection refused». Ya no es
cierto y el comentario decía lo contrario de lo que pasa: corregido en las tres.

2. LA COPIA FUERA LA DA LA MUDANZA, NO GITHUB (decisión del usuario)

El «paso 1: espejar los 26 repos» deja de ser el paso 1. En cuanto el gitea vive en la caja nueva,
esos repos dejan de existir sólo en la máquina que se borra — que es lo que el paso pedía. El
objetivo es dejar de pagar dos máquinas, no sumar una dependencia. `espejar-repos.sh` queda como
herramienta disponible.

3. EL §9 REESCRITO: qué está hecho, qué falta y en qué orden

Hecho y cerrado: la caja arranca takana puro · store/grafos/granja/respaldo · repo firmado · la
imagen del perfil servidor con gitea sirviendo 200 supervisado por arje · `arjectl` · y el ensayo con
los datos REALES de gioser corriendo sobre takana.

Falta, en orden: actualizar la caja a la imagen nueva (`upgrade`, no `dd`) → mudar los datos del
gitea (`.backup` + rsync, con el origen parado en el corte) → caddy con los 6 dominios vivos → DNS →
verificar desde fuera con un clone real → el resto de servicios del censo → borrar gioser con las 8
puertas en verde.

Bloqueantes con su tamaño: `git` sellado sin `remote-http` (afecta a clonar DESDE una caja takana,
no al gitea que sirve; re-sella una raíz de `base`) y la puerta 5, que no bloquea la mudanza.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Tf9T4vGzsMoT7eS8YzMFn
2026-09-14 18:59:31 +00:00
Sergio 5b98d1b2bf atuq: no era el perfil — son DOS SALIDAS, y el «3 de 13» medía la cámara
Dos cosas antes de la medición: el MOZ_LOG de las que pintan y las que no termina IDÉNTICO (las dos
commitean WaylandBufferSHM de 1280x696), y el cruce de las 15 corridas está confundido — las 13 de
«perfil del usuario» salieron todas con VGA=1.

`screendump` de QMP fotografía UN dispositivo. Con VGA=1 hay dos, y hasta ahora se miraba uno. Con
`id=` en cada uno y capturando los dos en cada toma, en la misma corrida y el mismo instante:

    +312s  ██ PRIMERA PINTURA — 704456 px EN vga0
           gpu0 = 962675 px de fondo + panel y dock (el escritorio, SIN navegador)
           vga0 = 703766 px magenta                 (la ventana, con la página)

⇒ cosmic-comp maneja las DOS salidas y la ventana cae en una u otra. «Pinta 3 de 13» era cuántas
veces cayó en la pantalla que yo fotografiaba: una tasa de mi cámara, no del producto. El §6.10.ter
tiene la misma explicación (aquel arranque también traía `drm: card0 card1`).

Queda en pie, ya sin confundido: el navegador arranca, mapea y commitea SIEMPRE; cuando la ventana
está en la pantalla que se mira, se ve entre +184 y +312 s; el perfil no era la causa y cosmic-comp
nesteado tampoco.

⚠ Tercera vez en el día con la misma forma: un ✗ de una captura de UNA pantalla no dice «la ventana
no está», dice «no está en ESA» — igual que `mapped 1` no probaba que se viera. El estado anota ahora
en qué pantalla apareció y cuántas se fotografiaron, y el vigía NO cuenta las ciegas: las nombra.
2026-09-14 18:57:00 +00:00
Sergio 26dd2233dc estado: cosecha granja 2026-09-14T18:33:41Z — avance del árbol KDE 2026-09-14 18:33:41 +00:00
Sergio 49b2842ddb atuq: la TASA — pinta 3 de 13 con el perfil del usuario, y cuando pinta siempre a ~200 s
Diez corridas idénticas con `scripts/cosmic/tasa-primera-pintura.sh` (--as-user, VGA=1, ventana 480 s,
captura cada 30 s), más las cinco anteriores, todas anotadas en docs/state/primera-pintura.json:

    perfil del usuario     3 de 13 pintaron   184, 199, 204 s
    perfil nuevo en tmpfs  2 de 2             197, 197 s

Dos cosas que la tasa dice y una anécdota no podía: cuando pinta, pinta SIEMPRE en la misma ventana
(184…204 s) y nunca a los 300, 400 ni 900 ⇒ no es una cola larga, son DOS REGÍMENES —o sale a los
~200 s o no sale—; y con el perfil del usuario falla ~3 de cada 4, mientras que con perfil nuevo en
tmpfs no falló (2 de 2, pocas corridas para afirmar que nunca, suficientes para saber dónde mirar:
qué hace el primer arranque del perfil que el perfil ya hecho no hace).

⚠ Condición de la medida, parte del número: las diez salieron con el anfitrión a load ~10 (tanda de
KDE de otro agente + una VM de otra sesión, en 4 cores). El número es un PISO, no una constante.

⚠ Y una trampa del arnés medida en las corridas 8–10: con esa carga el guest tarda más de 420 s en
llegar al shell y los `esperar` vencen. No las invalida —se verificó una por una que el navegador se
lanzó y dejó su MOZ_LOG de 1200–5000 líneas— pero una corrida abortada de verdad se ve casi igual:
por eso el guion cuenta las abortadas APARTE en vez de sumarlas a los fallos.
2026-09-14 18:27:29 +00:00
SergioandClaude Opus 5 390fdf2dcb ensayo con los DATOS REALES de gioser: su gitea corriendo en takana — y el git de la distro no clona por HTTP
Sin tocar gioser (todo lectura) y en la VM desechable. Dentro de la VM: `<title>GioSer Gitea: Git
with a cup of tea</title>`, 200, `/explore/repos` listando los repos de verdad (sergio/takana,
tawasuyu/agora, card, chasqui, cosmos, khipu, llimphi…) y el clon de uno de ellos con 478 commits y
HEAD correcto.

El snapshot de la DB se saca EN CALIENTE y sale consistente: `sqlite3 gitea.db ".backup …"` con el
servidor vivo, 1,5 s para 314 M, `integrity_check` ok, 44 filas en `repository`. Copiar el fichero a
pelo mientras el servidor escribe es justo lo que no hay que hacer.

Tres detalles que sólo aparecen con los datos puestos:

· **El uid del origen no es el del destino.** Los ficheros llegan con su uid NUMÉRICO y el gitea de
  gioser es 969, no el 916 que declaraba la receta. O se chownean 2 G —lento, y hay que acordarse—
  o gitea no puede leer sus datos, y eso no falla al copiar: falla al arrancar. La receta pasa a
  969, alineada con el origen. El ArtifactHash no se mueve (`[[user]]` está fuera de hash_inputs).
· El `app.ini` de gioser escucha en `127.0.0.1:3002` porque allá caddy hace de proxy: la caja sirve,
  pero sólo desde dentro. `HTTP_ADDR`/`ROOT_URL` son adaptación, no copiado.
· 🧨 **El `git` de la distro no puede clonar por HTTP**: `git: 'remote-http' is not a git command`.
  Medido sobre el artefacto sellado: `git-core/` trae `git-remote-ext`, `git-remote-fd` y
  `git-http-backend` (el lado SERVIDOR) y no `git-remote-http`; `strings` da 0 referencias a libcurl
  pese a que `curl` está en `[deps] build`. No se había notado porque en el hub se usa el git de
  Artix, no el sellado. Un hub nuevo no podría clonar el repo por HTTPS. Re-sellar `git` es raíz de
  `perfil.base` ⇒ unidad propia.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Tf9T4vGzsMoT7eS8YzMFn
2026-09-14 18:26:54 +00:00
Sergio 4456b65829 estado: cosecha granja 2026-09-14T18:04:26Z — avance del árbol KDE 2026-09-14 18:04:26 +00:00
SergioandClaude Opus 5 fd09ca77b0 arjectl en la imagen: relanzar en caliente — y el genesis NO alcanzaba para eso
El servicio que falla y agota su backoff sólo se podía recuperar reiniciando la máquina entera.
Ya no. Y no hubo que escribir nada: **el cliente existía en tawasuyu y el crate se llama `arje-ctl`**
(el binario, `arjectl`). Buscarlo por `arjectl` no lo encontraba, y de ahí salió mi conclusión falsa
de que había que implementarlo — el protocolo ya traía ListEntes, SpawnCardFromDisk,
StopCardFromDisk, KillEnte y EnteStatus.

`recipes/arjectl.toml` lo construye del MISMO commit que `arje-zero` (98db584f), y no por comodidad:
el bus es un protocolo entre dos binarios y un cliente de otro árbol puede conectar sin entenderse
con el init. Publica sólo `arjectl`; el crate también produce un `systemctl` de camuflaje que acá no
se instala — en una distro sin systemd, ese nombre en el PATH invita a escribir runbooks con el
verbo ajeno.

⚠ EL HUECO QUE SÓLO SE VE USÁNDOLO: el genesis de la seed dice qué arranca AL BOOT, pero
`start`/`restart` usan `SpawnCardFromDisk`, que lee `/etc/arje/cards.d/<label>.json` — y el armado
no lo escribía:

    $ arjectl start gitea
    Error: arje-zero rechazó: card gitea: No such file or directory
           (buscada en /etc/arje/cards.d/gitea.json)

Son dos preguntas distintas —qué arranca solo, y qué se puede encarnar a pedido— y arje las responde
desde sitios distintos. `inyectar-cards.py` escribe ahora los dos árboles, y en `cards.d` escribe
TODAS las cards, no sólo las nuevas: `sshd` viene del product-rootfs y tampoco era relanzable.

Medido con la VM arrancada UNA sola vez: la imagen trae `cards.d/{gitea,sshd}.json` · `list-units`
da PID/CPU/MEM/HILOS/reinicios · poner el `app.ini` + `arjectl start gitea` ⇒ **GET / 200 sin
reiniciar** (uptime 6 min) · `arjectl restart gitea` cambia el PID (118 → 192) y sigue en 200.

⚠ Y un aviso que costó un HTTP intermitente: **`arjectl start` sobre un Ente YA VIVO lo DUPLICA** —
`SpawnCardFromDisk` no deduplica por label y arje le da un ULID nuevo. En gitea el síntoma fue
`unable to lock level db … resource temporarily unavailable` y un `[F]`: dos servidores peleando por
el mismo estado. Para relanzar se usa `restart`, o se mira `list-units` antes. Un `start` idempotente
es trabajo de arje, no de esta imagen.

⚠ Deuda anotada, no barrida: `arjectl` va en `perfil.servidor` porque este frente es el que lo pagó.
TODA imagen de takana corre arje-zero como PID 1 y ninguna se puede operar sin él ⇒ el argumento
para subirlo a `base` es fuerte, y es una línea. Se deja como decisión.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Tf9T4vGzsMoT7eS8YzMFn
2026-09-14 17:59:11 +00:00
Sergio 8054119429 estado: cosecha granja 2026-09-14T17:34:29Z — avance del árbol KDE 2026-09-14 17:34:30 +00:00
SergioandClaude Opus 5 9cb80fcfd6 SDD 28 §6.11: la imagen del perfil servidor con gitea ARRANCA y sirve — 200 desde fuera de la VM
PID 1 = arje-zero · gitea encarnado por él (ppid=1) · corriendo como uid=916, la cuenta que declara
`[[user]]` · escuchando en :3000 · `GET /` devuelve 200 con <title>takana git</title> · y su
gitea.db creada por él mismo. Primer servicio de PAQUETE que arranca en una imagen de takana: los
que había venían horneados en el bootstrap.

La cadena entera, eslabón por eslabón: [[user]] → /etc/passwd de la imagen · [[service]] →
service-cards → genesis de la seed → arje encarna → setuidgid → sirve.

Queda escrito lo que NO está probado: el app.ini, el usuario del sitio y los datos se pusieron A MANO
en la VM para llegar al 200 — es justo lo que la mudanza tiene que traer de gioser. Y la imagen no
trae `arjectl`: tras poner la config hubo que reiniciar, porque el backoff de restart se agota y no
hay forma de relanzar un ente en caliente.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Tf9T4vGzsMoT7eS8YzMFn
2026-09-14 17:13:28 +00:00
Sergio 446c209fd2 estado: cosecha granja 2026-09-14T17:04:07Z — avance del árbol KDE 2026-09-14 17:04:08 +00:00
Sergio 44b3624de6 kirigami: arreglado el no-determinismo — eran DOS causas, y ahora reproduce bit a bit
Antes: dos reconstrucciones con las mismas entradas y el mismo lab daban artefactos
distintos. Ahora: `why-differs` da 464 entradas idénticas · 0 divergen.

Hash: 41eea38e… → a72b1626… (arrastra 37 dependientes directos, 39 transitivos).

── CAUSA 1: el AOT de QML compilaba un conjunto DISTINTO de funciones cada vez ─────────
`libKirigamiTemplates.so` cambiaba de tamaño (5.737.344 vs 5.795.072) y difería en 177
símbolos locales, todos `QmlCacheGeneratedCode…__invoke` y concentrados en CUATRO ficheros:
InlineMessage, LinkButton, NavigationTabBar y Badge.

Y esos cuatro son justo los que importan módulos QML HERMANOS del propio proyecto
(`org.kde.kirigami.platform`, `.primitives`, `.controls`). `qmlcachegen` sólo compila a AOT
lo que puede resolver de tipos, y los tipos del hermano salen de su `.qmltypes`, que produce
otro objetivo del mismo build. `src/templates/CMakeLists.txt` no declara `DEPENDENCIES`
ninguna ⇒ con ninja en paralelo es una CARRERA.

Control que sostiene el diagnóstico: `Chip` y `Heading`, del mismo directorio, no divergen —
y `kirigami-addons` y `kquickcharts`, que también llevan QML, reproducen. No es «QML es
no-determinista».

Arreglo: `-j1` en el compile. Orden topológico fijo ⇒ el cachegen ve siempre lo mismo.
NO es throttling (eso va por nice/taskset justamente para no re-hashear): es corrección, y
el re-hash es el precio que se paga a propósito.

Descartadas, con motivo: `-DQT_QML_NO_CACHEGEN=ON` apaga también el bytecode precompilado
(coste de arranque en el escritorio); `--only-bytecode` sería lo quirúrgico pero
`QT_QMLCACHEGEN_ARGUMENTS` es propiedad de objetivo y NO es INHERITED, así que no hay forma
de ponerla desde la línea de órdenes.

── CAUSA 2: el .tar.bz2 de plantillas se armaba sin orden ──────────────────────────────
`kde_package_app_templates` de ECM tiene camino reproducible —`--sort=name --mtime=@
SOURCE_DATE_EPOCH --numeric-owner --owner=0 --group=0`— pero detrás de `if(GNU_TAR_FOUND)`,
que exige que `tar --version` diga «GNU tar». El rootfs del lab es Alpine: `tar` es BUSYBOX
⇒ caía al respaldo `cmake -E tar cvfj`, que ni ordena ni normaliza. El orden lo ponía readdir.

Arreglo: `tar` (GNU tar 1.35, ya en el corpus) entra en `[deps] build`.

Comprobado mirando el artefacto, no deducido:

    drwxr-xr-x 0/0  1970-01-01 00:00 ./
    -rw-r--r-- 0/0  1970-01-01 00:00 ./CMakeLists.txt
    -rw-r--r-- 0/0  1970-01-01 00:00 ./LICENSES/BSD-3-Clause.txt

owner 0/0, mtime al epoch (SOURCE_DATE_EPOCH=1 lo fija el sandbox) y la lista ORDENADA.
2026-09-14 16:40:35 +00:00
Sergio 45f7bdda45 estado: cosecha granja 2026-09-14T16:33:58Z — avance del árbol KDE 2026-09-14 16:33:58 +00:00
Sergio 9ceed7bbbe estado: cosecha granja 2026-09-14T16:03:24Z — avance del árbol KDE 2026-09-14 16:03:24 +00:00
Sergio c14db82263 atuq: el tiempo de primera pintura, en el vigía de la imagen — y es 3 de 5, no un número
`scripts/cosmic/atuq-en-imagen.py` ya no contesta «pinta / no pinta» sino CUÁNTO TARDA: mide cada
captura, imprime `+Ns ██ PRIMERA PINTURA`, acepta `--budget` (def. 420 s) y `--until-paint`, y sale
≠0 si no pintó o si se pasó del presupuesto. El magenta se cuenta CON TOLERANCIA porque `cosmic-idle`
atenúa la pantalla al 46 % a los ~+590 s y un contador por color exacto lo lee como «desapareció».

El número se publica en `docs/state/primera-pintura.json` y `scripts/vigia-imagen.py` lo informa como
sexto dato, marcado como «no lo mide este vigía» (arrancar la imagen son ~15 min sin KVM). Se ACUMULA
una entrada por corrida, no se pisa, y el vigía informa la tasa:

    ⚠ pintaron 3 de 5 corridas · primera pintura +197…+204s

⚠ Y eso corrige lo que publiqué hace una hora. Con cinco corridas sobre la MISMA imagen: pintó en
tres (+197, +197, +204 s) y NO pintó en dos —una con 900 s de observación—, siendo la 4 y la 5 el
mismo comando. El fallo es INTERMITENTE: ni «nunca pinta» ni «sólo tardaba».

El argumento que me llevó a «tarda» era el MOZ_LOG (`mapped 1` + «has buffer» + WaylandBufferSHM
commiteado). La corrida 5 lo refutó: commiteaba cuadros desde ≤+377 s con la pantalla vacía a los
900 s. Que el cliente se crea visible NO es evidencia de que se vea; la evidencia es el píxel. Queda
escrito en el vigía, al lado de la tasa, para que no se vuelva a usar como prueba.

De paso, las flags nuevas nacen en inglés (CLAUDE.md §4): --as-user, --wait, --budget, --until-paint,
--only-cosmic; los mensajes siguen en castellano.
2026-09-14 16:02:27 +00:00
SergioandClaude Opus 5 d611f8577d [[user]] en la receta: la otra mitad del SDD 30 — un demonio que no corre como root necesita cuenta
El SDD 30 sacó las Cards de una constante de Rust y las puso en la receta. Los USUARIOS se quedaron
donde estaban las Cards: `/etc/passwd` de la imagen es `takana_bootstrap::PRODUCT_PASSWD`, un literal
con `root` y `sshd`, y añadir un tercero era editar Rust y recompilar takana.

No es simetría por elegancia, es un servicio que no arranca: `gitea` se niega a correr como root, su
Card hace `setuidgid gitea`, y sin la cuenta arranca, muere y reintenta para siempre con un log que
dice `unknown user` — no «a la imagen le falta una cuenta».

    [[user]]
    name = "gitea"
    uid  = 916
    home = "/var/lib/gitea"

**El uid se declara, no se asigna**, por la misma razón que el ULID de la Card: un «primero libre a
partir de 1000» hace que dos imágenes del mismo perfil salgan con dueños distintos y el rootfs deje
de reproducir SIN QUE NADA FALLE — los ficheros se ven iguales y `ls -l` dice otro número. Fuera de
`hash_inputs`, medido: el hash de gitea no se movió (`b3:391a613e…` antes y después).

`takana users <recetas…> [--merge <rootfs>]` es el gemelo de `service-cards`, y fusiona **por clave,
no por línea entera** — componer dos veces no duplica, y `grep -q` de la línea completa no serviría
porque la misma cuenta con otro GECOS se leería como nueva. Tres decisiones con su control:

· Una cuenta ya presente con OTRA línea es CONFLICTO y no se pisa: sale ≠0. Pisarla es cambiarle el
  uid a ficheros que ya son de alguien, y eso se descubre dentro de la VM.
· Se planea todo y sólo entonces se escribe. Fichero a fichero, un conflicto en `passwd` dejaba el
  `group` ya escrito: media cuenta es peor que ninguna, porque parece que está. Comprobado con el
  caso exacto — `group` sin la cuenta, `passwd` con otro uid — y los DOS ficheros quedan intactos.
· Un `passwd` ausente es un error, no un fichero a crear: crearlo dejaría una imagen SIN `root`.

La validación rechaza lo que rompe tarde: `root`/`sshd`/`nobody` y sus uids, uid fuera de
100..=65533, `home` relativo y un `:` en cualquier campo — que partiría la línea y fallaría lejos.

Y `--user-paths` NO es `--service-paths` con otro nombre: aquél lista los servicios HABILITADOS,
éste los paquetes INSTALADOS que declaran cuentas. `postgres` instalado y sin levantar necesita su
usuario igual, porque los ficheros de la imagen ya son suyos.

`scripts/servidor-image.sh` lo aplica entre hidratar el perfil y sellar la imagen, y aborta si hay
conflicto: un rootfs con el uid equivocado produce ficheros de un dueño que no existe.

Verde: 6 tests del módulo, core 234, cli 88, bootstrap 42, `targets.py --selftest` 7/7.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Tf9T4vGzsMoT7eS8YzMFn
2026-09-14 15:39:52 +00:00
Sergio 1b3af538d3 estado: cosecha granja 2026-09-14T15:34:25Z — avance del árbol KDE 2026-09-14 15:34:25 +00:00
Sergio 8156207c40 atuq: el número — el navegador TARDA entre 2 y 5 minutos, no se queda sin pintar
`--como-usuario` (atuq pelado, con SU perfil por defecto en la ext4 del disco) reprodujo el síntoma:
300 s de observación, seis capturas, ninguna con ventana. Pero el MOZ_LOG dice otra cosa 30 s después
de la última captura: `mapped 1`, «marked as visible & has buffer», `WaylandBufferSHM` de 1280x696
commiteado y `mIsFullyOccluded 0` — lo mismo que hace cuando pinta.

Segunda corrida, 900 s y captura cada 60 s:

    +66s  +137s  fondo liso
    +204s        699458 px magenta — la página, pintada
    +268s…+526s  703766 px, estable

La primera pintura cae entre +137 s y +204 s, contra ~+134 s con perfil nuevo en tmpfs; y en la
corrida anterior no había llegado a los +291 s con la máquina más cargada. Bajo TCG «cinco minutos y
dos capturas» no distingue «no pinta» de «todavía no pintó», así que el §6.10.ter queda corregido en
su propio párrafo: de sus cuatro afirmaciones, la cuarta medía la paciencia.

⚠ Trampa nueva, para el que venga a medir la imagen: `cosmic-idle` ATENÚA la pantalla. Entre +526 s y
+590 s sin una sola entrada, los 703766 px de (255,0,255) pasan a 703779 px de (117,0,117) — la misma
ventana al 46 %. Un diff de píxeles o un contador por color exacto lo lee como «desapareció».
2026-09-14 15:28:36 +00:00
Sergio 426e5d1b1d estado: KF6 tanda 5 — 11/11 reproducen
kio kcolorscheme kdeclarative krunner kwayland layer-shell-qt kquickimageeditor
kcharselect kruler kdf kfind.

  REPRODUCEN: 11 · DERIVA: 0 · NO-DETERMINISMO: 0 · no construyeron: 0

`kio` entra acá y es de las gordas del árbol KDE: reproduce bit a bit.
2026-09-14 15:24:47 +00:00
SergioandClaude Opus 5 de7c3faa9c gitea arranca: su [[service]], probado con el entorno de verdad — y dos fallos que sólo salen ahí
La receta ya declara su servicio (SDD 30) y `perfil.servidor` lo habilita. El ArtifactHash NO se
mueve (`b3:391a613e…` antes y después): `[[service]]` está fuera de `hash_inputs`.

⚠ Primero, una corrección del commit anterior: declaraba `gitea` en `perfil.servidor` con SEIS
LÍNEAS DE COMENTARIO y sin la línea `"gitea",`. El perfil cargó igual, el grafo no dijo nada y el
paquete simplemente no estaba. Lo cazó `targets.py --services` al resolver el label: «lo declara
gitea, que NO pertenece al perfil». Un comentario que explica una entrada que no existe se lee como
la entrada.

La card no encarna el binario directo: **gitea se niega a correr como root** (`[F] Gitea is not
supposed to be run as root`), así que va por `setuidgid`. Y comprueba dos cosas del SITIO antes de
arrancar, saliendo 78 con un mensaje que las nombra: `/etc/gitea/app.ini` y el usuario `gitea`. Un
gitea sin config no falla — arranca y ofrece el asistente de «crear administrador» a quien pase.

Probado en el worker con el argv exacto y `env -i`, que es lo que arje hace de verdad. Tres fallos
que con una shell normal no se ven NUNCA:

· `exec setuidgid …` a secas ⇒ `sh: exec: line 0: setuidgid: not found`. El `sh` de busybox de la
  imagen no trae `FEATURE_SH_STANDALONE`: no despacha sus applets, los busca en `PATH`, y PID 1 no
  garantiza ninguno. Todo con ruta absoluta (`/bin/grep`, `/usr/bin/setuidgid`).
· sin `PATH` en el `envp` ⇒ `git not found: executable file not found in $PATH`. **gitea lanza
  `git` como subproceso**, y el mensaje se lee como «falta git» con git instalado y raíz de `base`.
  Un envp vacío no es «limpio»: es sin PATH.
· sin `cd` ⇒ `fatal: error reading '/root/.git'`. El cwd se hereda y gitea corre `git config` en él.
  `Service` no tiene campo `cwd`, así que va en el argv, a la vista.

Con eso: escucha, `GET /` responde **200** y el proceso corre como `gitea`. Las dos guardas
verificadas por separado (78 y su mensaje cada una). El worker quedó limpio y censado: sin usuario,
sin /etc/gitea, sin /var/lib/gitea, sin symlinks y sin procesos.

Y `/etc/gitea` entra en las rutas de la mudanza: el `app.ini` guarda los SECRETOS generados (gitea
los escribe en el propio fichero, que por eso tiene que ser suyo, `gitea:gitea 0660`).

⚠ Lo que queda abierto y está anotado en la receta: **el usuario `gitea` no existe en el producto**.
`/etc/passwd` de la imagen es la constante `takana_bootstrap::PRODUCT_PASSWD` y sólo trae `root` y
`sshd`. El SDD 30 sacó las Cards de una constante de Rust y las puso en la receta; los USUARIOS
siguen donde estaban las Cards. Hasta que se declaren, el usuario llega con los datos del sitio.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Tf9T4vGzsMoT7eS8YzMFn
2026-09-14 15:16:21 +00:00
Sergio f2aafb1b39 estado: KF6 tanda 4 + 15 del worker — dos no-determinismos REALES en la imagen de KDE
Hub, KF6 tanda 4: REPRODUCEN 9 · DERIVA 1 · NO-DETERMINISMO 2 · no construyeron 0
Worker, Rust: REPRODUCEN 13 · DERIVA 2 · NO-DETERMINISMO 0

El libro pasa de 104 a 207 entradas en la jornada.

── Los dos que divergen, y por qué importan ──────────────────────────────────────────

`kirigami` — está en `escritorio-kde` y tiene **37 dependientes**. Dos sitios:
  · libKirigamiTemplates.so: los símbolos del AOT de QML llevan un contador por fichero
    que cambia de corrida a corrida (`…LinkButton_qml3$_28/_38/_58` en A contra
    `…Badge_qml3$_88/_98/_108` en B) ⇒ el orden en que se compilan los .qml no está fijado.
  · kdevappwizard/templates/kirigami6.tar.bz2: difiere desde el byte 0xa, o sea desde el
    primer bloque comprimido — un tar armado sin orden estable.

`syntax-highlighting` — también en `escritorio-kde`. libKF6SyntaxHighlighting.so difiere
en 8.800.310 bytes desde el offset 41 y hasta **el tamaño cambia** (10.345.888 contra
10.345.840). Las cadenas que difieren son datos comprimidos ⇒ es el recurso generado con
las definiciones de sintaxis, otra vez orden de entrada.

Los tres de hoy (con `gocryptfs`) son la MISMA clase: **recurso generado cuyo orden de
entrada nadie fija**. No es el compilador ni el lab: es que la receta deja que el orden lo
decida un `readdir` o el planificador.

── Lo que NO se hace acá, y por qué ──────────────────────────────────────────────────
Arreglarlo toca la receta ⇒ re-hash ⇒ reconstruir kirigami y sus 37 dependientes. Eso es
una decisión de campaña con su coste, no algo que se mete de paso en una verificación.
Los cuatro ejemplares quedan en `store/.divergen/` para poder mirarlos.

── Control que sostiene el hallazgo ──────────────────────────────────────────────────
`kirigami-addons` y `kquickcharts` TAMBIÉN llevan QML y reproducen. O sea que no es «QML
es no-determinista»: es algo propio de esas dos recetas.
2026-09-14 15:09:32 +00:00
Sergio 703e81d6a8 estado: cosecha granja 2026-09-14T15:04:16Z — avance del árbol KDE 2026-09-14 15:04:16 +00:00
SergioandClaude Opus 5 447e151424 ADR 0019: el dueño del formato Card — y takana lo escribe a mano en cinco sitios
La mudanza emite tarjetas de arje y el producto instalado también; quién es dueño del formato no
estaba escrito, así que por omisión son dos repos. Medido hoy:

  el tipo canónico existe y está en tawasuyu   `shared/card/card-core::Card`
  …y VALIDA su versión                          CARD_SCHEMA_VERSION = 1, comparada al deserializar
  emisores dentro de takana                     2, en dos lenguajes (bootstrap Rust + arje.py)
  deps de card-core en crates/*/Cargo.toml      0
  `"schema_version": 1` escrito a mano          5 sitios
  arje-absorb                                   usa card_core::Card y ya trae systemd/openrc/runit/
                                                dinit/sysvinit; formatos/ reimplementa DOS en Python

El día que el esquema pase a 2, arje rechaza las tarjetas de takana — y no falla en un test: falla
en el arranque de una caja recién instalada. Hoy coinciden por suerte, no por construcción. Es el
mismo fallo que ya se pagó un piso más abajo, cuando había dos emisores DENTRO de takana y cada uno
tenía un campo distinto mal en la raíz.

Decisión: tawasuyu DEFINE, takana GENERA. Un solo emisor acá y que serialice con el tipo, no con
`format!` — criterio de aceptación negativo: cero literales `"schema_version"` en el árbol. Los
lectores de init ajeno se RETIRAN (absorb ya los tiene), no se mejoran, y mientras convivan hay una
prueba que compara las dos salidas y falla si divergen. Lo que takana aporta —el lector `proc`, que
lee lo VIVO porque `rc-status` miente— va hacia absorb, no en paralelo.

Y la herramienta NO se muda a tawasuyu: la mudanza habla de recetas, perfiles, store y ArtifactHash.
Lo que cruza la frontera es el tipo, no la herramienta.

Dos precondiciones que no se saltan: `card` es uno de los 26 repos sin copia fuera de gioser (hacer
que el bootstrap dependa en compilación de un repo que sólo vive en la máquina que se borra es
convertir un problema conocido en un bloqueo de arranque); y `STAGE1_SEED_CARD` ENTRA EN EL HASH del
bootstrap, así que reserializar con card-core puede mover el baseline del selfhost — se mide con
`takana hash` antes, y si se mueve es una decisión propia. La mudanza no tiene ese problema y puede
adoptar el tipo primero.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Tf9T4vGzsMoT7eS8YzMFn
2026-09-14 15:01:05 +00:00
Sergio 589efee4f8 atuq: en la imagen el navegador SÍ pinta — la segunda pantalla no era
La sospecha salía del propio serial: el arranque del §6.10.ter veía DOS dispositivos DRM
(`drm: card0 card1 renderD128`) y uno nuevo ve uno solo. Sin `-vga none`, QEMU agrega una VGA
estándar además del virtio-gpu, OVMF pinta su GOP ahí y el kernel levanta simpledrm encima: un
compositor con dos tarjetas puede componer en la que el `screendump` no muestra, y eso se ve igual
que «la ventana no aparece». Por eso el guion lleva `VGA=1`, para pedir ese caso por su nombre.

Medido con las dos configuraciones y el mismo lanzamiento:

    -vga none  → card0        → 703766 px magenta
    VGA=1      → card0 card1  → 703766 px magenta

El mismo número al píxel. La ventana aparece —panel, dock y el navegador con su barra lateral—,
`nsWindow::Create() Toplevel` está en el MOZ_LOG, la superficie se mapea y `mIsFullyOccluded 0`, con
`WaylandBufferSHM` de 1280x696, el mismo camino de buffers que bajo sway.

⇒ la segunda pantalla no es la causa. Queda una sola diferencia con aquella corrida: cómo se lanzó
el navegador. Acá va con perfil nuevo y MOZ_ENABLE_WAYLAND puesto; allá fue un `atuq` pelado con su
perfil por defecto tecleado en el serial. Para eso está `--como-usuario`, que es la corrida que sigue.

⚠ Dos trampas del arnés, medidas y escritas en el guion: el terminal hace ECO de lo que se le
escribe, así que una marca de fin literal se lee en el eco y las órdenes se pisan; y `cmd & ; echo`
es error de sintaxis en ash ⇒ el navegador no se lanzó y la corrida siguió dando capturas de un
escritorio vacío, que se leen igual que el fallo que se investiga.
2026-09-14 14:35:13 +00:00
Sergio 9d6c79a749 estado: cosecha granja 2026-09-14T14:33:32Z — avance del árbol KDE 2026-09-14 14:33:32 +00:00
Sergio 642c170b6a docs(SDD 23): §10 — la misma herida reabierta por el renombre, y el gocryptfs sin causa
Deja escrito lo de hoy donde ya vivía el diagnóstico de esta clase de fallo (§9):
el aprovisionamiento de `go` en el worker SE HIZO el 2026-08-28 y el renombre lo
deshizo el 2026-09-09 sin que nada fallara. Con el método de detección (varias
muriendo en segundos = sistémico; leer el error de UNA antes de contar deuda), la
comprobación en los dos sentidos, y las cuatro sondas de `pgrep` que el mismo
renombre dejó ciegas.

Incluye el no-determinismo de `gocryptfs` con la hipótesis REFUTADA anotada como
tal: no es el `cgo` (sq y usql también lo usan y reproducen) ni la ruta aleatoria
del temporal (las cadenas son idénticas y difieren 1.874.136 bytes, desde .rodata).
Queda abierto y sin causa; no está en ningún perfil, así que no bloquea imágenes.
2026-09-14 14:32:04 +00:00
Sergio cb101fd70b estado: KF6 tanda 3 (12/12) + 17 del worker, con el primer NO-DETERMINISMO real del frente Go
Hub, KDE Frameworks tanda 3: kglobalaccel kpackage kconfigwidgets kiconthemes
ktextwidgets kxmlgui kparts kcmutils knotifications kdeclarative ksvg kwallet.
  REPRODUCEN: 12 · DERIVA: 0 · NO-DETERMINISMO: 0 · no construyeron: 0

Worker (ya con `go` arreglado), familia Go:
  REPRODUCEN: 15 · DERIVA: 1 · NO-DETERMINISMO: 1 · no construyeron: 0

  · `checkmake` — la que antes «no construía» — REPRODUCE. Cierra el arreglo del enlace
    de `go`: no estaba rota, faltaba el binario en el PATH del host.
  · `cilium-cli` DERIVA: el artefacto guardado era viejo; las dos reconstrucciones
    coinciden entre sí ⇒ se movió el mundo, no la receta. No es un fallo.
  · `gocryptfs` NO-DETERMINISMO, y es el primero de verdad del frente Go.

La causa de gocryptfs, con los dos ejemplares guardados en `store/.divergen/`:

    usr/bin/gocryptfs  ELF, difieren [.text .rodata .data .debug_*]
      · .debug_str sólo en A: …/.gotmp/go-build3432240771/b141
      · .debug_str sólo en B: …/.gotmp/go-build2186295412/b141

El directorio temporal `go-build<aleatorio>` queda horneado en el DWARF. Hipótesis a
comprobar, no conclusión: sólo pasa con `cgo = true`, porque cgo genera fuentes C en ese
temporal y su ruta real entra en la info de depuración; con CGO off no hay fuentes
generadas y las 15 restantes reproducen. En el corpus hay exactamente cuatro recetas Go
con cgo: gitea, gocryptfs, sq y usql — ninguna verificada todavía. Se miden antes de
afirmar nada.
2026-09-14 14:23:38 +00:00
SergioandClaude Opus 5 74151a2b0c gitea 1.27.0 con sqlite y bindata: el binario sellado no podía abrir la base de datos
La mudanza de gioser pasa por levantar su gitea del otro lado — 28 repos, 26 sin copia fuera. El
corpus ya tenía `gitea` sellado (1.26.4, `b3:35bb4f04…`) y NO sirve, medido contra el artefacto:

    $ gitea --config app.ini migrate
    Error: sqlite3 requires: -tags sqlite,sqlite_unlock_notify
    this Gitea binary was not built with SQLite3 support

Construía, reproducía y no podía abrir la sqlite en la que gioser guarda TODO (`DB_TYPE = sqlite3`).
Y `gitea --version` decía `version development`. Es subcomando-sin-driver un piso más abajo.

Tres cambios, y el tercero es el que no se ve venir:

· Pin 1.27.0 (gioser corre 1.27.0). No es cosmético: gitea migra el esquema hacia adelante y se
  planta si la DB trae migraciones más nuevas que el binario, así que el pin va por delante del
  origen, nunca por detrás.
· Tags `sqlite,sqlite_unlock_notify` (⇒ `cgo = true`, el driver de mattn es C) y `bindata`, que
  embebe `public/` y `templates/`: sin él la receta publica sólo el ejecutable y el servidor
  arrancaría sin UI.
· La fuente pasa de `repo`+`commit` al TARBALL DE RELEASE. El clon no alcanza: la UI se compila
  con Node y las deps Go no están vendoreadas en git. El `gitea-src-1.27.0.tar.gz` trae las dos
  cosas hechas — medido: `public/assets/` 764, `vendor/` 11246, `templates/` 663 — así que
  construye con el lab tal cual, sin Node y sin red. La URL es locator (ADR 0013); ancla el sha256.

Nuevo hash: `b3:391a613e…`. Declarado en `perfil.servidor` como paquete y NO en `servicios`:
arrancarlo necesita el [[service]] del SDD 30 con su app.ini, y declarar un arranque que no existe
sería la mentira que ese campo existe para no tener.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016Tf9T4vGzsMoT7eS8YzMFn
2026-09-14 14:17:52 +00:00
Sergio 0a75414da0 estado: 12 KF6 más verificadas + 10 rescatadas del libro del worker
Tanda 2 de la familia KDE Frameworks (hub): kbookmarks kcolorscheme kcompletion
kdnssd kholidays kunitconversion kauth kpty solid sonnet prison kservice.

  REPRODUCEN: 12 · DERIVA: 0 · NO-DETERMINISMO: 0 · no construyeron: 0

Y aparte: el worker tenía su propio libro (`work/repro-worker.tsv`, fuera de la siembra)
con 13 verificaciones del 2026-09-05 que nunca volvieron al hub. Cobertura medida y
perdida. Importadas 10.

Las otras 3 NO se importan, y el motivo es el que justifica que la clave del libro sea
(receta, ArtifactHash) y no la receta sola: su hash cambió desde entonces, así que la
medición ya no habla del artefacto de hoy.
  · atuq, bzip2  — reproducían, pero a un hash superado
  · aichat       — decía NO-DETERMINISMO a `c40a15bd…`; el hash vigente es `7a515b0a…`
                   y a ÉSE el propio worker le midió «reproduce». Importar por nombre
                   habría arrastrado un no-determinismo que ya no existe.
2026-09-14 14:13:14 +00:00
Sergio 756ed9c6a6 atuq: el compositor NO era la causa — con cosmic-comp nesteado el navegador pinta
El §6.10.ter dejó dos variables cambiando a la vez (compositor y arranque real) y ninguna medición
que las separe. `scripts/cosmic/atuq-en-cosmic.sh` saca la primera de encima en ~2 min por vuelta,
sin QEMU y sin imagen: sway headless de andamio, cosmic-comp nesteado encima por winit, atuq adentro,
y `grim` capturando del lado de sway. El `--control` corre EL MISMO binario de atuq —el del cierre
hidratado para la imagen— directo sobre sway.

Las dos capturas coinciden al píxel en la región de la página (586331 px magenta, mismo bbox), y no
es que el navegador se escape a sway: antes de lanzarlo, la ventana de cosmic-comp ocupa 1276x637 en
ese mismo rectángulo, y el MOZ_LOG del widget ve `mode output size 1276 x 637` con cosmic contra
`1280 x 720` en el control. Las dos corridas enteras difieren en 1130 píxeles, todos en las barras
de título.

⇒ cosmic-comp no es el que impide la ventana. Queda como variable el arranque de verdad: kms/DRM
sobre virtio-gpu en vez de winit, el PID1 de arje, el seat.

De paso queda anotado el camino de buffers cuando SÍ funciona —`WaylandBufferSHM`, memoria
compartida y no dmabuf—, que es la línea de base contra la que comparar la traza de la imagen.

Y `scripts/cosmic/atuq-en-imagen.py` para medir allá: arranca la imagen, maneja el serial, lanza el
navegador con el mismo MOZ_LOG y pide capturas por QMP. La corrida del §6.10.ter fue a mano y no
dejó un solo log que se pueda releer.
2026-09-14 14:11:49 +00:00
Sergio 6c1c316671 estado: cosecha granja 2026-09-14T14:03:05Z — avance del árbol KDE 2026-09-14 14:03:05 +00:00
Sergio bb83a4f973 estado: 12 frameworks KF6 tier 1 verificados — reproducen los 12
Barrido por FAMILIA (KDE Frameworks tier 1, todos CMake), que es lo que hace
legible el censo: si el fallo fuera del toolchain se concentraría acá y saltaría
a la vista. karchive kcodecs kconfig kdbusaddons kguiaddons ki18n kidletime
kitemmodels kplotting kwidgetsaddons kwindowsystem kcrash.

  REPRODUCEN: 12 · DERIVA: 0 · NO-DETERMINISMO: 0 · no construyeron: 0

Los 12 además CONSTRUYEN hoy, que es el otro hallazgo del verificador: `sealed`
sólo dice que alguien los construyó alguna vez con algún lab, y el lab rueda.
2026-09-14 14:01:38 +00:00
Sergio 5cb6e568d6 catálogo: wl-clipboard sube al corpus — cerraba el único orphan_dep de cuatro grafos
Estaba sólo en `recipes/incoming-wlr/`, o sea inalcanzable desde las otras
cuatro colas. `cliphist` vive en el CORPUS y la pide en `[deps] run`, así que
corpus, gnome, kde y cosmic la reportaban como `orphan_deps: ["wl-clipboard"]`.

No era cosmético: `escritorio-cosmic` declara `cliphist` de raíz, y la imagen
se habría armado con el demonio de historial y SIN `wl-copy`/`wl-paste` — el
modo de fallo silencioso que la propia receta de cliphist advierte (el binario
corre y no hace nada). La clausura no lo podía ver: decía `falta=0` en los
cinco perfiles, porque una dep que no resuelve no se cuenta, desaparece.

Solución = la que el catálogo ya usó con `mpv` y `atuq`: subirla al corpus, de
donde las colas la alcanzan (sibling-first y después el catálogo padre).

Medido antes de mover: ninguna de sus 9 deps tenía variante hermana en
`incoming-wlr`, así que el ArtifactHash no podía cambiar — y no cambió
(`b3:fc2ab7b7…` a los dos lados, comprobado con `takana hash`). Cero re-sellos.

Tras regenerar los cinco grafos: `orphan_deps: []` en los cinco, y la clausura
de `escritorio-cosmic` pasa de 273 a 274, sellada.
2026-09-14 13:54:28 +00:00
Sergio d2187fda11 estado: 11 recetas KDE más verificadas reproducibles (SDD 23) 2026-09-14 13:48:34 +00:00
Sergio 98df75a8cb estado: cosecha granja 2026-09-14T13:32:34Z — avance del árbol KDE 2026-09-14 13:32:34 +00:00
Sergio 5614d8c855 estado: cosecha granja 2026-09-14T13:02:49Z — avance del árbol KDE 2026-09-14 13:02:49 +00:00
Sergio edfdda2d4d estado: cosecha granja 2026-09-14T12:32:23Z — avance del árbol KDE 2026-09-14 12:32:23 +00:00
Sergio a26780cbd8 estado: cosecha granja 2026-09-14T12:03:00Z — avance del árbol KDE 2026-09-14 12:03:00 +00:00
Sergio 658eecb9cd estado: cosecha granja 2026-09-14T11:32:56Z — avance del árbol KDE 2026-09-14 11:32:56 +00:00
Sergio 0eee35a041 estado: cosecha granja 2026-09-14T11:03:49Z — avance del árbol KDE 2026-09-14 11:03:49 +00:00
Sergio 6c45f438b0 estado: cosecha granja 2026-09-14T10:32:23Z — avance del árbol KDE 2026-09-14 10:32:23 +00:00
Sergio af2469107f estado: cosecha granja 2026-09-14T10:02:17Z — avance del árbol KDE 2026-09-14 10:02:17 +00:00
Sergio d21d69ff8f estado: cosecha granja 2026-09-14T09:32:17Z — avance del árbol KDE 2026-09-14 09:32:17 +00:00