From 12e3b1d4d0992579e519c6e613ad469329ac0774 Mon Sep 17 00:00:00 2001 From: sergio Date: Sat, 23 May 2026 05:24:35 +0000 Subject: [PATCH] =?UTF-8?q?docs(renaser):=20plan=20de=20la=20Fase=2021=20?= =?UTF-8?q?=E2=80=94=20Atlas,=20el=20explorador=20del=20grafo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plan trazado para mañana. Tres capas: 1. Cuatro capacidades de host read-only (sys_grafo_manifiesto, sys_grafo_raiz, sys_grafo_recuperar, sys_grafo_hijo) que abren el grafo de objetos al userspace. Mismo patron de validacion de memoria que sys_net_*. 2. La app 'atlas': lienzo ~520x400, lee el grafo perezosamente con cache LRU de 16 entradas, navega con flechas / Enter / Backspace desde el manifiesto hacia los hijos. 3. Representacion radial: foco central con su firma cromatica (3 primeros bytes del hash), hijos en circulo, padre en cima si hay historial, cartela inferior con hash completo + tamaño + previsualizacion (texto si pasa el test ASCII, hex si no). Subfases 21a (caps), 21b (app navegable), 21c (paseo guiado). Sinergias y mejoras del sistema documentadas: dedup visual del grafo direccionado por contenido, integridad por uso (cada navegacion rehashea), validacion del almacen, camino natural a la escritura (Fase 22), encaje con el faro Akasha de la Fase 20 (quien recibe AnunciarRaiz puede explorar la raiz del par). Co-Authored-By: Claude Opus 4.7 --- renaser/FASE_21_ATLAS.md | 245 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 renaser/FASE_21_ATLAS.md diff --git a/renaser/FASE_21_ATLAS.md b/renaser/FASE_21_ATLAS.md new file mode 100644 index 0000000..85619df --- /dev/null +++ b/renaser/FASE_21_ATLAS.md @@ -0,0 +1,245 @@ +# Fase 21 — Atlas :: el explorador del grafo + +> *El paralelo a un explorador de archivos en un sistema que no tiene +> archivos. renaser nunca tuvo carpetas: tiene un grafo de objetos +> direccionado por contenido (BLAKE3 + postcard sobre virtio-blk). Lo +> que ha estado bajo el agua desde la Fase 7 sale a la superficie con +> una piel navegable.* + +--- + +## 1. La idea + +`atlas` es la primera app que **lee** del grafo persistente desde el +userspace. Hasta hoy, solo el kernel toca el grafo: las apps ven su +ranura `EntradaApp.estado` y nada más. Esta fase invierte la asimetría: +las apps reciben tres capacidades de inspección read-only y `atlas` las +ejerce mostrando, en pantalla, la topología del grafo —el manifiesto, +los bytecodes, los estados, las raíces— como un atlas de regiones +conectadas por aristas. + +La elección de la metáfora es deliberada. Un explorador de archivos +representa un sistema jerárquico (Unix) o un sistema con etiquetas y +versiones (Plan 9, Git). El grafo de renaser no es ninguno de los dos: +es un DAG inmutable, direccionado por contenido, con dos anclas +(`raiz`, `manifiesto`). El paralelo natural es un **atlas**: un mapa de +territorios donde cada nodo es una localidad, cada arista una frontera, +y la identidad de la localidad es su contenido —no un nombre—. + +## 2. Tres capas, tres responsabilidades + +### Capa 1 — capacidades de host `sys_grafo_*` (kernel/src/wasm/env.rs) + +Cuatro caps nuevas. Todas read-only. Validan rango contra la memoria +lineal del módulo. Idéntico patrón a los `sys_net_*` de la Fase 19. + +| Capacidad | Firma | Salida | Errores | +|---|---|---|---| +| `sys_grafo_manifiesto` | `(hash_out: u32) -> i32` | escribe 32 B del hash del manifiesto | `-1` sin ancla | +| `sys_grafo_raiz` | `(hash_out: u32) -> i32` | escribe 32 B del hash de la raíz | `-1` sin ancla | +| `sys_grafo_recuperar` | `(hash_in, datos_out, datos_cap, info_out) -> i32` | escribe `datos` truncados a `datos_cap` + struct `{datos_total_len, n_hijos, datos_escritos}` (12 B) en `info_out` | `-1` objeto no encontrado, `-2` rango fuera de memoria | +| `sys_grafo_hijo` | `(hash_in, indice, hash_out) -> i32` | escribe el hash del hijo `indice` | `-1` objeto ausente, `-2` índice fuera de rango | + +Punto delicado: `sys_grafo_recuperar` **rehashea** el payload servido +para que el módulo nunca reciba bytes corruptos atribuidos a un hash +que no les corresponde. El grafo ya hace esto en `almacen::recuperar`; +heredamos esa garantía sin código nuevo. + +### Capa 2 — la app `atlas` (apps/atlas/, wasm32) + +Lienzo natural ~520×400, en la misma paleta índigo del compositor. + +Estado mínimo: + +```rust +struct Vista { + foco: Hash, // nodo central + historial: Vec, // breadcrumbs para volver + cache: BTreeMap, // LRU pequeña (16 entradas) + seleccionado: usize, // qué hijo está marcado +} + +struct NodoInfo { + hash: Hash, + datos_preview: [u8; 96], // primeros bytes del payload + datos_len_total: u32, // tamaño completo del payload + n_hijos: u32, // cuántas aristas salen + hijos: Vec, // resueltos perezosamente +} +``` + +Flujo: + +1. Al `init`, llamar `sys_grafo_manifiesto` y empezar centrados ahí. +2. En cada `tick`, recoger teclas del compositor (ya las recibe la + ventana enfocada vía la Fase 8c) y mover el cursor / cambiar de + nodo en consecuencia. +3. Cualquier nodo nuevo se carga perezosamente con `sys_grafo_recuperar` + y se cachea. + +Navegación: + +- ← / → mueven el cursor entre hijos del foco actual. +- Enter desciende: el hijo seleccionado pasa a ser el nuevo foco; el + anterior va al historial. +- Backspace asciende: vuelve al último foco del historial. +- Esc reinicia al manifiesto. +- `r` re-ancla al `raiz` si la hay (toggle manifiesto / raíz). + +### Capa 3 — la pintura: «la elegancia de la graficación» + +La representación es **radial**, no lista. Es lo que distingue a +`atlas` de un explorador de archivos clásico: + +``` + ┌──────────────┐ + │ PADRE │ + │ hash... │ + └──────┬───────┘ + │ + ┌──────┴───────┐ + │ │ + │ FOCO │ ← centrado, grande + │ hash + meta │ + └──┬──┬──┬─────┘ + │ │ │ + ┌───────┘ │ └───────┐ + ┌───┴──┐ ┌────┴───┐ ┌──┴──┐ + │ HIJO │ │ HIJO │ │HIJO │ + │ ● │ │ ● │ │ ● │ ← círculo radial + └──────┘ └────────┘ └─────┘ +``` + +- **Foco**: en el centro del lienzo, recuadro grande con su hash + abreviado (primeros 8 hex), tamaño del payload, número de hijos. + Color del recuadro derivado de los primeros 3 bytes del hash —cada + objeto tiene su propia firma cromática estable—. +- **Hijos**: hasta 8 a la vez, dispuestos en círculo alrededor del foco. + Si hay más, una pequeña indicación `+N` en la circunferencia, con + teclas `[` / `]` para rotar la página de hijos visible. +- **Padre**: si hay historial, se dibuja como una pista flotante arriba, + conectada al foco por una arista vertical. +- **Aristas**: trazadas con Bresenham, color tenue (`TINTA_TENUE`); la + arista al hijo seleccionado se realza en `ETIQUETA`. +- **Cartela inferior**: la huella completa (32 hex), el tamaño total y + la previsualización del payload —si los primeros bytes pasan el test + ASCII imprimible, se muestra como texto; si no, como hex—. + +Cada **previsualización** es lo que cierra la metáfora: un objeto que +contiene texto (la bitácora persistida, el manifiesto serializado) se +delata por su payload legible. Uno binario muestra su silueta en hex. + +## 3. Subfases y criterios de cierre + +**21a — capacidades de host** *(≈ 1 sesión corta)* + +- [ ] Añadir las 4 caps al `wasm/env.rs` con sus rangos validados. +- [ ] Almacenar tabletas de tests: pedir el manifiesto y un nodo + conocido desde una app de prueba. +- [ ] Cerrar cuando una mini-app de prueba imprime el hash del + manifiesto en pantalla. + +**21b — la app `atlas` con navegación radial** *(≈ 1 sesión larga)* + +- [ ] Crate `apps/atlas/` con `font8x8`, `init` carga el manifiesto. +- [ ] Pintar el foco + sus hijos en círculo, sin selección. +- [ ] Teclado: cursor entre hijos, Enter descender, Backspace volver. +- [ ] Cartela con hash + tamaño + previsualización. +- [ ] Añadir a `GENESIS` (10ª app); `CELDA_TASKBAR_ANCHO` 116→106 px + para que las diez pestañas caben holgadas en 1280 px. +- [ ] Cerrar cuando se verifica en QEMU: arranca apuntando al + manifiesto, se navega a un hijo (un bytecode WASM), se ve el + tamaño y los primeros bytes; se vuelve con Backspace. + +**21c — el paseo guiado** *(opcional, si queda margen)* + +- [ ] Tecla `r` alterna entre las dos anclas (manifiesto / raíz). +- [ ] Indicador de la naturaleza del nodo: si su `datos` deserializa + como `Manifiesto`, mostrar «manifiesto»; si es un `.wasm` + (magic bytes `\0asm`), mostrar «bytecode»; si es texto ASCII, + mostrar «texto»; el resto «opaco». +- [ ] Pruebas integradas con la sustitución del disco (eliminar + `target/disk.img` y re-sembrar): `atlas` muestra el árbol de + semilla; tras editar en `bitacora`, `atlas` revela el nuevo + `estado` colgando del manifiesto. + +## 4. Qué eficiencia aprovecha + +- **Direccionamiento por contenido**: cuando dos apps comparten + bytecode (ej. dos `hola` clonadas), `atlas` lo muestra como UN nodo + con dos aristas entrantes —la dedup ya inherente al grafo se vuelve + visible—. +- **`almacen::recuperar` es O(1)**: el índice `BTreeMap` + ya está construido; cada navegación es una sola consulta + una + lectura de disco asíncrona (Fase 6.2). +- **Lazy loading + cache**: solo cargamos lo que está a un salto del + foco actual. El cache LRU de 16 entradas cubre la cuenca de + navegación humana. +- **El grafo es pequeño hoy** (~25 objetos). Una visualización completa + brute-force ya cabría —no necesitamos algoritmos sofisticados de + layout—. + +## 5. Qué mejora el sistema (no solo añade) + +1. **Primer caso de uso del grafo desde el userspace**. Asentamos el + patrón que toda app futura que quiera leer datos compartidos seguirá. +2. **Surface lo invisible**. El grafo era una propiedad estructural + indirecta; ahora es un objeto observable. Los bugs del almacén (si + los hubiera) se delatan visualmente. +3. **Validación de integridad por uso**. Cada navegación rehashea el + payload servido. Si un sector se corrompe en virtio-blk, `atlas` lo + descubrirá antes que ningún test. +4. **Camino natural a Fase 22 (escritura)**. Una vez que las apps leen, + la siguiente capacidad lógica es escribir: `sys_grafo_almacenar`, + `sys_grafo_anclar_raiz`. `atlas` se convertirá entonces en un + editor del grafo, no solo un explorador. +5. **Sinergia con Akasha** (Fase 20). El `AnunciarRaiz` que emite el + kernel anuncia el hash del manifiesto. Quien reciba el faro y use + `atlas` podrá descubrir qué tiene un par —el explorador y el + protocolo distribuido se complementan—. + +## 6. Riesgos y mitigaciones + +- **WASM lento bajo wasmi**: el descubrimiento de la Fase 20 (los apps + degradan la cadencia del reactor a ~600 ms/iter cuando hay muchos) + aplica aquí. `atlas` debe pintar UNA vez por interacción, no por + fotograma; usar el lienzo cacheado entre teclas. +- **Lienzo grande**: 520×400 a 4 B/píxel = 832 KiB. Cabe en el techo + de 4 MiB de cada app. Sin holgura para optimizar, pero suficiente. +- **Profundidad del grafo**: si el grafo creciera mucho, la navegación + con cursor entre 8 hijos visibles a la vez se quedaría corta. El + toggle `[` / `]` de rotación basta para hoy; un Fase 22 puede + introducir búsqueda por prefijo de hash. + +## 7. Cosecha visual prevista + +Al cerrar la Fase 21, una captura headless mostrará algo así (el +contenido exacto cambia con el grafo): + +``` +┌── atlas :: el explorador del grafo ──────────────────────┐ +│ │ +│ ┌─────────────┐ │ +│ │ raiz·?? │ (si la hay, en cima) │ +│ └──────┬──────┘ │ +│ │ │ +│ ┌──────┴──────┐ │ +│ │ MANIFIESTO │ ← foco │ +│ │ 2f3deadf... │ │ +│ │ 9 hijos │ │ +│ │ 510 bytes │ │ +│ └─┬─┬─┬─┬─┬───┘ │ +│ ┌─────────┘ │ │ │ │ └─────────┐ │ +│ ┌──┴──┐ ┌───┴─┴─┴───┐ ┌────┴──┐ │ +│ │ ● │ │ ● │ │ ● │ │ +│ │bita-│ │ pregon.. │ │ tonada│ ... │ +│ │cora │ │ │ │ │ │ +│ └─────┘ └─────────────┘ └───────┘ │ +│ │ +│ ─── 2f3deadfcc7dae25c4d... (32 hex) ─ 510 B ─ texto: ─── │ +│ {"version":1,"apps":[{"nombre":"bitacora","bytecode":.. │ +└──────────────────────────────────────────────────────────┘ +``` + +El sistema, que hasta hoy era un grafo silencioso, gana un mapa. +