tawasuyu

tawasuyu/brahman

Rust 506TOML 198Markdown 56JSON 197212 Sutichaykuna

⎇ 6cb63b266becd186f9ad016c7cd6dccc4faf855b renaser/ROADMAP.md Markdown · 408 siq'ikuna · 22.8 KB Ñawpa willay ch'uya

feat(renaser): Fase 20 — Akasha Over Ether (grafo distribuido) 42fee6fcb · sergio ·

1# renaser — Hoja de ruta
2
3Estado de las fases del proyecto. Para la arquitectura, ver `ARCHITECTURE.md`.
4
5## Fases completadas
6
7Todas verificadas en QEMU (captura de pantalla incluida en su momento).
8
9### Fase 1 — el primer microsegundo
10Arranque UEFI, adopción del framebuffer GOP, lienzo de doble búfer y la baliza
11de pánico (franja roja al colapsar). Punto de entrada con `bootloader_api`.
12
13### Fase 1.5 — empaquetado y arranque
14Miembro `boot/`: constructor de la imagen de disco UEFI (crate `bootloader`
150.11, vía dependencia de artefacto) y lanzador de QEMU. `cargo run` pasa a
16compilar, forjar la imagen y arrancar, todo de un gesto.
17
18### Fase 2.0 — cimientos del manejo de fallos
19GDT propia + TSS con stack de emergencia (IST) para el doble fallo. IDT con
20manejadores de excepción de CPU. El breakpoint es recuperable; el resto de
21excepciones encienden la baliza.
22
23### Fase 2.1 — interrupciones de hardware
24Remapeo del PIC 8259 fuera del rango de las excepciones. Temporizador (PIT) a
25100 Hz e IRQ1 de teclado. El kernel pasa de "pintar una vez" a un bucle de
26render despertado por el hardware.
27
28### Fase 3 — memoria dinámica y reactor asíncrono
29Heap de 64 MiB con `linked_list_allocator` como asignador global; manejador
30propio de OOM (franja naranja). Reactor cooperativo: `Executor`, `Task`,
31`Waker`. Texto vectorial con `fontdue`: el texto deja de ser mapa de bits.
32
33### Fase 4 — el escudo de aislamiento WASM
34Runtime `wasmi` `no_std`. Matriz de capacidades con dos funciones de host
35(`sys_render_frame`, `sys_get_scancode`) y validación infranqueable de límites
36de la memoria lineal. Primera app del userspace: `apps/hello_wasm`, un módulo
37`wasm32` aislado que pinta y responde al teclado.
38
39### Fase 5 — multitarea cooperativa, fuel y reloj
40Unificación del reactor (Fase 3) y el runtime WASM (Fase 4). El ABI del
41userspace pasa a `init`/`tick`: cada `tick` es un punto de cesión cooperativa.
42`async_system::reloj` convierte la IRQ0 en el `Future` `EsperaFrame`, que marca
43el compás de los fotogramas. Cada app es una `AplicacionWasm` persistente y una
44tarea del reactor. Escudo de combustible (`fuel`): cada `tick` corre con un
45presupuesto estricto; agotarlo desaloja la app sin tocar al kernel. Capacidades
46ampliadas — regiones de dibujo por app y canal de teclado por app. Verificado
47en QEMU con tres apps concurrentes, una de ellas díscola y desalojada en vivo.
48
49### Fase 6.0 — cuotas de memoria y ciclo de vida
50Completa el aislamiento espacial del userspace. Cada `AplicacionWasm` instancia
51su `Store` con un `StoreLimits` (techo de memoria lineal de 4 MiB, vía
52`Store::limiter`); rebasarlo es una trampa que desaloja la app con baliza
53amarilla — gemela de la púrpura del desalojo por combustible. `Drop` para
54`AplicacionWasm` reconcilia el ciclo de vida: da de baja el canal de teclado de
55la difusión de la IRQ1. Verificado en QEMU con cuatro apps — una díscola
56(desalojo temporal) y una glotona (desalojo espacial), ambas en vivo.
57
58## Fase 6.1 — sustrato de almacenamiento (completada)
59
60Estrategia incremental para el almacenamiento, frente al riesgo del hardware:
61
62- **6.1a — Sonda PCI** *(hecha)* — `drivers/pci.rs` enumera el bus PCI por
63  `0xCF8`/`0xCFC` y localiza el disco virtio-blk; `boot` forja el disco de
64  pruebas y lo adjunta como `virtio-blk-pci`. El muro del descubrimiento de
65  hardware queda derribado.
66- **6.1b — HAL y lectura de sector** *(hecha)* — `drivers/disco.rs`: asignador
67  de marcos «bump», `KernelHal` (el `trait Hal` de `virtio-drivers`: DMA y
68  traducción de direcciones) y `montar_y_leer_sector0`, que lee el sector 0 por
69  sondeo. Verificado por una firma que viaja del anfitrión al disco y vuelve.
70- **6.1c — Grafo de objetos** *(hecha)* — `almacen.rs`: el almacenamiento como
71  DAG direccionado por contenido —la identidad de un objeto es el hash BLAKE3
72  de su forma serializada (`postcard`); el disco se organiza como un log con
73  superbloque e índice—, y las cinco capacidades `sys_object_*` que lo exponen
74  al userspace. `drivers/disco.rs` gana un asignador de marcos con liberación
75  real (mapa de bits), escritura de sectores y un `VirtIOBlk` persistente. La
76  app `cronista` lleva la cuenta de los arranques en el grafo: la cuenta
77  perdura entre reinicios.
78
79## Fase 6.2 — E/S de disco asíncrona por interrupción (completada)
80
81La Fase 6.1 hizo hablar al disco, pero por **sondeo**: el procesador se quedaba
82en espera activa vigilando el *used ring* de virtio. La 6.2 libera el
83planificador cooperativo — la E/S de bloques pasa a ser **reactiva**:
84
85- `EsperaDisco` — una transferencia de bloques como `Future` nativo, sobre la
86  API no bloqueante de `virtio-drivers` (`read_blocks_nb` / `peek_used` /
87  `complete_*`). Cede la CPU mientras el disco trabaja.
88- La **IRQ del disco** — `montar` descubre la línea de IRQ legada del
89  dispositivo (registro «Interrupt Line» del espacio de configuración PCI), la
90  enruta por el 8259 y registra su manejador; `atender_irq` reconoce la
91  interrupción y despierta a la tarea que aguardaba el bloque.
92- `bloquear_en` — el puente para los contextos síncronos (el arranque, las
93  capacidades WASM): duerme la CPU con `hlt` en vez de sondear.
94
95Decisión de ingeniería: las IRQ se enrutan por el **PIC 8259** que el kernel ya
96gobierna, no por el IOAPIC — basta leer la línea que el firmware ya asignó.
97Verificado en QEMU: el disco se enruta a la IRQ 11; una tarea-sonda del reactor
98lee un bloque de forma asíncrona mientras las apps siguen pintando.
99
100## Fase 7 — el userspace nace del Grafo de Objetos (completada)
101
102Hasta la Fase 6, el userspace venía **empotrado en el binario del kernel**:
103cuatro `include_bytes!` de `.wasm` y regiones escritas a mano. La Fase 7 lo
104destierra — las aplicaciones pasan a ser objetos del grafo, gobernadas por un
105**Manifiesto de Génesis** que también vive en el grafo. Plan completo en
106`FASE7.md`.
107
108- **7a — el Manifiesto (completada).** `manifiesto.rs`: tipos `Manifiesto` /
109  `EntradaApp` y carga desde el grafo. El superbloque gana el ancla
110  `manifiesto` (VERSION 1→2). `kernel_main` lee el manifiesto e instancia cada
111  app recuperando su bytecode del grafo, verificado por su hash.
112- **7b — la imagen sembrada por `boot` (completada).** Nace la crate
113  `formato`, un núcleo `no_std` con el formato del grafo en disco, COMPARTIDO
114  por el kernel y el constructor de imagen `boot`. `boot` siembra el disco
115  virgen con el grafo ya poblado —bytecode y manifiesto—; el kernel pierde
116  todo `include_bytes!` del userspace. Su binario ya no carga ni un `.wasm`.
117- **7c — persistencia inter-sesión (completada).** La app `memoriosa` graba
118  su estado como un objeto del grafo; el kernel lo ancla en la ranura
119  `EntradaApp.estado` y re-graba el manifiesto. Al despertar, `init` lo relee
120  y la app retoma donde quedó. Capacidades `sys_estado_cargar` /
121  `sys_estado_guardar`; el kernel custodia un manifiesto VIVO y mutable.
122
123## Fase 8 — el compositor teselante e interactivo (completada)
124
125El kernel deja de colocar las ventanas a mano: las **tesela**. El motor es
126`mirada-layout` —el mismo núcleo `no_std` que ordena el compositor Wayland de
127brahman—, enlazado por `path` cruzando la frontera de workspace. Plan completo
128en `FASE8.md`.
129
130- **8a — el compositor tesela (completada).** `compositor.rs` calcula un marco
131  por app con el algoritmo `MasterStack`. El kernel centra el fotograma natural
132  de cada app dentro de su marco; las apps no cambian una instrucción.
133  `region_x/y` del manifiesto quedan vestigiales — la posición la decide el
134  compositor.
135- **8b — teselado interactivo (completada).** `Alt+Espacio` cicla los modos de
136  teselado en caliente. El kernel cachea el último fotograma de cada app y
137  recompone desde la caché: las apps estáticas sobreviven al re-teselado sin
138  enterarse del cambio.
139- **8c — foco y enrutamiento selectivo (completada).** Una ventana enfocada,
140  con borde índigo; `Alt+J` / `Alt+K` mueven el foco entre las ventanas vivas.
141  El teclado deja de difundir: entrega cada tecla sólo a la app enfocada.
142- **8d — manipulación de ventanas (completada).** El orden de teselado se
143  separa de la identidad de las ventanas. `Alt+Enter` promueve la ventana
144  enfocada a la celda maestra; `Alt+H` / `Alt+L` la reordenan. El foco viaja
145  con la ventana.
146
147## Fase 9 — orden-Z y ventanas flotantes (completada)
148
149El teselado de la Fase 8 repartía la pantalla sin solapamiento. La Fase 9 suma
150un segundo modelo de composición —el SOLAPAMIENTO—: una ventana puede abandonar
151el teselado y FLOTAR sobre las demás. Verificada en QEMU (`sendkey`).
152
153- El `Escritorio` separa dos capas: las ventanas TESELADAS, al fondo; y las
154  FLOTANTES, encima, apiladas en un orden-Z (`flotantes`, de atrás hacia
155  adelante). Juntas son una partición de las ventanas.
156- `Alt+F` alterna la ventana enfocada entre teselada y flotante. Una flotante
157  nace con un marco propio, en cascada, y al frente del orden-Z; al volver al
158  teselado se reincorpora a la rejilla, que se recalcula.
159- Con flotantes vivas, el kernel deja de pintar ventana a ventana: RECOMPONE el
160  escritorio entero, capa a capa de atrás hacia adelante —el solapamiento se
161  resuelve por el orden del pintado—. Sin flotantes conserva el camino rápido
162  de la Fase 8.
163- El foco recorre todas las ventanas; al posarse en una flotante, la alza al
164  frente: la flotante enfocada está siempre delante.
165
166## Fase 10 — alta y baja de aplicaciones en vivo (completada)
167
168Hasta la Fase 9 el censo de aplicaciones se fijaba en el arranque. La Fase 10
169lo vuelve DINÁMICO: una app puede nacer o cerrarse con el reactor ya en marcha.
170Verificada en QEMU (`sendkey`).
171
172- El reactor admite NACIMIENTOS en vivo: una cola que `engendrar` alimenta y
173  que el ejecutor drena al inicio de cada vuelta, adoptando cada futuro como
174  tarea. El censo de tareas deja de ser inmutable tras el arranque.
175- `Alt+Q` cierra la app enfocada: una baja LIMPIA. El compositor saca la
176  ventana del teselado y del orden-Z; la app, al advertir la baja, concluye su
177  tarea y `AplicacionWasm::drop` libera su memoria, su combustible y su canal.
178- `Alt+N` lanza una app nueva: `nacer_ventana` la añade y entrega su índice; el
179  orquestador instancia el WASM y engendra su tarea. Las apps de génesis dejan
180  su bytecode cacheado como plantilla; cada `Alt+N` instancia una en rotación.
181- El censo de ventanas sólo crece —los índices son la identidad, jamás se
182  reciclan—; una ventana cerrada queda como ranura inerte, fuera del teselado.
183
184## Fase 11 — el reloj del sistema como capacidad de host (completada)
185
186Hasta la Fase 10 una aplicación sólo sabía cuántas veces la habían llamado, no
187cuánto tiempo había pasado. La Fase 11 le da al userspace un sentido del
188tiempo. Verificada en QEMU (`sendkey`).
189
190- Capacidad `sys_tiempo_mono`: los milisegundos monótonos desde el arranque —la
191  décima función del host—. El temporizador (PIT) ya late a 100 Hz; `reloj`
192  expone esa cuenta y `env` la inyecta. Lectura pura, jamás retrocede.
193- App nueva `pulso`: un compás visual cuya escena es una función PURA del reloj
194  del host. Dos instancias, nazcan cuando nazcan, laten al unísono — la prueba
195  de que el tiempo es absoluto, no una cuenta de fotogramas.
196- El userspace de génesis crece de 5 a 6 apps.
197
198## Fase 12 — la bocina del PC como capacidad de host (completada)
199
200La Fase 11 le dio al userspace un reloj; la Fase 12, una voz. La bocina del PC
201se suma a la matriz de capacidades. Verificada en QEMU.
202
203- Driver `drivers/altavoz`: el canal 2 del PIT como generador de onda cuadrada
204  + la compuerta del puerto 0x61. El canal 0 (latido del kernel) no se toca.
205- Capacidad `sys_tono(frecuencia_hz)` —la undécima—. La bocina es un recurso
206  único: pertenece a la ventana ENFOCADA, como el teclado desde la Fase 8c. Al
207  cambiar el foco, el compositor la calla.
208- App nueva `tonada`: toca una escala de Do mayor y la dibuja como una
209  escalera de barras. Junta el reloj (`sys_tiempo_mono`) y la bocina
210  (`sys_tono`). El userspace de génesis crece de 6 a 7 apps.
211- Verificado por captura: la onda cuadrada de la bocina, enrutada a un WAV,
212  late a la frecuencia media de la escala.
213
214## Fase 13 — ratón, puntero y arrastre de flotantes (completada)
215
216Hasta la Fase 12 renaser dialogaba sólo con el teclado; las ventanas flotantes
217nacían en cascada y allí se quedaban. La Fase 13 trae el ratón: un puntero,
218clic-para-enfocar y arrastre del marco de las flotantes. Verificada en QEMU
219(`mouse_move` / `mouse_button` del monitor).
220
221- Driver `drivers/raton`: el ratón PS/2 cuelga del dispositivo auxiliar del
222  8042 + la IRQ12. El driver despierta el aux, programa su IRQ, le ordena
223  reportar, ensambla paquetes de 3 bytes con guarda del bit-3.
224- El puntero como capa de presentación: `Pantalla::estampar_puntero` pinta un
225  sprite de flecha de 12×18 sobre el framebuffer, DESPUÉS de copiar el
226  lienzo. El lienzo nunca lo contiene — hace de save-under natural—.
227- El compositor gana `atender_raton`: botón bajando → clic-para-enfocar (sobre
228  cualquier ventana viva); si la enfocada flota, arranca un ARRASTRE con el
229  desfase de agarre; el botón sostenido la sigue al puntero; al soltar, fin.
230
231## Fase 14 — la identidad del escritorio: nombres y barra de tareas (completada)
232
233Las ventanas eran anónimas; el escritorio no sabía nombrar lo que mostraba. La
234Fase 14 le pone un nombre a cada cuarto y una barra al pie con la lista de
235quienes lo habitan. Verificada en QEMU.
236
237- Cada `Ventana` lleva un `nombre: String` —el del manifiesto, o el del
238  orquestador al engendrarla en vivo—. `Plantilla` lo guarda para las copias.
239- Una franja de 40 px al pie reservada como `area_taskbar`. `area_apps` la
240  descuenta — las ventanas teselan y flotan sin tapar la barra ni la consola.
241- `consola` gana los tipos `Taskbar` / `CeldaTaskbar` y los métodos
242  `pintar_taskbar` y `pintar_etiqueta`. La pestaña enfocada lleva el índigo del
243  foco; la desalojada, su color de baliza; el resto, el slate.
244- Un clic dentro de la barra enfoca la ventana de la pestaña pulsada, sin
245  iniciar arrastre. El compositor encuentra la celda con `celda_taskbar_en`.
246
247## Mejora estructural — mapeador MMIO en el kernel (entre fases 13 y 14)
248
249Los BAR prefetchables 64-bit que OVMF aloja en la ventana PCI de 64 bits NO
250los mapea `bootloader_api`. El kernel gana `memory::mmio`, que envuelve la
251tabla L4 activa y abre páginas hacia las regiones MMIO que virtio-drivers le
252pide. `KernelHal::mmio_phys_to_virt` llama al mapeador antes de devolver el
253puntero. Trata `PageAlreadyMapped` y `ParentEntryHugePage` como éxito
254silencioso. Los marcos para tablas intermedias salen del banco DMA. Esta
255mejora resolvió el #PF inexplicable en máquinas con un OVMF que coloca el BAR
256del virtio-blk fuera de los primeros 4 GiB.
257
258## Fase 15 — la voz del sistema (completada)
259
260La bocina pertenecía al app enfocado (Fase 12), pero el kernel necesita hablar
261también: un acorde al arrancar, un repique al lanzar una app, un bajo al
262desalojarla. Verificada en QEMU con captura PCM a WAV.
263
264- `altavoz` gana una cola de notas (`SECUENCIA: Mutex<VecDeque<(u32,u32)>>`) y
265  un reloj de fin (`FIN_NOTA: AtomicU64`). `agendar(&[(frec, ms)])` encola;
266  `atender()` —invocada por la tarea del compositor cada fotograma— pasa a la
267  nota siguiente cuando la actual termina. `kernel_sonando()` gatea a los apps:
268  mientras el kernel habla, `sys_tono` ignora a las apps.
269- Catálogo: `VOZ_BIENVENIDA` (Do-Mi-Sol), `VOZ_LANZAR` (repique ascendente),
270  `VOZ_CERRAR` (descendente), `VOZ_DESALOJO` (bajo grave).
271- Hitos: `kernel_main` agenda el acorde antes de `ejecutor.run`. `nacer_ventana`,
272  `cerrar` y `desalojar` lo agendan al hacer su trabajo.
273- Pestañas de la barra de tareas: tinta calculada por brillo del fondo, así la
274  pestaña crema del desalojo por memoria ya no lleva texto invisible.
275
276## Fase 16 — la barra viva: lanzador y reloj (completada)
277
278La barra de tareas era pasiva. Esta fase la activa con un botón lanzador a la
279izquierda («+», equivalente táctil de `Alt+N`) y un reloj `mm:ss` a la derecha
280que late cada segundo. Verificada en QEMU con dos capturas separadas en el
281tiempo: el reloj avanza de `0:17` a `0:29`.
282
283- `compositor`: layout reorganizado — lanzador a la izquierda (36 px), celdas
284  en el medio, reloj a la derecha (80 px). `clic_en_launcher` enruta el clic
285  al contador `PARTOS`; la tarea del compositor lo recoge y lanza.
286- `compositor::tick_reloj()` — invocada cada fotograma; recompone sólo cuando
287  el segundo del reloj monótono cambia respecto al último mostrado.
288- `consola::Taskbar` crece con `launcher`, `reloj` y `reloj_region`.
289  `pintar_taskbar` dibuja la cruz del lanzador como dos rectángulos
290  cruzados (sin depender de la tipografía) y rotula el reloj.
291
292## Fase 17 — `bitacora`, el editor que recuerda (completada)
293
294`memoriosa` (Fase 7c) demostró que un app podía persistir su huella. La Fase 17
295lo lleva al gesto natural: un editor de texto. Tecleas, reinicias renaser, el
296texto sigue ahí. Verificada en QEMU.
297
298- Nuevo crate `apps/bitacora/`: lienzo 480×280, tipografía 8×8 (crate `font8x8`)
299  escalada x2 a 16×16, render pixel a pixel desde la memoria del propio app.
300  Buffer 512 bytes, wrap a 28 columnas, Enter / Backspace, persiste cada
301  cambio con `sys_estado_guardar`. Mapeo de scancodes US a ASCII (minúsculas).
302- `GENESIS` crece de 7 a 8 apps; `bitacora` es la maestra al arrancar.
303- `CELDA_TASKBAR_ANCHO` baja de 150 a 130 px para que las ocho pestañas
304  quepan holgadas con el lanzador y el reloj.
305
306## Fase 18 — red: virtio-net y el primer hola al exterior (completada)
307
308renaser hablaba solo. Esta fase abre una boca y una oreja al exterior con
309virtio-net, reutilizando el `KernelHal` del disco y el mapeador MMIO. Al
310arrancar, el kernel envía un ARP request al gateway de QEMU; lee la
311respuesta y la registra. Verificada con captura pcap.
312
313- Driver `drivers/red`: monta `VirtIONet<KernelHal, PciTransport, 16>`,
314  expone `enviar(frame)` y `drenar_rx(callback)`. Sin pila TCP/IP — solo
315  ethernet crudo —; la composición de paquetes se hace en el llamante.
316- `componer_arp_request`: helper para construir el ARP request inicial.
317- `interrupts::registrar_irq_red` + handler de IDT, gemelo del de disco.
318- Tarea `tarea_red` en el reactor: envía el ARP al arrancar, drena RX en
319  cada fotograma y vuelca cada paquete a COM1.
320- QEMU args ganan `-netdev user,id=net0 -device virtio-net-pci`.
321
322Líneas abiertas posteriores: capacidades `sys_net_*` para que los apps
323también hablen; una pila mínima ARP/IP/UDP; reciclado de las ranuras de
324ventana cerradas; audio con varias voces (PCM).
325
326## Fase 19 — voz del userspace hacia la red (completada)
327
328La Fase 18 hizo que el kernel hablara con la red. La Fase 19 le da la
329misma capacidad a los apps con tres capacidades nuevas, y estrena la
330primera app que las usa.
331
332- `drivers::red::recibir_en(buf) -> usize`: drena UN paquete por
333  llamada, recicla el descriptor a la cola RX. El gemelo cooperativo de
334  `drenar_rx`, dimensionado para el patrón que los apps usan.
335- Tres capacidades `wasm/env` nuevas: `sys_net_mac` (escribe la MAC en
336  un buffer del módulo), `sys_net_enviar(ptr, len)` (envía un frame
337  Ethernet crudo) y `sys_net_recibir(salida, capacidad)` (drena un
338  paquete, devuelve los bytes copiados). Todas validan rango contra la
339  memoria lineal del módulo y devuelven códigos negativos diagnósticos.
340- App `pregon` (4.2 KiB WASM): al arrancar pide su MAC, anuncia su
341  presencia con un broadcast Ethernet (EtherType `0x88B5`, payload
342  `"renaser :: hola desde mi red"`) y en cada `tick` drena un paquete y
343  lo muestra en su lienzo 480×160 — título, MAC, cuentas TX/RX y datos
344  del último frame entrante (tamaño, EtherType, src MAC).
345- `tarea_red` ya no drena RX: la posesión de la cola pasa al userspace.
346  El kernel conserva sólo el envío del ARP de prueba al arrancar.
347- `GENESIS` crece de 8 a 9 apps; `pregon` queda en posición 2 (detrás
348  de `bitacora`). `CELDA_TASKBAR_ANCHO` baja de 130 a 116 px para que
349  las nueve pestañas + lanzador + reloj caben en 1280 px.
350
351Verificada con `-object filter-dump,...,file=/tmp/renaser.pcap`. El
352pcap captura tres frames: el broadcast `0x88B5` de `pregon`, el ARP
353request del kernel y el ARP reply del gateway. El primero es el del
354huésped — la voz del userspace ya pasó al cable.
355
356Líneas abiertas posteriores: una pila mínima ARP/IP/UDP para los apps;
357un servidor de eco / un cliente DNS de juguete; reciclado de las
358ranuras de ventana cerradas; audio con varias voces (PCM).
359
360## Fase 20 — Akasha Over Ether: el grafo distribuido (completada)
361
362El grafo de objetos persistentes —direccionado por contenido, ya BLAKE3—
363deja de ser una propiedad LOCAL del disco y se vuelve una propiedad
364DISTRIBUIDA del cable. Sin TCP, sin IP, sin DNS: tres mensajes y un
365EtherType propio bastan.
366
367- Crate `akasha/` (no_std compartido, gemela de `formato`): el
368  protocolo. `MensajeAkasha` con `SolicitarObjeto(id)`,
369  `ProveedorObjeto(id, payload)`, `AnunciarRaiz(id)`. Serializado con
370  `postcard`. Helpers `componer_frame` y `analizar_frame`. EtherType
371  experimental `0x88B5`. Seis pruebas unitarias.
372- Módulo `kernel/src/akasha.rs`: el respondedor. Drena la cola RX del
373  dispositivo de red y **demultiplexa**: los frames AoE legítimos los
374  procesa en el núcleo; el resto va a una cola del userspace que
375  `sys_net_recibir` lee. Atiende `SolicitarObjeto` consultando
376  `almacen`, absorbe `ProveedorObjeto` verificando integridad, registra
377  `AnunciarRaiz` y, si ignoramos el nodo anunciado, le pedimos al emisor.
378- Faro periódico: cada 5 s, `AnunciarRaiz` con el hash del manifiesto se
379  difunde por broadcast. La cadencia se mide contra el reloj monótono —
380  no contra los awaits—, por lo que el ritmo del faro es independiente
381  de cuánto trabajo del reactor consume cada vuelta.
382- `tic_compositor`: el pulso fiable. Los oficios AoE se enganchan al tic
383  del compositor (cuyo latido cooperativo es el único garantizado bajo
384  carga del reactor); una tarea propia con `EsperaFrame::await` en bucle
385  no escalaba porque el intérprete `wasmi` de los apps degrada la
386  cadencia de los awaits a varios cientos de ms.
387- `sys_net_recibir` lee de la cola del userspace que mantiene `akasha`,
388  no del driver. `drivers::red::recibir_en` queda como primitiva del
389  driver para futuras herramientas de diagnóstico.
390
391Verificada con `cargo test -p akasha` (6 pruebas verdes) y con QEMU
392headless + `-object filter-dump`. En 60 s de captura: 11 `AnunciarRaiz`
393con Δ promedio 5.86 s, un ARP request + reply y el saludo en texto
394plano de `pregon`. La casa ya tiene su propio idioma de red — y un faro
395que late.
396
397Líneas abiertas posteriores: una pila ARP/IP/UDP mínima para los apps;
398un peer real en una segunda VM para ver la replicación end-to-end
399`AnunciarRaiz → SolicitarObjeto → ProveedorObjeto`; un indicador AoE en
400la barra de tareas que pinte los contadores de `ResumenAkasha`;
401reciclado de las ranuras de ventana cerradas; audio con varias voces.
402
403## Principios que persisten entre fases
404
405- Reutilizar infraestructura madura de la comunidad antes que reinventar.
406- `unsafe` mínimo, confinado y justificado.
407- Verificar cada fase en QEMU antes de cerrarla.
408- `git commit` + `git push` tras cada iteración.

ROADMAP.md

renaser — Hoja de ruta

Estado de las fases del proyecto. Para la arquitectura, ver ARCHITECTURE.md.

Fases completadas

Todas verificadas en QEMU (captura de pantalla incluida en su momento).

Fase 1 — el primer microsegundo

Arranque UEFI, adopción del framebuffer GOP, lienzo de doble búfer y la baliza de pánico (franja roja al colapsar). Punto de entrada con bootloader_api.

Fase 1.5 — empaquetado y arranque

Miembro boot/: constructor de la imagen de disco UEFI (crate bootloader 0.11, vía dependencia de artefacto) y lanzador de QEMU. cargo run pasa a compilar, forjar la imagen y arrancar, todo de un gesto.

Fase 2.0 — cimientos del manejo de fallos

GDT propia + TSS con stack de emergencia (IST) para el doble fallo. IDT con manejadores de excepción de CPU. El breakpoint es recuperable; el resto de excepciones encienden la baliza.

Fase 2.1 — interrupciones de hardware

Remapeo del PIC 8259 fuera del rango de las excepciones. Temporizador (PIT) a 100 Hz e IRQ1 de teclado. El kernel pasa de "pintar una vez" a un bucle de render despertado por el hardware.

Fase 3 — memoria dinámica y reactor asíncrono

Heap de 64 MiB con linked_list_allocator como asignador global; manejador propio de OOM (franja naranja). Reactor cooperativo: Executor, Task, Waker. Texto vectorial con fontdue: el texto deja de ser mapa de bits.

Fase 4 — el escudo de aislamiento WASM

Runtime wasmi no_std. Matriz de capacidades con dos funciones de host (sys_render_frame, sys_get_scancode) y validación infranqueable de límites de la memoria lineal. Primera app del userspace: apps/hello_wasm, un módulo wasm32 aislado que pinta y responde al teclado.

Fase 5 — multitarea cooperativa, fuel y reloj

Unificación del reactor (Fase 3) y el runtime WASM (Fase 4). El ABI del userspace pasa a init/tick: cada tick es un punto de cesión cooperativa. async_system::reloj convierte la IRQ0 en el Future EsperaFrame, que marca el compás de los fotogramas. Cada app es una AplicacionWasm persistente y una tarea del reactor. Escudo de combustible (fuel): cada tick corre con un presupuesto estricto; agotarlo desaloja la app sin tocar al kernel. Capacidades ampliadas — regiones de dibujo por app y canal de teclado por app. Verificado en QEMU con tres apps concurrentes, una de ellas díscola y desalojada en vivo.

Fase 6.0 — cuotas de memoria y ciclo de vida

Completa el aislamiento espacial del userspace. Cada AplicacionWasm instancia su Store con un StoreLimits (techo de memoria lineal de 4 MiB, vía Store::limiter); rebasarlo es una trampa que desaloja la app con baliza amarilla — gemela de la púrpura del desalojo por combustible. Drop para AplicacionWasm reconcilia el ciclo de vida: da de baja el canal de teclado de la difusión de la IRQ1. Verificado en QEMU con cuatro apps — una díscola (desalojo temporal) y una glotona (desalojo espacial), ambas en vivo.

Fase 6.1 — sustrato de almacenamiento (completada)

Estrategia incremental para el almacenamiento, frente al riesgo del hardware:

Fase 6.2 — E/S de disco asíncrona por interrupción (completada)

La Fase 6.1 hizo hablar al disco, pero por sondeo: el procesador se quedaba en espera activa vigilando el used ring de virtio. La 6.2 libera el planificador cooperativo — la E/S de bloques pasa a ser reactiva:

Decisión de ingeniería: las IRQ se enrutan por el PIC 8259 que el kernel ya gobierna, no por el IOAPIC — basta leer la línea que el firmware ya asignó. Verificado en QEMU: el disco se enruta a la IRQ 11; una tarea-sonda del reactor lee un bloque de forma asíncrona mientras las apps siguen pintando.

Fase 7 — el userspace nace del Grafo de Objetos (completada)

Hasta la Fase 6, el userspace venía empotrado en el binario del kernel: cuatro include_bytes! de .wasm y regiones escritas a mano. La Fase 7 lo destierra — las aplicaciones pasan a ser objetos del grafo, gobernadas por un Manifiesto de Génesis que también vive en el grafo. Plan completo en FASE7.md.

Fase 8 — el compositor teselante e interactivo (completada)

El kernel deja de colocar las ventanas a mano: las tesela. El motor es mirada-layout —el mismo núcleo no_std que ordena el compositor Wayland de brahman—, enlazado por path cruzando la frontera de workspace. Plan completo en FASE8.md.

Fase 9 — orden-Z y ventanas flotantes (completada)

El teselado de la Fase 8 repartía la pantalla sin solapamiento. La Fase 9 suma un segundo modelo de composición —el SOLAPAMIENTO—: una ventana puede abandonar el teselado y FLOTAR sobre las demás. Verificada en QEMU (sendkey).

Fase 10 — alta y baja de aplicaciones en vivo (completada)

Hasta la Fase 9 el censo de aplicaciones se fijaba en el arranque. La Fase 10 lo vuelve DINÁMICO: una app puede nacer o cerrarse con el reactor ya en marcha. Verificada en QEMU (sendkey).

Fase 11 — el reloj del sistema como capacidad de host (completada)

Hasta la Fase 10 una aplicación sólo sabía cuántas veces la habían llamado, no cuánto tiempo había pasado. La Fase 11 le da al userspace un sentido del tiempo. Verificada en QEMU (sendkey).

Fase 12 — la bocina del PC como capacidad de host (completada)

La Fase 11 le dio al userspace un reloj; la Fase 12, una voz. La bocina del PC se suma a la matriz de capacidades. Verificada en QEMU.

Fase 13 — ratón, puntero y arrastre de flotantes (completada)

Hasta la Fase 12 renaser dialogaba sólo con el teclado; las ventanas flotantes nacían en cascada y allí se quedaban. La Fase 13 trae el ratón: un puntero, clic-para-enfocar y arrastre del marco de las flotantes. Verificada en QEMU (mouse_move / mouse_button del monitor).

Fase 14 — la identidad del escritorio: nombres y barra de tareas (completada)

Las ventanas eran anónimas; el escritorio no sabía nombrar lo que mostraba. La Fase 14 le pone un nombre a cada cuarto y una barra al pie con la lista de quienes lo habitan. Verificada en QEMU.

Mejora estructural — mapeador MMIO en el kernel (entre fases 13 y 14)

Los BAR prefetchables 64-bit que OVMF aloja en la ventana PCI de 64 bits NO los mapea bootloader_api. El kernel gana memory::mmio, que envuelve la tabla L4 activa y abre páginas hacia las regiones MMIO que virtio-drivers le pide. KernelHal::mmio_phys_to_virt llama al mapeador antes de devolver el puntero. Trata PageAlreadyMapped y ParentEntryHugePage como éxito silencioso. Los marcos para tablas intermedias salen del banco DMA. Esta mejora resolvió el #PF inexplicable en máquinas con un OVMF que coloca el BAR del virtio-blk fuera de los primeros 4 GiB.

Fase 15 — la voz del sistema (completada)

La bocina pertenecía al app enfocado (Fase 12), pero el kernel necesita hablar también: un acorde al arrancar, un repique al lanzar una app, un bajo al desalojarla. Verificada en QEMU con captura PCM a WAV.

Fase 16 — la barra viva: lanzador y reloj (completada)

La barra de tareas era pasiva. Esta fase la activa con un botón lanzador a la izquierda («+», equivalente táctil de Alt+N) y un reloj mm:ss a la derecha que late cada segundo. Verificada en QEMU con dos capturas separadas en el tiempo: el reloj avanza de 0:17 a 0:29.

Fase 17 — bitacora, el editor que recuerda (completada)

memoriosa (Fase 7c) demostró que un app podía persistir su huella. La Fase 17 lo lleva al gesto natural: un editor de texto. Tecleas, reinicias renaser, el texto sigue ahí. Verificada en QEMU.

Fase 18 — red: virtio-net y el primer hola al exterior (completada)

renaser hablaba solo. Esta fase abre una boca y una oreja al exterior con virtio-net, reutilizando el KernelHal del disco y el mapeador MMIO. Al arrancar, el kernel envía un ARP request al gateway de QEMU; lee la respuesta y la registra. Verificada con captura pcap.

Líneas abiertas posteriores: capacidades sys_net_* para que los apps también hablen; una pila mínima ARP/IP/UDP; reciclado de las ranuras de ventana cerradas; audio con varias voces (PCM).

Fase 19 — voz del userspace hacia la red (completada)

La Fase 18 hizo que el kernel hablara con la red. La Fase 19 le da la misma capacidad a los apps con tres capacidades nuevas, y estrena la primera app que las usa.

Verificada con -object filter-dump,...,file=/tmp/renaser.pcap. El pcap captura tres frames: el broadcast 0x88B5 de pregon, el ARP request del kernel y el ARP reply del gateway. El primero es el del huésped — la voz del userspace ya pasó al cable.

Líneas abiertas posteriores: una pila mínima ARP/IP/UDP para los apps; un servidor de eco / un cliente DNS de juguete; reciclado de las ranuras de ventana cerradas; audio con varias voces (PCM).

Fase 20 — Akasha Over Ether: el grafo distribuido (completada)

El grafo de objetos persistentes —direccionado por contenido, ya BLAKE3— deja de ser una propiedad LOCAL del disco y se vuelve una propiedad DISTRIBUIDA del cable. Sin TCP, sin IP, sin DNS: tres mensajes y un EtherType propio bastan.

Verificada con cargo test -p akasha (6 pruebas verdes) y con QEMU headless + -object filter-dump. En 60 s de captura: 11 AnunciarRaiz con Δ promedio 5.86 s, un ARP request + reply y el saludo en texto plano de pregon. La casa ya tiene su propio idioma de red — y un faro que late.

Líneas abiertas posteriores: una pila ARP/IP/UDP mínima para los apps; un peer real en una segunda VM para ver la replicación end-to-end AnunciarRaiz → SolicitarObjeto → ProveedorObjeto; un indicador AoE en la barra de tareas que pinte los contadores de ResumenAkasha; reciclado de las ranuras de ventana cerradas; audio con varias voces.

Principios que persisten entre fases