ADR 0016 los listaba entre los CONGELADOS; el usuario pidió descongelarlos al abrir el SDD 28. La
enmienda queda escrita en el propio ADR, que si no la etiqueta deja de describir el hecho.
`hammer-install.sh` → `takana-install.sh`, `hammer-live-install.sh` → `takana-live-install.sh`,
`hammer-banner.txt` → `takana-banner.txt`, `BRIEFING-hammer.md` → `BRIEFING-takana.md`.
**Lo que hacía caro esto no es el nombre del fichero.** El instalador se inyecta en el ISO como
`/usr/bin/hammer-install` y su éxito se detecta con un `grep` de `HAMMER-INSTALL-OK` desde TRES
scripts de prueba. Renombrar un solo lado los deja casando NADA — sin fallar —, que es literalmente
el modo en que `atribuir-fallos.py` quedó mudo cuando el renombre movió el target de `tracing`.
Se renombraron las dos puntas en el mismo commit (`/usr/bin/takana-install`,
`TAKANA-INSTALL-OK/FAIL`, `TAKANA_INSTALL_*`, `work/takana-install.img`, `/run/takana-install`),
se comprobó por `grep` que no quede ningún token viejo fuera del ADR, y —lo que decide— se CORRIÓ
`install-tui-test.sh`: 4/4 casos verdes.
Las tres `TAKANA_INSTALL_*` caen al nombre viejo (`${TAKANA_INSTALL_X:-${HAMMER_INSTALL_X:-}}`):
el llamador puede ser un ISO anterior al renombre. Misma convención que `TAKANA_ROOT_PW` unas
líneas más arriba en ese mismo script.
NO se tocó `/usr/sbin/hammer-recover` ni su hook de arranque —renombrarlo rompe máquinas YA
INSTALADAS, no el repo—: sobrevive intacto dentro del script renombrado, verificado por conteo
antes y después (8 ocurrencias). Tampoco `hammerd`, `hammer-edit` (su `name` está en la ruta del
store), `/var/lib/hammer`, `HAMMER_LIVE` ni los siete literales de hash.
De paso: `scripts/.hammer-banner.txt.kate-swp` era un swap de editor commiteado por error. Fuera.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RomoxEGZUhaT4pob1QSX5x
11 KiB
ADR 0010 — Arranque por grafo: el menú de boot como navegación del grafo de estados (mirada + takana)
Estado: aceptado; lado takana implementado (pasos 1–5 ✅). Instalador live EFI validado 2-stage en
OVMF ✅; cero-parpadeo validado por captura de framebuffer ✅ (salvo el seamless i915, metal-only).
Falta metal real y el lado mirada. Fecha: 2026-07-06 (impl. EFI-stub + cero-parpadeo 2026-07-10).
Contexto cruzado: takana (arranque/kernel/generaciones) + tawasuyu/mirada (render). El
espejo de este ADR para el lado mirada vive en tawasuyu/HANDOFF-arranque-grafo.md.
Contexto
takana quiere instalarse en metal real con un arranque soberano: nada de systemd-boot
(sigue siendo systemd) y GRUB-EFI está roto en este stack (GRUB 2.14 cuelga la rama UEFI, ver
[etapa-metal-usb]). El compositor mirada (tawasuyu, 02_ruway/mirada) ya es "lo que ves al
arrancar": compositor Wayland + greeter + launcher sobre DRM/KMS. La idea del usuario: que el
menú de arranque sea de mirada, no de un bootloader ajeno — "sólo falta ponerle su menú tipo
GRUB".
Al mirarlo, el menú no es un port de GRUB. En un Linux normal el menú es una lista de kernels. En takana, donde el sistema es un grafo content-addressed de estados (SDD 15: config = paquete = función = proceso), el menú puede ser la navegación de ese grafo: elegir un nodo = activar un estado del sistema. Eso cierra el eslabón proceso que SDD 15 §H4 dejó abierto (las tres primeras lentes ya coinciden en el hash; faltaba el lado proceso = replay de un log monótono de estados).
Decisión
El menú de arranque es un selector gráfico sobre el grafo de estados del sistema, renderizado por mirada sobre KMS, respaldado por el modelo de generaciones/DAG de takana. La frontera entre los dos agentes es un contrato de datos (takana describe el grafo; mirada lo dibuja y pide activar un nodo). Invariante de UX compartido: cero parpadeo de DRM desde la firmware hasta el escritorio.
Quién reside sobre qué
| Capa | Reside en | Notas |
|---|---|---|
| Cargador EFI + entrada en el disco instalado | takana | install-to-disk EFI; ver "loader" abajo. |
| Kernel con KMS sin costura (simpledrm→i915) | takana | linux-generic.toml ya trae SIMPLEDRM+SYSFB_SIMPLEFB+FB_EFI+I915+FBDEV_EMULATION. |
| El grafo de estados (nodos que el menú ofrece) + activar nodo | takana | generaciones (takana-upgrade/recover), overlay, DAG de wawa-memo. |
| Render + navegación del menú sobre KMS | tawasuyu/mirada | reusa Prezi espacial / Zoom-Z (árbol fractal) / constelaciones. |
| Sostener el DRM master sin parpadeo menú→escritorio | mirada (con el kernel de takana) | un solo framebuffer, abierto una vez, nunca re-modeset. |
El contrato (la frontera limpia)
takana → mirada — takana escribe el grafo en un path bien conocido (propuesta:
/run/hammer/boot-graph.json, regenerable, world-readable):
{
"version": 1,
"current": "<blake3-del-nodo-vivo>",
"default": "<blake3-a-arrancar-si-no-hay-elección>",
"nodes": [
{
"id": "<blake3>",
"label": "texto corto para el usuario",
"kind": "generation | snapshot | base | recovery",
"created": "2026-07-06T12:00:00Z",
"parents": ["<blake3>", "..."],
"bootable": true,
"summary": "qué cambió respecto del padre (opcional)"
}
]
}
mirada → takana — mirada pide activar el nodo elegido (propuesta: escribir el id en
/run/hammer/boot-select o invocar takana boot activate <id>). takana valida el id contra el
grafo, activa la generación (pivota overlay/root) y sigue el arranque. Un nodo recovery mapea al
hammer-recover --rollback que ya existe.
El grafo es content-addressed: cada
ides un hash,parentsforma un DAG (no una lista lineal). El modelo in-place actual de takana (hammer-recover: "no hay menú de generaciones tipo NixOS") se sube a un grafo navegable — es trabajo nuevo de takana, no un refactor cosmético.
Cero parpadeo (invariante compartido)
Un solo modo de video desde la firmware hasta el compositor:
- Firmware GOP framebuffer →
SYSFB_SIMPLEFBtoma ese mismo FB → i915 hace seamless takeover sin cambio de modo. (El kernel ya tiene los tres bits=y.) - Sin texto de fbcon ni cursor durante el arranque, sin getty en el VT gráfico. Diagnóstico
preciso (2026-07-10, evidencia por captura de framebuffer en OVMF-GOP,
scripts/): hoy el kernel metal pinta TODO el log de boot sobre el framebuffer gráfico (simpledrm "switching to colour frame buffer device 160x50" + decenas de líneas). Causa:CONFIG_VT_CONSOLE=yregistra el VT como consola automáticamente (quitarconsole=tty0NO alcanza — probado), yquiet loglevel=0por LoadOptions NO lo frena (fbcon redibuja el ring buffer al tomar el FB a ~0.6s; además elignore_loglevel earlyprintkHORNEADO enCONFIG_CMDLINEfuerza la salida). Fix (requiere rebuild del kernel metal, cambia el hash firmado): (a)CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y— fbcon no toca el FB hasta el primer output ⇒ queda negro; (b) cmdline horneada → quitarearlyprintk=efi,keep ignore_loglevel, añadirquiet loglevel=3 vt.global_cursor_default=0; (c)CONFIG_LOGOya está off ✓. GOTCHA de validación: conquietlos marcadores serie kernel-side desaparecen ⇒ los harness EFI deben apoyarse en los marcadores userspace tee'ados a/dev/ttyS0(que sobrevivenquiet). El seamless i915 (1) sólo se valida en metal Intel real (OVMF no trae i915). - mirada abre el DRM master directo y lo sostiene desde el menú hasta el escritorio — nunca suelta, nunca re-modeset.
El loader (cómo se lanza el kernel sin systemd-boot ni GRUB)
El cuelgue del EFI-stub directo en el metal del usuario era por el initrd de 100MB (medición TPM
- quirk de LoadOptions del firmware).
linux-generic.tomlya trae squashfs+overlay ⇒ el initramfs se vuelve minúsculo (sólo monta el squashfs). Con initrd chico, EFI-stub directo vuelve a ser viable y soberano — sin GRUB ni systemd. Es decir: squashfs+overlay no es un desvío, es lo que destraba el arranque EFI soberano y de paso el cero-parpadeo (initrd chico = menos tiempo muerto antes del takeover).
Plan (lado takana)
- Este ADR + el handoff a tawasuyu con el contrato (hecho en este commit).
- initrd chico → EFI-stub directo reprobado en OVMF ✅ (2026-07-10): el disco instalado NO usa un
rootfs en RAM sino un initramfs mínimo de pivote (~770K) que resuelve
takana-rootpor LABEL y haceswitch_roota la ext4 real. Ese initrd chico es lo que destraba EFI-stub directo (el cuelgue del metal era por un initrd de 100MB). Validado en OVMF porscripts/efi-disk-boot-test.sh. (La vía squashfs+overlay del [post-etapa-e] queda como optimización futura; el pivote a ext4 ya cumple.) - Contrato de generaciones-grafo ✅ (módulo
takana_upgrade::boot_graph+ subcomandotakana boot): el modelo in-place de generaciones se lee como un grafo de estados navegable (id =of_tree, DAG porparent),takana boot graphemite/run/hammer/boot-graph.jsoncon el formato del contrato, ytakana boot activate <id>(o--from-select) deja el sistema en un nodo (no-op si ya vivo · rollback paso a paso a un ancestro · nodorecoverysintético · error honesto ante un "redo" hacia una generación huérfana). Validado e2e por el CLI. mirada ya puede maquetar contra el grafo real. - Afinar kernel/cmdline para el cero-parpadeo ✅ (2026-07-10):
linux-metalconCONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y+ cmdline horneadaquiet loglevel=3 vt.global_cursor_default=0(sinearlyprintk/ignore_loglevel) + ttyS0 último (la shell de arje-zero sale por serial, no pinta tty0). Validado por captura de framebuffer en OVMF-GOP (scripts/efi-flicker-test.sh): el kernel NO toca el FB (Δ media de brillo = 0.000 entre handoff y post-boot; el viejo saltaba ~3→~11) ⇒ el contenido de la firmware sobrevive intacto hasta que mirada abra el DRM. Los harness EFI pasan a marcadores userspace tee'ados a/dev/ttyS0(sobrevivenquiet). El seamless i915 (firmware GOP → simplefb → i915 sin re-modeset) sólo se valida en metal Intel real. - install-to-disk EFI ✅ (2026-07-10): el bzImage
linux-metalES el binario EFI (\EFI\BOOT\BOOTX64.EFI, ruta fallback removible, sin GRUB ni systemd-boot). Como no hay LoadOptions en esa ruta, elCONFIG_CMDLINEhorneado (… initrd=/initramfs.cpio.gz rdinit=/init) activa el pivote. Dos caminos, mismos artefactos:- host-side
scripts/install-image-efi.sh— GPT+ESP+root/store/state, ESP con mtools de takana, ext4 conmke2fs -dbajounshare -r; validado VERDE en OVMF (scripts/efi-disk-boot-test.sh: firmware → BOOTX64.EFI → pivote → arje-zero PID1). - live-side
scripts/takana-live-install.shrama EFI — detecta/sys/firmware/efiy hace MBR con ESP tipo 0xEF (UEFI arranca una ESP MBR igual que GPT ⇒ alcanza busybox fdisk/mkfs.vfat/mount, sin GPT-tool ni mtools en el live). El kernel EFI-stub viaja en el payload (iso-image.sh INSTALLER=1bundleabzImage-efi). Validación 2-stage VERDE en OVMF (scripts/efi-install-test.sh): ISO live UEFI →takana-installdetecta/sys/firmware/efiy toma la rama EFI → el disco instalado bootea SOLO por EFI-stub soberano (sin GRUB) → arje-zero PID1. Falta sólo el metal real (quemar USB + bootear, Secure Boot OFF).
- host-side
Consecuencias
- La frontera es un fichero + un comando, no una API compartida ⇒ los dos agentes avanzan sin
bloquearse. takana puede emitir el grafo y probar EFI-stub sin esperar a mirada; mirada puede
maquetar el menú contra un
boot-graph.jsonde ejemplo sin esperar a takana. - El menú-grafo es la primera manifestación del lado proceso de SDD 15 §H4 — arrancar = activar un nodo del DAG. No colapsa todo el modelo, pero lo hace visible.
- No mueve la frontera de confianza (ADR 0007/0009): activar un nodo es reproducir/hidratar un árbol sellado del store, no ejecutar algo nuevo.
Referencias
- SDD 15 §H3/§H4 (
docs/15-frontier-ai-native.md) — config = paquete = función = proceso; el lado proceso = replay del MonotonicLog. - ADR 0007 (arje-zero como init propio), ADR 0009 (código content-addressed).
- Memoria de proyecto: etapa-metal-usb (GRUB 2.14 roto, EFI-stub colgó por initrd 100MB, metal booteado vía systemd-boot como crutch descartable), post-etapa-e-refinamientos (squashfs+overlay, rollback-al-boot).
tawasuyu/HANDOFF-arranque-grafo.md— el espejo, lado mirada.