Files
brahman/renaser/CHANGELOG.md
T
sergio 4f31146533 feat(renaser): Fase 7 — apertura: plan y andamiaje del Manifiesto de Génesis
Abre la Fase 7 («apps que nacen del grafo»): destierra el include_bytes!
del userspace — las apps pasan a ser objetos del grafo, gobernadas por
un Manifiesto de Génesis que también vive en el grafo.

Este commit es sólo plan + andamiaje; el kernel se comporta idéntico a
la Fase 6.2.

- FASE7.md — el plan de ataque: el problema de la génesis, las
  sub-fases 7a/7b/7c y los guardarraíles.
- kernel/src/manifiesto.rs — andamiaje: tipos Manifiesto/EntradaApp +
  (de)serialización postcard completos; cargar/sembrar_genesis son
  esbozos hasta la 7a. Declarado en main.rs, aún sin cablear a
  kernel_main (#![allow(dead_code)] temporal).

CHANGELOG y DIARIO al día.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 15:02:19 +00:00

24 KiB
Raw Blame History

Registro de cambios — renaser

Registro técnico detallado, fase a fase, en orden cronológico. Formato inspirado en Keep a Changelog. Para la crónica en lenguaje llano, ver DIARIO.md; para el estado y los planes, ROADMAP.md.


Fase 1 — El primer microsegundo — 2026-05-21

Infraestructura

  • Espacio de trabajo Cargo, kernel/Cargo.toml, .cargo/config.toml, rust-toolchain.toml.
  • Target inicial: especificación JSON propia x86_64-renaser.json — PIC, soft-float, sin SSE, enlazador lld.

Añadido

  • kernel/src/main.rs: punto de entrada con el macro entry_point! de bootloader_api 0.11.
  • Adopción y verificación con seguridad de tipos del framebuffer GOP (ancho, alto, formato de píxel, stride).
  • Lienzo intermedio estático de 8 MiB en .bss, alineado a página: la técnica de doble búfer para evitar parpadeos.
  • #[panic_handler] que dibuja una franja roja directamente sobre el framebuffer mediante escrituras volátiles.
  • Dependencias: bootloader_api 0.11, x86_64 0.15, embedded-graphics 0.8.

Notas

  • Corrección clave: bootloader (constructor de imagen, lado anfitrión) no es bootloader_api (la API no_std que consume el kernel).

Fase 1.5 — Empaquetado y arranque — 2026-05-21

Cambiado

  • Migración del target del kernel: de la JSON propia x86_64-renaser.json al target nativo precompilado x86_64-unknown-none. Elimina build-std y la burocracia de compilador asociada.

Añadido

  • Miembro boot/: orquestador de anfitrión. Dependencia de artefacto (RFC 3028) sobre el kernel; construcción de la imagen de disco UEFI con bootloader::UefiBoot; lanzador de QEMU.

Toolchain

  • Instalación de la toolchain nightly (la máquina solo tenía la estable).

Corregido

  • Los nightly recientes exigen -Zjson-target-spec para usar specs JSON (resuelto al migrar al target nativo).
  • Sintaxis del acelerador de QEMU: -machine q35,accel=kvm:tcg.

Verificado

  • Arranque en QEMU: superficie índigo limpia a 1280×800.
  • Baliza de pánico (franja roja) confirmada inyectando un pánico de prueba.

Fase 2.0 — Cimientos del manejo de fallos — 2026-05-21

Añadido

  • kernel/src/gdt.rs: GDT propia, TSS y un stack de emergencia (IST) reservado para el manejador de doble fallo.
  • kernel/src/interrupts.rs: IDT con manejadores de excepción de CPU. El breakpoint (#BP) es recuperable; #UD, #DE, #GP, #PF y #DF son fatales y encienden la baliza.
  • #![feature(abi_x86_interrupt)].

Corregido

  • La GDT debe recargar los registros SS/DS/ES con un segmento de datos del kernel: el cargador deja SS = 0x10, valor que en la GDT nueva pasa a ser el descriptor del TSS; el primer iretq de una rutina de excepción provocaba un #GP. Diagnosticado con la traza -d int de QEMU.

Verificado

  • Excepción int3 atrapada y superada; línea-latido teal dibujada como prueba.

Fase 2.1 — Interrupciones de hardware — 2026-05-21

Añadido

  • kernel/src/pic.rs: remapeo del par 8259 (PIC) fuera del rango de las excepciones (vectores 0x20+); programación del temporizador PIT a 100 Hz; IRQ1 de teclado.
  • Bucle de render en kernel_main, despertado por el temporizador, en sustitución del hlt estático.

Verificado

  • La línea-latido se anima (temporizador en marcha); las pulsaciones de teclado inyectadas cambian el cuadro-eco (teclado en marcha).

Fase 3 — Memoria dinámica y reactor asíncrono — 2026-05-21

Añadido

  • kernel/src/memory/: linked_list_allocator como #[global_allocator] sobre una región estática en .bss.
  • #[alloc_error_handler]: franja naranja de agotamiento de memoria. #![feature(alloc_error_handler)].
  • kernel/src/async_system/: reactor cooperativo — Executor, Task/TaskId, Waker (vía alloc::task::Wake) y ScancodeStream.
  • kernel/src/texto.rs: rasterización de tipografía vectorial con fontdue; TTF Adwaita Mono empotrada con include_bytes!.
  • Dependencias: linked_list_allocator 0.10, spin 0.9, crossbeam-queue 0.3, futures-util 0.3, fontdue 0.9.

Cambiado

  • Heap ampliado de 16 MiB a 64 MiB: fontdue, al analizar una tipografía real, agotaba los 16 MiB iniciales. El #[alloc_error_handler] lo delató pintando la franja naranja — el guardarraíl funcionó en silicio real.

Corregido

  • El modo no_std de fontdue está condicionado a su feature hashbrown; sin ella recae en std. Se fija default-features = false, features = ["hashbrown"].

Verificado

  • Rótulo de bienvenida rasterizado al arranque; el texto tecleado aparece en vivo.

Fase 4 — El escudo de aislamiento WASM — 2026-05-21

Añadido

  • kernel/src/wasm/: intérprete wasmi 1.0.9 en modo no_std. env.rs define la matriz de capacidades — exactamente dos funciones de host: sys_render_frame(ptr, len), con validación infranqueable de los límites de la memoria lineal, y sys_get_scancode().
  • apps/hello_wasm/: primera aplicación del userspace — módulo wasm32-unknown-unknown (cdylib), un cuadrado móvil dirigido por teclado. Se empotra en el kernel con include_bytes!.
  • Dependencia: wasmi 1.0.

Cambiado

  • El kernel se EXCLUYE del espacio de trabajo (exclude = ["kernel", "apps"]): al añadir wasmi, cargo build intentaba compilar el kernel para el anfitrión y fallaba por un símbolo _start duplicado. El kernel pasa a construirse únicamente como dependencia de artefacto de boot.

Corregido

  • wasmi no_std necesita default-features = false, features = ["hash-collections"].
  • wasmi 1.0.9 usa Linker::instantiate_and_start (no existe instantiate).

Verificado

  • La aplicación WASM pinta su propia superficie y responde a las pulsaciones de teclado inyectadas, sin más vía hacia el kernel que las dos capacidades.

Mantenimiento — Estructura, documentación e integración — 2026-05-21

Cambiado

  • Refactorización: main.rs dividido de 692 a ~155 líneas. Se extraen los módulos sync.rs, grafico.rs, consola.rs y baliza.rs. Sin cambios de comportamiento (verificado en QEMU).

Añadido

  • Documentación: CLAUDE.md, README.md, ARCHITECTURE.md, ROADMAP.md, CHANGELOG.md y DIARIO.md.
  • Integración con git: repositorio inicializado, remoto origin en Gitea, .gitignore.

Seguridad

  • renaser.txt —un borrador de trabajo que contenía una credencial— se subió por error en el commit inicial. Se purgó de todo el historial con git filter-branch y se reescribió el remoto con push --force. La credencial expuesta debe rotarse.

Fase 5 — Multitarea cooperativa, guardarrail de fuel y reloj — 2026-05-22

Unificación de la Fase 3 (reactor) y la Fase 4 (WASM): el userspace deja de ser una sola app que monopoliza la CPU y pasa a ser un conjunto de aplicaciones cooperativas, aisladas también en el TIEMPO.

Añadido

  • kernel/src/async_system/reloj.rs: convierte la IRQ0 (PIT, 100 Hz) en una primitiva asíncrona. CONTADOR_PULSOS (AtomicU64) y EsperaFrame, un Future que se resuelve en el siguiente pulso — la unidad de cesión cooperativa del userspace. Censo de wakers tras Mutex, drenado por la IRQ0.
  • kernel/src/wasm: ABI de fotograma. AplicacionWasm —instancia PERSISTENTE entre fotogramas (Store + TypedFunc<(), ()> + región)— sustituye al wasm::ejecutar de fuego-y-olvido. El módulo del userspace exporta ahora init() (una vez) y tick() (un fotograma, y retorna).
  • Escudo de combustible: Engine con Config::consume_fuel(true) y CompilationMode::Eager (el fuel mide solo ejecución). Presupuesto recargado antes de cada tickFUEL_ARRANQUE (20 M) y FUEL_FOTOGRAMA (2 M).
  • kernel/src/wasm/env.rs: capacidad sys_render_frame con regiones de dibujo — cada fotograma se compone desplazado por el (offset_x, offset_y) de la app; un tamaño ajeno a la región se rechaza. Canal de teclado por aplicación: la IRQ1 difunde cada scancode a TODOS los canales, de modo que varias apps reciben la entrada en paralelo sin robársela.
  • kernel/src/grafico.rs: RegionPantalla y Color::DESALOJO (púrpura).
  • apps/discola/: aplicación WASM construida para portarse mal — su tick es un bucle cerrado. Demuestra el guardarrail de fuel en vivo.

Cambiado

  • apps/hello_wasm: migrada al ABI init/tick; su lienzo se dimensiona a la región (480×560). El estado del cuadrado persiste en su memoria lineal.
  • interrupts.rs: la IRQ0 avanza el reloj; la IRQ1 difunde a los canales.
  • consola.rs: volcar_marco compone en una sub-región; pintar_desalojo tatúa la baliza púrpura.
  • Contención de fallos: el subsistema WASM ya no usa .expect(). Toda falla —carga, instanciación, desbordamiento, agotamiento de fuel— se devuelve como Result; la tarea desaloja la app (baliza púrpura) y el kernel sigue vivo.

Verificado

  • QEMU: tres apps concurrentes. Dos instancias de hello_wasm (mismo bytecode, regiones izquierda y derecha) renderizan y responden a W/A/S/D en paralelo, con movimiento idéntico. La app díscola es desalojada en su primer fotograma por agotamiento de combustible: su región queda púrpura y el sistema —kernel y apps vecinas— no sufre un solo sobresalto.

Fase 6.0 — Cuotas de memoria y ciclo de vida del userspace — 2026-05-22

El aislamiento de las aplicaciones, que la Fase 5 hizo temporal (combustible), se completa ahora en la dimensión espacial (memoria) y se cierra la fuga de recursos del ciclo de vida.

Añadido

  • Techo de memoria lineal por aplicación: 4 MiB. wasm/mod.rs construye un StoreLimits (StoreLimitsBuilder::memory_size + trap_on_grow_failure) y lo liga al Store con Store::limiter. Un memory.grow que rebase la cuota se convierte en trampa; el kernel la captura y desaloja la app.
  • FallaApp::SinMemoria y Color::DESALOJO_MEMORIA (amarillo pálido). El desalojo distingue la causa por color: púrpura (tiempo/aborto), amarillo (memoria). La clasificación es robusta — Error::as_trap_code() da un código público y unívoco: TrapCode::GrowthOperationLimited.
  • Drop para AplicacionWasm: al morir una app desalojada, su canal de teclado se da de baja del censo de difusión de la IRQ1 — cierra la fuga señalada en la Fase 5. async_system::teclado se reorganiza en crear_canal / registrar_canal / cerrar_canal; el canal se inscribe al FINAL de la carga, de modo que una carga fallida no deja canales huérfanos.
  • apps/glotona/: aplicación WASM construida para devorar memoria — su tick invoca memory.grow sin freno. Demuestra el guardarrail espacial en vivo.

Verificado

  • QEMU: cuatro apps concurrentes. Las dos hello_wasm renderizan y responden al teclado en paralelo; la app díscola es desalojada por combustible (franja púrpura) y la app glotona por cuota de memoria (franja amarilla), ambas en su primer fotograma, sin que el kernel ni las apps honradas se inmuten.

Fase 6.1a — Sonda PCI y disco de pruebas — 2026-05-22

Primer paso de la estrategia incremental hacia el almacenamiento: derribar el muro del descubrimiento de hardware antes de diseñar nada encima.

Añadido

  • kernel/src/drivers/: nuevo subsistema de drivers. pci.rs enumera el bus PCI por fuerza bruta mediante el mecanismo de configuración #1 —puertos de E/S 0xCF8 (dirección) y 0xCFC (datos)—; recorre buses y dispositivos leyendo el Vendor/Device ID, y localiza el disco virtio-blk (vendor 0x1AF4, device 0x1001/0x1042), devolviendo su ubicación y sus seis BARs.
  • kernel_main: tras fundar la consola, sondea el bus PCI y deja constancia visual del hallazgo.

Cambiado

  • boot/src/main.rs: forja un disco de pruebas target/disk.img (fichero disperso de 32 MiB; se respeta si ya existe) y lo adjunta a QEMU como virtio-blk-pci. Corrección de plataforma: la máquina q35 es x86_64 y exige la transmisión PCI; virtio-blk-device (su gemelo MMIO) es de ARM.

Verificado

  • QEMU: el kernel enumera el bus y reporta en pantalla virtio-blk en bus 0 dev 3 :: BAR0 E/S 0x6000 — un dispositivo virtio-blk transicional (device 0x1001), con su BAR0 en espacio de E/S. El muro del descubrimiento PCI queda derribado; las cuatro apps del userspace siguen operando sin alteración.

Fase 6.1b — HAL, DMA y lectura del sector 0 — 2026-05-22

Segundo paso del sustrato de almacenamiento: el diálogo real con el disco. El kernel monta el dispositivo virtio-blk y lee su primer sector por DMA.

Añadido

  • Dependencia virtio-drivers 1.13 (no_std, default-features = false, feature alloc).
  • kernel/src/drivers/disco.rs:
    • Asignador de marcos «bump» — reparte páginas físicas de 4 KiB para el DMA, tomadas de la mayor región de RAM libre que el cargador reporta. No libera: suficiente para una sonda (la gestión fina llegará con el grafo).
    • KernelHal — implementa el trait Hal de virtio-drivers. dma_alloc entrega marcos físicos a cero; mmio_phys_to_virt traduce los BARs (el cargador mapea ≥ 4 GiB de memoria física, que cubre todo MMIO de PCI); share/unshare usan un buffer rebote para que cualquier región del kernel pueda viajar al dispositivo.
    • montar_y_leer_sector0 — enumera el bus, habilita E/S + memoria + bus-master, monta el PciTransport y el VirtIOBlk, y lee el sector 0 por sondeo del used ring (sin depender aún de interrupciones).
  • kernel/src/drivers/pci.rs: reescrito como CamPuertos, la implementación de ConfigurationAccess de virtio-drivers sobre los puertos 0xCF8/0xCFC.
  • kernel_main captura physical_memory_offset y la región de RAM de BootInfo, funda el subsistema de disco y reporta el resultado de la sonda.

Cambiado

  • boot/src/main.rs: al forjar el disco de pruebas graba una firma (renaser-6.1b) en su sector 0 — el testigo del viaje de ida y vuelta.

Verificado

  • QEMU: el kernel reporta virtio-blk :: bus 0 dev 3 :: 65536 sectores :: s0=renaser-6.1b. La firma grabada por el anfitrión se lee de vuelta intacta: descubrimiento PCI, transporte, DMA y transferencia funcionan de punta a punta. Las cuatro apps del userspace siguen operando sin alteración.

Fase 6.1c — El grafo de objetos direccionado por contenido — 2026-05-22

Tercer y último paso del sustrato de almacenamiento. El disco deja de ser un dispositivo que se sondea y pasa a ser una MEMORIA QUE PERDURA: un grafo dirigido acíclico de objetos direccionados por contenido — no un sistema de archivos plano POSIX.

Añadido

  • kernel/src/almacen.rs — el grafo de objetos:
    • Objeto — una carga útil de bytes (datos) y una lista de aristas (hijos: hashes de otros objetos). Las aristas hacen del almacén un DAG.
    • Direccionamiento por contenido — la identidad de un objeto es el hash BLAKE3 de su forma serializada. De ello se siguen dos propiedades que un sistema de archivos jamás regala: INTEGRIDAD (el contenido leído se rehashea y se verifica contra el hash pedido) y DEDUPLICACIÓN (contenido idéntico produce el mismo hash; se almacena una sola vez).
    • Disco como log — el sector 0 es el superbloque (magia RENASGRF, versión, cursor del log y hash de la raíz); tras él se anexan los registros de objetos, [longitud u32 LE][payload postcard][relleno a cero]. Un índice en memoria (hash -> sector) se reconstruye al arrancar recorriendo el log de cabo a rabo.
    • API: init —monta el disco, lee o forja el superbloque, reconstruye el índice—, almacenar, recuperar, raiz y fijar_raiz.
  • Cinco capacidades nuevas del host en wasm/env.rssys_object_put, sys_object_datos, sys_object_hijo, sys_object_raiz y sys_object_fijar_raiz —, con la misma validación infranqueable de límites de la memoria lineal que sys_render_frame. Distinguen dos clases de fallo: un puntero inválido ABORTA la app —es su culpa, se traduce en trampa—; un fallo del almacenamiento le devuelve un código de error negativo —no lo es—.
  • apps/cronista/ — la primera aplicación del userspace que escribe en el almacenamiento PERSISTENTE. En cada arranque consulta la raíz del grafo, graba un objeto nuevo —datos: el número de arranque; hijos: la raíz anterior, el eslabón del DAG— y lo corona como raíz. Pinta una celda por arranque registrado y un testigo de integridad que recorre la cadena entera.
  • Dependencias: serde 1 y postcard 1 (serialización binaria compacta, el formato que viaja al disco) y blake3 1 (la función hash). Las tres no_std.

Cambiado

  • kernel/src/drivers/disco.rs reescrito para un sustrato PERMANENTE:
    • El asignador de marcos «bump» de la Fase 6.1b cede el paso a uno de MAPA DE BITS con liberación real. dma_dealloc y unshare devuelven los marcos a la arena: un almacén vivo, con su trasiego incesante de DMA, ya no la agota.
    • El VirtIOBlk deja de montarse y destruirse en cada llamada: se monta UNA vez y queda tras un Mutex global. leer_sectores / escribir_sectores exponen la E/S de bloques — el disco deja de ser de solo lectura. Se retira montar_y_leer_sector0, la sonda de un solo uso de la Fase 6.1b.
  • boot/src/main.rs: el disco de pruebas pasa a ser el disco de objetos. Ya no se le graba una firma — se forja virgen, a cero, y el kernel lo formatea la primera vez que no halle el superbloque.
  • main.rs: informar_disco (la sonda de la Fase 6.1b) se sustituye por informar_almacen, que funda el grafo. El userspace pasa de cuatro a cinco apps; las regiones de discola y glotona se reajustan para alojar a cronista.

Notas

  • blake3 forzado a escalar. El target del kernel corre sin SSE; un camino SIMD de blake3 activado por detección en tiempo de ejecución ejecutaría instrucciones que la CPU, sin CR4.OSFXSR, rechazaría con un #UD. Se fija blake3 con pure + los cuatro no_* (sse2, sse41, avx2, avx512): implementación puramente escalar, sin SIMD ni ensamblador.

Verificado

  • QEMU, TRES arranques consecutivos sobre el mismo disco persistente: la app cronista pinta 1, luego 2, luego 3 celdas — la cuenta de arranques sobrevive a los reinicios porque vive en el grafo, en el disco, no en la RAM. El testigo de integridad queda VERDE en los tres: el DAG entero se recorre, de la raíz al primer eslabón, y su profundidad cuadra con la cuenta. El superbloque en disco confirma la magia RENASGRF, versión 1, cursor 4 y la raíz del tercer arranque; el registro del primer arranque guarda datos = 1 y cero hijos. Las otras cuatro apps siguen su curso sin alteración — las dos hello_wasm renderizando, discola desalojada en púrpura, glotona en amarillo.

Fase 6.2 — E/S de disco asíncrona por interrupción — 2026-05-22

La Fase 6.1 hizo hablar al disco, pero por SONDEO: el procesador se quedaba en espera activa vigilando el used ring de virtio, incapaz de atender nada más. La 6.2 libera el planificador cooperativo — la E/S de bloques pasa a ser REACTIVA, guiada por la interrupción física del dispositivo.

Añadido

  • EsperaDisco (drivers/disco.rs): una transferencia de bloques expresada como Future nativo. Posee sus buferes DMA —BlkReq, BlkResp y los datos, en el heap para una dirección estable—; su poll envía la petición por la API NO BLOQUEANTE de virtio-drivers (read_blocks_nb/write_blocks_nb), consulta el used ring (peek_used) y, si la transferencia sigue en vuelo, inscribe el waker y cede. leer_bloques/escribir_bloques lo construyen.
  • La IRQ del disco: montar descubre la línea de IRQ legada del dispositivo (registro «Interrupt Line», offset 0x3C del espacio de configuración PCI), registra un manejador en la IDT y abre la línea en el PIC. interrupts::irq_discodisco::atender_irq reconoce la interrupción en el dispositivo —leer su registro ISR baja la línea INTx— y despierta, vía un waker de ranura única, a la tarea que aguardaba el bloque.
  • bloquear_en — el puente para los contextos SÍNCRONOS (el arranque, las capacidades WASM, que no pueden .await): lleva un Future de disco hasta su final durmiendo la CPU con hlt —la despiertan la IRQ del disco o el temporizador, como red de seguridad—; jamás en espera activa con el sistema ya en marcha.
  • pic::desenmascarar / pic::vector_irq: abrir una línea concreta del par 8259 (con su cascada, si vive en el esclavo) y mapear línea → vector de IDT.
  • pci::linea_irq: leer el registro «Interrupt Line» de un dispositivo.
  • tarea_sonda_disco (main.rs): una tarea del reactor que lee el sector 0 de forma asíncrona — la prueba viva de que la IRQ conduce la E/S sin detener a las aplicaciones.

Cambiado

  • leer_sectores/escribir_sectores se reescriben sobre la maquinaria asíncrona (bloquear_en + EsperaDisco). El almacen y las capacidades sys_object_* NO cambian una línea: heredan la E/S por interrupción de forma transparente — la espera de disco deja de quemar ciclos en sondeo.
  • El VirtIOBlk pide al dispositivo que emita interrupciones al completar cada petición (enable_interrupts).

Decisiones de ingeniería

  • PIC, no IOAPIC. El kernel corre íntegramente sobre el par 8259 (pic.rs) y la crate x86_64 no ofrece abstracción de APIC. Las IRQ legadas de PCI de la máquina q35 se enrutan por el 8259: basta leer la línea que el firmware UEFI ya asignó y abrirla. Migrar al IOAPIC habría exigido levantar LAPIC + IOAPIC + parseo de tablas ACPI — un subsistema entero, desproporcionado para el objetivo. El resultado funcional es idéntico: E/S conducida por la interrupción física.
  • Las capacidades WASM no .await-ean. El intérprete wasmi ejecuta las funciones de host de forma SÍNCRONA: no hay manera de suspender un módulo a mitad de una llamada de host. Por eso sys_object_* no se vuelven asíncronas; usan bloquear_en, que duerme la CPU con hlt en lugar de sondear. El verdadero solapamiento E/S ↔ render lo aprovechan las TAREAS del reactor (tarea_sonda_disco hoy; la carga dinámica de módulos, mañana).
  • Una IRQ legada de PCI es de NIVEL: el manejador reconoce primero al dispositivo —lo que baja su línea— y sólo después cierra el EOI del PIC; el orden inverso reavivaría la interrupción en bucle.
  • Todo acceso al disco toma su Mutex con las interrupciones desactivadas (without_interrupts): la IRQ del disco jamás encuentra el cerrojo ocupado, lo que hace imposible el interbloqueo por interrupción.

Verificado

  • QEMU: el disco virtio-blk se enruta a la IRQ 11. La tarea_sonda_disco reporta «sonda asíncrona OK -- 2 IRQ de disco atendidas»: la interrupción del disco dispara de verdad. La app cronista, sobre el disco persistente heredado de la Fase 6.1c, continúa la cuenta de arranques (3 → 4 → 5 celdas) con el testigo de integridad del DAG en verde — la nueva E/S asíncrona lee y escribe el grafo sin un solo fallo. Las cuatro apps WASM siguen su curso, sin un sobresalto ni un micro-congelamiento.

Fase 7 — Apertura: Apps que nacen del Grafo — 2026-05-22

Apertura de la Fase 7. Este commit asienta el plan y el andamiaje; no cambia el comportamiento del kernel. La Fase 7 destierra el include_bytes! del userspace: las aplicaciones pasan a ser objetos del grafo, y un Manifiesto de Génesis —también en el grafo— dicta qué arranca, con qué cuota y en qué región.

Añadido

  • FASE7.md — el plan de ataque: el objetivo, el problema huevo-y-gallina de la génesis, las sub-fases 7a (manifiesto + carga desde el grafo, con semilla por el kernel), 7b (siembra de la imagen por boot, muerte del include_bytes!) y 7c (persistencia inter-sesión), y los guardarraíles.
  • kernel/src/manifiesto.rs — andamiaje del Manifiesto de Génesis. Los tipos Manifiesto / EntradaApp y la (de)serialización postcard están completos; cargar y sembrar_genesis son esbozos hasta la Fase 7a. La sub-región se guarda en campos u32 de ancho fijo (formato en disco), no como RegionPantalla (usize, ancho de plataforma).

Notas

  • El módulo se declara en main.rs pero aún no se cablea a kernel_main (#![allow(dead_code)] temporal, hasta que la 7a le dé un llamador). El kernel compila y se comporta idéntico a la Fase 6.2 — nada observable que verificar en QEMU en esta apertura.