gioser

tawasuyu/brahman

Rust 326TOML 123JSON 14Markdown 114554 Definitions

⎇ main renaser/FASE_21_ATLAS.md Markdown · 245 lines · 12.2 KB History raw

docs(renaser): plan de la Fase 21 — Atlas, el explorador del grafo 12e3b1d4d · sergio ·

1# Fase 21 — Atlas :: el explorador del grafo
2
3> *El paralelo a un explorador de archivos en un sistema que no tiene
4> archivos. renaser nunca tuvo carpetas: tiene un grafo de objetos
5> direccionado por contenido (BLAKE3 + postcard sobre virtio-blk). Lo
6> que ha estado bajo el agua desde la Fase 7 sale a la superficie con
7> una piel navegable.*
8
9---
10
11## 1. La idea
12
13`atlas` es la primera app que **lee** del grafo persistente desde el
14userspace. Hasta hoy, solo el kernel toca el grafo: las apps ven su
15ranura `EntradaApp.estado` y nada más. Esta fase invierte la asimetría:
16las apps reciben tres capacidades de inspección read-only y `atlas` las
17ejerce mostrando, en pantalla, la topología del grafo —el manifiesto,
18los bytecodes, los estados, las raíces— como un atlas de regiones
19conectadas por aristas.
20
21La elección de la metáfora es deliberada. Un explorador de archivos
22representa un sistema jerárquico (Unix) o un sistema con etiquetas y
23versiones (Plan 9, Git). El grafo de renaser no es ninguno de los dos:
24es un DAG inmutable, direccionado por contenido, con dos anclas
25(`raiz`, `manifiesto`). El paralelo natural es un **atlas**: un mapa de
26territorios donde cada nodo es una localidad, cada arista una frontera,
27y la identidad de la localidad es su contenido —no un nombre—.
28
29## 2. Tres capas, tres responsabilidades
30
31### Capa 1 — capacidades de host `sys_grafo_*` (kernel/src/wasm/env.rs)
32
33Cuatro caps nuevas. Todas read-only. Validan rango contra la memoria
34lineal del módulo. Idéntico patrón a los `sys_net_*` de la Fase 19.
35
36| Capacidad | Firma | Salida | Errores |
37|---|---|---|---|
38| `sys_grafo_manifiesto` | `(hash_out: u32) -> i32` | escribe 32 B del hash del manifiesto | `-1` sin ancla |
39| `sys_grafo_raiz` | `(hash_out: u32) -> i32` | escribe 32 B del hash de la raíz | `-1` sin ancla |
40| `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 |
41| `sys_grafo_hijo` | `(hash_in, indice, hash_out) -> i32` | escribe el hash del hijo `indice` | `-1` objeto ausente, `-2` índice fuera de rango |
42
43Punto delicado: `sys_grafo_recuperar` **rehashea** el payload servido
44para que el módulo nunca reciba bytes corruptos atribuidos a un hash
45que no les corresponde. El grafo ya hace esto en `almacen::recuperar`;
46heredamos esa garantía sin código nuevo.
47
48### Capa 2 — la app `atlas` (apps/atlas/, wasm32)
49
50Lienzo natural ~520×400, en la misma paleta índigo del compositor.
51
52Estado mínimo:
53
54```rust
55struct Vista {
56    foco: Hash,                      // nodo central
57    historial: Vec<Hash>,            // breadcrumbs para volver
58    cache: BTreeMap<Hash, NodoInfo>, // LRU pequeña (16 entradas)
59    seleccionado: usize,             // qué hijo está marcado
60}
61
62struct NodoInfo {
63    hash: Hash,
64    datos_preview: [u8; 96],   // primeros bytes del payload
65    datos_len_total: u32,      // tamaño completo del payload
66    n_hijos: u32,              // cuántas aristas salen
67    hijos: Vec<Hash>,          // resueltos perezosamente
68}
69```
70
71Flujo:
72
731. Al `init`, llamar `sys_grafo_manifiesto` y empezar centrados ahí.
742. En cada `tick`, recoger teclas del compositor (ya las recibe la
75   ventana enfocada vía la Fase 8c) y mover el cursor / cambiar de
76   nodo en consecuencia.
773. Cualquier nodo nuevo se carga perezosamente con `sys_grafo_recuperar`
78   y se cachea.
79
80Navegación:
81
82- ← / → mueven el cursor entre hijos del foco actual.
83- Enter desciende: el hijo seleccionado pasa a ser el nuevo foco; el
84  anterior va al historial.
85- Backspace asciende: vuelve al último foco del historial.
86- Esc reinicia al manifiesto.
87- `r` re-ancla al `raiz` si la hay (toggle manifiesto / raíz).
88
89### Capa 3 — la pintura: «la elegancia de la graficación»
90
91La representación es **radial**, no lista. Es lo que distingue a
92`atlas` de un explorador de archivos clásico:
93
94```
95                       ┌──────────────┐
96                       │   PADRE      │
97                       │  hash...     │
98                       └──────┬───────┘
99                              │
100                       ┌──────┴───────┐
101                       │              │
102                       │    FOCO      │      ← centrado, grande
103                       │  hash + meta │
104                       └──┬──┬──┬─────┘
105                          │  │  │
106                  ┌───────┘  │  └───────┐
107              ┌───┴──┐  ┌────┴───┐  ┌──┴──┐
108              │ HIJO │  │  HIJO  │  │HIJO │
109              │ ●    │  │   ●    │  │  ●  │   ← círculo radial
110              └──────┘  └────────┘  └─────┘
111```
112
113- **Foco**: en el centro del lienzo, recuadro grande con su hash
114  abreviado (primeros 8 hex), tamaño del payload, número de hijos.
115  Color del recuadro derivado de los primeros 3 bytes del hash —cada
116  objeto tiene su propia firma cromática estable—.
117- **Hijos**: hasta 8 a la vez, dispuestos en círculo alrededor del foco.
118  Si hay más, una pequeña indicación `+N` en la circunferencia, con
119  teclas `[` / `]` para rotar la página de hijos visible.
120- **Padre**: si hay historial, se dibuja como una pista flotante arriba,
121  conectada al foco por una arista vertical.
122- **Aristas**: trazadas con Bresenham, color tenue (`TINTA_TENUE`); la
123  arista al hijo seleccionado se realza en `ETIQUETA`.
124- **Cartela inferior**: la huella completa (32 hex), el tamaño total y
125  la previsualización del payload —si los primeros bytes pasan el test
126  ASCII imprimible, se muestra como texto; si no, como hex—.
127
128Cada **previsualización** es lo que cierra la metáfora: un objeto que
129contiene texto (la bitácora persistida, el manifiesto serializado) se
130delata por su payload legible. Uno binario muestra su silueta en hex.
131
132## 3. Subfases y criterios de cierre
133
134**21a — capacidades de host** *(≈ 1 sesión corta)*
135
136- [ ] Añadir las 4 caps al `wasm/env.rs` con sus rangos validados.
137- [ ] Almacenar tabletas de tests: pedir el manifiesto y un nodo
138      conocido desde una app de prueba.
139- [ ] Cerrar cuando una mini-app de prueba imprime el hash del
140      manifiesto en pantalla.
141
142**21b — la app `atlas` con navegación radial** *(≈ 1 sesión larga)*
143
144- [ ] Crate `apps/atlas/` con `font8x8`, `init` carga el manifiesto.
145- [ ] Pintar el foco + sus hijos en círculo, sin selección.
146- [ ] Teclado: cursor entre hijos, Enter descender, Backspace volver.
147- [ ] Cartela con hash + tamaño + previsualización.
148- [ ] Añadir a `GENESIS` (10ª app); `CELDA_TASKBAR_ANCHO` 116→106 px
149      para que las diez pestañas caben holgadas en 1280 px.
150- [ ] Cerrar cuando se verifica en QEMU: arranca apuntando al
151      manifiesto, se navega a un hijo (un bytecode WASM), se ve el
152      tamaño y los primeros bytes; se vuelve con Backspace.
153
154**21c — el paseo guiado** *(opcional, si queda margen)*
155
156- [ ] Tecla `r` alterna entre las dos anclas (manifiesto / raíz).
157- [ ] Indicador de la naturaleza del nodo: si su `datos` deserializa
158      como `Manifiesto`, mostrar «manifiesto»; si es un `.wasm`
159      (magic bytes `\0asm`), mostrar «bytecode»; si es texto ASCII,
160      mostrar «texto»; el resto «opaco».
161- [ ] Pruebas integradas con la sustitución del disco (eliminar
162      `target/disk.img` y re-sembrar): `atlas` muestra el árbol de
163      semilla; tras editar en `bitacora`, `atlas` revela el nuevo
164      `estado` colgando del manifiesto.
165
166## 4. Qué eficiencia aprovecha
167
168- **Direccionamiento por contenido**: cuando dos apps comparten
169  bytecode (ej. dos `hola` clonadas), `atlas` lo muestra como UN nodo
170  con dos aristas entrantes —la dedup ya inherente al grafo se vuelve
171  visible—.
172- **`almacen::recuperar` es O(1)**: el índice `BTreeMap<Hash, sector>`
173  ya está construido; cada navegación es una sola consulta + una
174  lectura de disco asíncrona (Fase 6.2).
175- **Lazy loading + cache**: solo cargamos lo que está a un salto del
176  foco actual. El cache LRU de 16 entradas cubre la cuenca de
177  navegación humana.
178- **El grafo es pequeño hoy** (~25 objetos). Una visualización completa
179  brute-force ya cabría —no necesitamos algoritmos sofisticados de
180  layout—.
181
182## 5. Qué mejora el sistema (no solo añade)
183
1841. **Primer caso de uso del grafo desde el userspace**. Asentamos el
185   patrón que toda app futura que quiera leer datos compartidos seguirá.
1862. **Surface lo invisible**. El grafo era una propiedad estructural
187   indirecta; ahora es un objeto observable. Los bugs del almacén (si
188   los hubiera) se delatan visualmente.
1893. **Validación de integridad por uso**. Cada navegación rehashea el
190   payload servido. Si un sector se corrompe en virtio-blk, `atlas` lo
191   descubrirá antes que ningún test.
1924. **Camino natural a Fase 22 (escritura)**. Una vez que las apps leen,
193   la siguiente capacidad lógica es escribir: `sys_grafo_almacenar`,
194   `sys_grafo_anclar_raiz`. `atlas` se convertirá entonces en un
195   editor del grafo, no solo un explorador.
1965. **Sinergia con Akasha** (Fase 20). El `AnunciarRaiz` que emite el
197   kernel anuncia el hash del manifiesto. Quien reciba el faro y use
198   `atlas` podrá descubrir qué tiene un par —el explorador y el
199   protocolo distribuido se complementan—.
200
201## 6. Riesgos y mitigaciones
202
203- **WASM lento bajo wasmi**: el descubrimiento de la Fase 20 (los apps
204  degradan la cadencia del reactor a ~600 ms/iter cuando hay muchos)
205  aplica aquí. `atlas` debe pintar UNA vez por interacción, no por
206  fotograma; usar el lienzo cacheado entre teclas.
207- **Lienzo grande**: 520×400 a 4 B/píxel = 832 KiB. Cabe en el techo
208  de 4 MiB de cada app. Sin holgura para optimizar, pero suficiente.
209- **Profundidad del grafo**: si el grafo creciera mucho, la navegación
210  con cursor entre 8 hijos visibles a la vez se quedaría corta. El
211  toggle `[` / `]` de rotación basta para hoy; un Fase 22 puede
212  introducir búsqueda por prefijo de hash.
213
214## 7. Cosecha visual prevista
215
216Al cerrar la Fase 21, una captura headless mostrará algo así (el
217contenido exacto cambia con el grafo):
218
219```
220┌── atlas :: el explorador del grafo ──────────────────────┐
221│                                                          │
222│                  ┌─────────────┐                         │
223│                  │   raiz·??   │ (si la hay, en cima)    │
224│                  └──────┬──────┘                         │
225│                         │                                │
226│                  ┌──────┴──────┐                         │
227│                  │ MANIFIESTO  │  ← foco                 │
228│                  │ 2f3deadf... │                         │
229│                  │  9 hijos    │                         │
230│                  │ 510 bytes   │                         │
231│                  └─┬─┬─┬─┬─┬───┘                         │
232│         ┌─────────┘ │ │ │ │ └─────────┐                  │
233│      ┌──┴──┐    ┌───┴─┴─┴───┐    ┌────┴──┐               │
234│      │ ●   │    │     ●      │   │   ●   │               │
235│      │bita-│    │  pregon.. │   │ tonada│  ...           │
236│      │cora │    │             │   │       │               │
237│      └─────┘    └─────────────┘   └───────┘               │
238│                                                          │
239│ ─── 2f3deadfcc7dae25c4d... (32 hex) ─ 510 B ─ texto: ─── │
240│ {"version":1,"apps":[{"nombre":"bitacora","bytecode":..  │
241└──────────────────────────────────────────────────────────┘
242```
243
244El sistema, que hasta hoy era un grafo silencioso, gana un mapa.
245

FASE_21_ATLAS.md

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.

CapacidadFirmaSalidaErrores
sys_grafo_manifiesto(hash_out: u32) -> i32escribe 32 B del hash del manifiesto-1 sin ancla
sys_grafo_raiz(hash_out: u32) -> i32escribe 32 B del hash de la raíz-1 sin ancla
sys_grafo_recuperar(hash_in, datos_out, datos_cap, info_out) -> i32escribe 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) -> i32escribe 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:

struct Vista {
    foco: Hash,                      // nodo central
    historial: Vec<Hash>,            // breadcrumbs para volver
    cache: BTreeMap<Hash, NodoInfo>, // 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<Hash>,          // 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:

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
              └──────┘  └────────┘  └─────┘

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)

21b — la app atlas con navegación radial (≈ 1 sesión larga)

21c — el paseo guiado (opcional, si queda margen)

4. Qué eficiencia aprovecha

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

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.