takana etapa 5b: los 59 docs de diseño, runbooks y ADR

645 líneas. Los ADR entran porque en este repo SON documentos vivos, no
registros inmutables: el 0013 tiene 5 commits, el 0009 dos. Eso se comprobó
antes de decidir, no se asumió por convención general.

EXCLUIDOS por ser REGISTRO o generado: docs/evidencia/ (6), el HANDOFF de la
noche de KDE (1) y docs/state/ (24, se regenera solo). Reescribir un comando
dentro de una evidencia la falsifica.

Y el ADR 0016 se excluye de todo barrido, con un aviso adentro para el próximo
que barra: habla SOBRE el renombre, así que necesita seguir diciendo 'hammer'.
El barrido se lo llevó puesto y lo dejó titulado 'Renombre del sistema: takana
→ takana'; revertido.

Congelados, verificados uno por uno con controles: /opt/hammer, /var/lib/hammer,
/usr/bin/hammer, /mnt/vvv/hammer, la URL de gitea, hammer-farm.service,
hammer-live-install.sh, BRIEFING-hammer.md, hammerd, hammer-recover y
HAMMER_LIVE.
This commit is contained in:
Sergio
2026-09-09 19:25:51 +00:00
parent e852f48491
commit 97ceb72411
56 changed files with 632 additions and 628 deletions
+25 -25
View File
@@ -1,14 +1,14 @@
# ADR 0010 — Arranque por grafo: el menú de boot como navegación del grafo de estados (mirada + hammer)
# ADR 0010 — Arranque por grafo: el menú de boot como navegación del grafo de estados (mirada + takana)
**Estado:** aceptado; lado hammer implementado (pasos 15 ✅). Instalador live EFI validado 2-stage en
**Estado:** aceptado; lado takana implementado (pasos 15 ✅). 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:** hammer (arranque/kernel/generaciones) + tawasuyu/mirada (render). El
**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
hammer quiere instalarse en metal real con un arranque **soberano**: nada de `systemd-boot`
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
@@ -16,7 +16,7 @@ arrancar": compositor Wayland + greeter + launcher sobre DRM/KMS. La idea del us
GRUB".
Al mirarlo, el menú no es un port de GRUB. En un Linux normal el menú es una **lista** de kernels.
En hammer, donde el sistema es un **grafo content-addressed** de estados (SDD 15: config = paquete =
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).
@@ -24,23 +24,23 @@ lentes ya coinciden en el hash; faltaba el lado proceso = replay de un log monó
## 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 **hammer**. La frontera entre
los dos agentes es un **contrato de datos** (hammer describe el grafo; mirada lo dibuja y pide activar
**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 | **hammer** | install-to-disk EFI; ver "loader" abajo. |
| Kernel con KMS sin costura (simpledrm→i915) | **hammer** | `linux-generic.toml` ya trae `SIMPLEDRM+SYSFB_SIMPLEFB+FB_EFI+I915+FBDEV_EMULATION`. |
| El grafo de estados (nodos que el menú ofrece) + activar nodo | **hammer** | generaciones (hammer-upgrade/recover), overlay, DAG de wawa-memo. |
| 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 hammer) | un solo framebuffer, abierto una vez, nunca re-modeset. |
| 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)
**hammer → mirada**hammer escribe el grafo en un path bien conocido (propuesta:
**takana → mirada**takana escribe el grafo en un path bien conocido (propuesta:
`/run/hammer/boot-graph.json`, regenerable, world-readable):
```json
@@ -62,14 +62,14 @@ un nodo). Invariante de UX compartido: **cero parpadeo** de DRM desde la firmwar
}
```
**mirada → hammer** — mirada pide activar el nodo elegido (propuesta: escribir el id en
`/run/hammer/boot-select` **o** invocar `hammer boot activate <id>`). hammer valida el id contra el
**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 `id` es un hash, `parents` forma un DAG (no una lista lineal).
> El modelo in-place actual de hammer (`hammer-recover`: "no hay menú de generaciones tipo NixOS")
> se **sube** a un grafo navegable — es trabajo nuevo de hammer, no un refactor cosmético.
> 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)
@@ -102,18 +102,18 @@ vuelve a ser viable y soberano** — sin GRUB ni systemd. Es decir: squashfs+ove
es lo que *destraba* el arranque EFI soberano y de paso el cero-parpadeo (initrd chico = menos tiempo
muerto antes del takeover).
## Plan (lado hammer)
## Plan (lado takana)
1. **Este ADR + el handoff a tawasuyu** con el contrato (hecho en este commit).
2. **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 `hammer-root` por LABEL y
rootfs en RAM sino un **initramfs mínimo de pivote** (~770K) que resuelve `takana-root` por LABEL y
hace `switch_root` a 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 por `scripts/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.)
3. **Contrato de generaciones-grafo** ✅ (módulo `hammer_upgrade::boot_graph` + subcomando `hammer
3. **Contrato de generaciones-grafo** ✅ (módulo `hammer_upgrade::boot_graph` + subcomando `takana
boot`): el modelo in-place de generaciones se lee como un **grafo de estados** navegable (id =
`of_tree`, DAG por `parent`), `hammer boot graph` emite `/run/hammer/boot-graph.json` con el
formato del contrato, y `hammer boot activate <id>` (o `--from-select`) deja el sistema en un nodo
`of_tree`, DAG por `parent`), `takana boot graph` emite `/run/hammer/boot-graph.json` con el
formato del contrato, y `takana boot activate <id>` (o `--from-select`) deja el sistema en un nodo
(no-op si ya vivo · rollback paso a paso a un ancestro · nodo `recovery` sinté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.**
@@ -129,22 +129,22 @@ muerto antes del takeover).
(`\EFI\BOOT\BOOTX64.EFI`, ruta fallback removible, sin GRUB ni systemd-boot). Como no hay LoadOptions
en esa ruta, el `CONFIG_CMDLINE` horneado (`… 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 hammer,
- **host-side** `scripts/install-image-efi.sh` — GPT+ESP+root/store/state, ESP con mtools de takana,
ext4 con `mke2fs -d` bajo `unshare -r`; **validado VERDE en OVMF** (`scripts/efi-disk-boot-test.sh`:
firmware → BOOTX64.EFI → pivote → arje-zero PID1).
- **live-side** `scripts/hammer-live-install.sh` rama EFI — detecta `/sys/firmware/efi` y 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=1` bundlea `bzImage-efi`). **Validación 2-stage VERDE en OVMF**
(`scripts/efi-install-test.sh`): ISO live UEFI → `hammer-install` detecta `/sys/firmware/efi` y toma
(`scripts/efi-install-test.sh`): ISO live UEFI → `takana-install` detecta `/sys/firmware/efi` y 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).
## Consecuencias
- La frontera es un **fichero + un comando**, no una API compartida ⇒ los dos agentes avanzan sin
bloquearse. hammer puede emitir el grafo y probar EFI-stub sin esperar a mirada; mirada puede
maquetar el menú contra un `boot-graph.json` de ejemplo sin esperar a hammer.
bloquearse. takana puede emitir el grafo y probar EFI-stub sin esperar a mirada; mirada puede
maquetar el menú contra un `boot-graph.json` de 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