Files
brahman/renaser/FASE7.md
T
sergio 900cd19e49 feat(renaser): Fase 7c — persistencia inter-sesión por-app
Cada app tiene ahora su propia ranura de estado en el Manifiesto de
Génesis (EntradaApp.estado): guarda y recobra lo suyo, sobrevive al
reinicio, y no pisa a ninguna otra app.

- apps/memoriosa: app WASM interactiva nueva. Cuenta las teclas pulsadas
  y persiste el recuento; al reiniciar despierta con su cuenta intacta.
  Reemplaza la 2a instancia de hola en la genesis.
- kernel: capacidades sys_estado_cargar / sys_estado_guardar. El kernel
  custodia un manifiesto VIVO (Mutex<Manifiesto>); fijar_estado lo muta,
  lo re-graba en el grafo y lo re-ancla. ContextoCapacidades.indice_app
  da a cada app su identidad — su ranura, jamas la de otra.
- cargar_userspace instala el manifiesto vivo antes de instanciar las
  apps: el init de una app ya consulta su estado al despertar.

Verificado en QEMU (screendump + sendkey): disco virgen -> memoriosa con
0 celdas, testigo verde; 5 pulsaciones -> 5 celdas; reinicio -> 5 celdas
intactas, testigo ambar (init releyo el estado del grafo).

Cierra la Fase 7 — el userspace nace del grafo, completa.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 18:43:58 +00:00

5.1 KiB

renaser — Fase 7 :: Apps que nacen del Grafo

Plan de ataque. Para el estado general ver ROADMAP.md; para la arquitectura, ARCHITECTURE.md.

El objetivo

Hoy el kernel lleva el userspace empotrado en su propio binario: main.rs tiene cuatro include_bytes! (app.wasm, discola.wasm, glotona.wasm, cronista.wasm) y cinco llamadas encender_app con regiones escritas a mano. Eso contradice la tesis de renaser: el almacenamiento es un grafo de objetos direccionado por contenido, no un binario monolítico.

La Fase 7 destruye el include_bytes! del userspace. Las aplicaciones pasan a ser objetos del grafo; el kernel las descubre, las verifica por su hash y las inyecta en caliente en wasmi. Qué apps arrancan, con qué cuota y en qué región lo dicta un Manifiesto de Génesis que también vive en el grafo. (La fuente font.ttf sigue empotrada: es del kernel, no del userspace.)

El problema de la génesis

Hay un huevo-y-gallina: el kernel lee el manifiesto para saber qué cargar, pero el manifiesto y el bytecode tienen que haber sido escritos antes. En un disco virgen no hay nada. Dos vías para sembrarlo:

  • A — el kernel siembra. En un disco sin manifiesto, el kernel graba en el grafo el bytecode de unas apps de génesis y un manifiesto por defecto. El bytecode de génesis llega vía include_bytes! — todavía.
  • B — boot siembra la imagen. El constructor de imagen (anfitrión) pre-puebla el disco con los objetos de bytecode y el manifiesto. El kernel jamás empotra una app.

B es el estado final puro, pero exige enseñarle a boot el formato del grafo (objetos, BLAKE3, log, superbloque) — trabajo de anfitrión considerable. Se ataca incremental, como las Fases 6.1a/b/c.

Sub-fases

7a — El Manifiesto y la carga desde el grafo (semilla por el kernel) — HECHA

  1. manifiesto.rs (andamiaje ya creado) — tipos Manifiesto / EntradaApp, (de)serialización postcard. Hoy es un módulo no_std del kernel; no se comparte con las apps (la frontera app↔kernel es el ABI WASM numérico, no tipos Rust).
  2. almacen.rs — el SuperBloque gana un segundo ancla, manifiesto: Option<Hash>, gemelo de raiz. VERSION sube de 1 a 2 (un disco v1 se reformatea, como ya hace init con discos ajenos). Getters manifiesto() / fijar_manifiesto().
  3. manifiesto::sembrar_genesis() — en un disco sin manifiesto: graba el bytecode de las apps de génesis (include_bytes!, sólo aquí), compone un Manifiesto por defecto con sus regiones y cuotas, lo graba y lo ancla.
  4. manifiesto::cargar() — lee el ancla del superbloque, recupera el objeto, lo deserializa.
  5. kernel_main — reemplaza las cinco encender_app escritas a mano por: cargar el manifiesto (o sembrarlo si falta) e iterar sus EntradaApp.
  6. wasm/mod.rs — el techo de memoria deja de ser la constante TECHO_MEMORIA y pasa a venir por-app del manifiesto (EntradaApp).
  7. Verificar en QEMU — la pantalla debe verse idéntica a la Fase 6.2 (cinco apps en sus regiones), pero ahora nacidas del grafo.

7b — La imagen sembrada por boot; muere include_bytes! HECHA

  • boot (anfitrión) aprende el formato del grafo y pre-puebla la imagen de disco con los objetos de bytecode + el manifiesto.
  • El kernel pierde los include_bytes! del userspace; sembrar_genesis se retira o queda como camino vacío de respaldo.

7c — Persistencia inter-sesión — HECHA

  • Una app (cronista evolucionada, o una nueva interactiva) guarda su estado mutado como un objeto nuevo del grafo al recibir teclado.
  • Cada EntradaApp usa su campo estado: Option<Hash> (ya previsto en el tipo). Al guardar, el kernel reescribe el manifiesto; al arrancar, le pasa ese estado a la app para que despierte donde quedó.
  • Probablemente una capacidad host nueva para que el kernel se entere del hash de estado nuevo que la app produjo.

Guardarraíles (directiva de la arquitecta)

  • No romper check-shared-cores.sh. Si algún tipo del manifiesto llegara a compartirse entre apps y kernel, debe habitar un núcleo estrictamente no_std. Hoy no se comparte: manifiesto.rs es kernel-only.
  • Errores recuperables con Result. Si el kernel lee del grafo un objeto de bytecode corrupto (su hash recomputado ≠ su id), almacen::recuperar ya lo detecta — devuelve Err. El kernel niega esa instanciación, pinta la baliza de desalojo en la región de esa app, y sigue levantando el resto. Un módulo podrido nunca tumba el arranque.

Estructura de archivos

archivo estado rol en la Fase 7
kernel/src/manifiesto.rs nuevo (7a) tipos Manifiesto/EntradaApp + (de)serialización + carga/siembra
kernel/src/almacen.rs a modificar (7a) SuperBloque.manifiesto, VERSION 2, getters
kernel/src/main.rs a modificar (7a) kernel_main itera el manifiesto en vez de include_bytes!
kernel/src/wasm/mod.rs a modificar (7a) techo de memoria por-app desde el manifiesto
boot/ a modificar (7b) siembra la imagen de disco con el grafo