Tres mensajes y un EtherType propio bastan para extender el grafo de
objetos —direccionado por contenido, ya BLAKE3— a otras maquinas
renaser que escuchen en la misma red de capa-2. Sin TCP, sin IP,
sin DNS.
Crate nueva 'akasha/' (no_std compartido, gemela de 'formato',
excluida del workspace):
- MensajeAkasha enum con SolicitarObjeto(id), ProveedorObjeto(id,
payload), AnunciarRaiz(id).
- Codec: postcard (mismo que ya usa el grafo en disco).
- EtherType: 0x88B5. MAX_PAYLOAD_AKASHA = 1486 (MTU sin fragmentar).
- Helpers componer_frame(src, dst, msg) y analizar_frame(bytes) que
distinguen EtherType ajeno, frame truncado y payload basura.
- 6 pruebas unitarias en verde.
Modulo nuevo 'kernel/src/akasha.rs' con tres oficios:
1. Demuxer (drenar_y_demultiplexar): drena la cola RX del dispositivo
virtio-net y demultiplexa: frames AoE con payload valido los
procesa el respondedor; el resto va a una cola del userspace que
'sys_net_recibir' ahora lee. Frames 0x88B5 con payload
no-postcard (saludo de pregon) se cuentan y tambien viajan al
userspace.
2. Atencion de mensajes (procesar):
- SolicitarObjeto(id): consulta almacen::recuperar; si tenemos el
objeto, respondemos ProveedorObjeto unicast con objeto.serializar()
y re-hashing de defensa en profundidad.
- ProveedorObjeto(id, payload): verifica blake3(payload)==id antes
de absorber con almacen::almacenar.
- AnunciarRaiz(id): si ignoramos el nodo, le solicitamos al emisor.
3. Faro periodico (difundir_raiz cada 5 s): broadcast del hash del
manifiesto actual. Cadencia medida contra reloj::milisegundos(),
no contra los awaits — el interprete wasmi de los apps degrada
la cadencia de EsperaFrame::await a varios cientos de ms, asi
que se mide contra el reloj monotono y los oficios per-fotograma
se enganchan al tic del compositor (cuyo latido es fiable).
Contadores ResumenAkasha (rx/tx por variante, descartados, cola del
usuario) listos para un futuro indicador AoE en la barra de tareas.
Cambios complementarios:
- sys_net_recibir lee de akasha::pop_usuario, no de
drivers::red::recibir_en (que queda #[allow(dead_code)] como
primitiva del driver para diagnostico).
- tarea_red queda corta: envia un ARP al gateway y termina. El
demuxer y el faro viven en el tic del compositor.
Verificacion:
- 'cargo test -p akasha' → 6 pruebas en verde.
- QEMU headless 60 s con -object filter-dump → 14 frames: 11
AnunciarRaiz (Δ promedio 5.86 s sobre 5.00 s de target), 2 ARP
y el pregon hello. Cada AnunciarRaiz lleva el hash del manifiesto
'2f3deadfcc7dae25..' en 33 bytes postcard sobre 47 bytes de frame.
- COM1 vuelca 'akasha :: ANUNCIO emitido :: raiz=2f3deadfcc7dae25..'
en cada disparo.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Tres capacidades nuevas en wasm/env (12-14):
- sys_net_mac(salida) -> i32: escribe los seis bytes del MAC del
dispositivo. 0 OK, -1 si no hay red.
- sys_net_enviar(ptr, len) -> i32: envia un frame Ethernet crudo.
Valida rango contra la memoria lineal del modulo.
- sys_net_recibir(salida, capacidad) -> i32: drena UN paquete por
llamada hacia el buffer del modulo. Devuelve los bytes copiados, 0
si nada pendiente, codigos negativos diagnosticos.
Añadida red::recibir_en(buf) -> usize como su contraparte del driver:
gemelo cooperativo de drenar_rx que aterriza en un buffer del usuario.
App nueva pregon (apps/pregon/, 4.2 KiB WASM): lienzo 480x160, tipografia
8x8 (font8x8) escalada x2. Al init pide su MAC y anuncia su presencia
con un broadcast Ethernet — destino FF:FF:FF:FF:FF:FF, EtherType
experimental 0x88B5, payload ASCII 'renaser :: hola desde mi red'. En
cada tick drena un paquete con sys_net_recibir y muestra el titulo, el
MAC propio, las cuentas TX/RX, y los datos del ultimo frame entrante.
GENESIS 8 -> 9 apps (pregon en posicion 2 detras de bitacora);
CELDA_TASKBAR_ANCHO 130 -> 116 px para que las nueve pestañas + lanzador
+ reloj caben holgadas en 1280 px.
tarea_red del kernel ya no drena RX (la cola pertenece al userspace),
conserva solo el envio del ARP de prueba al arrancar.
Verificada en QEMU con -object filter-dump. El pcap captura tres frames
en orden: (1) broadcast 88B5 de pregon con su payload, (2) ARP request
del kernel, (3) ARP reply del gateway 52:55:0a:00:02:02. La consola
anuncia 'manifiesto :: 9 apps nacidas del grafo'.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
La bocina pertenecía al app enfocado (Fase 12), pero el kernel
necesita hablar también. Ahora tiene voz propia, prioritaria.
- `altavoz`: cola `SECUENCIA: Mutex<VecDeque<(u32,u32)>>` (freq, ms)
+ reloj `FIN_NOTA: AtomicU64`. `agendar(&[...])` encola;
`atender()` (tarea del compositor cada fotograma) avanza la
secuencia y silencia al acabar; `kernel_sonando()` gatea a los
apps — mientras el kernel suena, `sys_tono` no-op.
- Catálogo: VOZ_BIENVENIDA (Do5-Mi5-Sol5, 500 ms), VOZ_LANZAR
(700→1050 Hz), VOZ_CERRAR (900→520 Hz), VOZ_DESALOJO (180 Hz).
- Hitos: `kernel_main` agenda el acorde antes de `ejecutor.run`;
`nacer_ventana` (Alt+N), `cerrar` (Alt+Q), `desalojar` (falla)
agendan al hacer su trabajo.
- De paso: las pestañas de la barra de tareas calculan su tinta por
brillo del fondo (ITU-R BT.601); la pestaña crema del desalojo por
memoria, que llevaba texto blanco invisible, ahora luce su nombre
en tinta oscura.
Verificado en QEMU con `-audiodev wav -machine pcspk-audiodev=spk`:
el PCM crudo trae, en orden, el acorde de bienvenida (~520, 630, 760
Hz), un brevísimo 180 Hz (las balizas de discola/glotona desalojadas)
y después la escala de Do mayor de tonada.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
La Fase 11 dio al userspace un reloj; la Fase 12, una voz. Hasta hoy
renaser solo sabía dibujar para llamar la atención.
- Driver `drivers/altavoz`: el canal 2 del PIT como generador de onda
cuadrada + la compuerta del puerto 0x61. El canal 0 —latido del
kernel— no se toca. `tono(hz)` es su única vía; un 0 la silencia.
- Capacidad `sys_tono(frecuencia_hz)` — la undécima función del host.
La bocina es un recurso único: pertenece a la ventana ENFOCADA,
como el teclado desde la Fase 8c. Al cambiar el foco, el compositor
la calla; la nueva dueña la reclama en su próximo fotograma.
- App nueva `tonada` (`apps/tonada/`, wasm32): toca una escala de Do
mayor y la dibuja como una escalera de barras. Junta el reloj
(`sys_tiempo_mono`) y la bocina (`sys_tono`).
- `GENESIS` crece de 6 a 7 apps; `tonada` es la maestra del escritorio.
Verificado en QEMU. Visual: la escalera de `tonada` recorre la escala
con el tiempo. Sonido: con la bocina enrutada a un WAV, el PCM
capturado es una onda cuadrada oscilante de ~375 Hz — la frecuencia
media de la escala de Do mayor.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El userspace gana un sentido del tiempo: hasta ahora una app solo sabía
cuántas veces la habían llamado, no cuánto tiempo había pasado.
- Capacidad `sys_tiempo_mono() -> u64` — la décima función del host:
los milisegundos monótonos desde el arranque. `reloj` expone la
cuenta del PIT (100 Hz) como `milisegundos()`; `env` la inyecta.
Lectura pura, no toca la memoria del módulo, jamás retrocede.
- App nueva `pulso` (`apps/pulso/`, wasm32): un compás visual cuya
escena es una función PURA de `sys_tiempo_mono` — sin estado entre
fotogramas—. Dos instancias laten al unísono nazcan cuando nazcan.
- `GENESIS` crece de 5 a 6 apps; `pulso` es la maestra del escritorio.
Verificado en QEMU (sendkey): la barra de `pulso` avanza con el tiempo
de pared; un segundo `pulso` lanzado con Alt+N ~15 s después aparece
sincronizado con el primero — el compás se rige por el reloj absoluto,
no por una cuenta de fotogramas.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El compositor de la 8a teselaba, pero era inmovil. Las 8b/8c lo hacen
vivo: el teclado reordena el escritorio y mueve el foco en caliente.
- Cache de fotogramas: cada ventana guarda en RAM del kernel su ultimo
fotograma —reservada una vez, acotada al lienzo natural—. Al re-teselar
o mover el foco, el kernel recompone desde la cache: las apps que solo
pintan en init (cronista) conservan su imagen sin enterarse del cambio.
- compositor: el registro ESCRITORIO (ventanas, marcos, caches, modo);
presentar_fotograma, desalojar, atender_mandos, ciclar_layout,
mover_foco. Foco en un AtomicUsize, mandos en una cola lock-free.
- teclado: la IRQ1 deja de difundir. Alt es el modificador del sistema —
Alt+Espacio cicla el teselado, Alt+J/K mueven el foco—; una tecla
ordinaria va SOLO a la app enfocada (CANALES reindexado por indice_app).
- consola: borde de foco (indigo / gris) en cada marco.
Guardarrail anti-interbloqueo: la IRQ1 jamas bloquea ESCRITORIO; se
comunica por dos atomicos y una cola lock-free. Las caches se reservan
una sola vez, al tamaño natural — sin asignacion en el bucle del reactor.
Verificado en QEMU (screendump + sendkey): arranque teselado con hola
enfocada; Alt+Espacio cicla a CenteredMaster y las apps estaticas
conservan su contenido; Alt+J mueve el foco; las teclas llegan solo a la
app enfocada. Cierra la Fase 8 — el compositor teselante e interactivo.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El kernel deja de colocar las ventanas a mano: las tesela. El motor es
mirada-layout — el mismo nucleo no_std que ordena el compositor Wayland
de brahman, enlazado por path cruzando la frontera de workspace. Es el
primer consumo REAL del nucleo compartido brahman <-> renaser.
- kernel/compositor.rs: enlaza mirada-layout y calcula un marco por app
con el algoritmo MasterStack, dentro del area de pantalla.
- consola::volcar_marco centra el fotograma natural de la app dentro de
su marco teselado (antes lo depositaba en region.x/y fijos).
- ContextoCapacidades lleva marco + natural_ancho/alto; sys_render_frame
valida el fotograma contra el tamaño natural.
- cargar_userspace tesela con el compositor y pinta el escenario antes
de encender las apps. Las apps NO cambian: el compositor reordena la
pantalla sin que ninguna toque una instruccion.
Verificado en QEMU (screendump): las cinco apps de genesis teseladas en
MasterStack — hola como ventana maestra, el resto apiladas a la derecha,
cada lienzo centrado en su panel.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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>
renaser —kernel asíncrono de espacio de direcciones único, no-POSIX,
`no_std` x86_64— entra al monorepo como su PROPIO workspace de Cargo,
no fusionado: usa toolchain nightly, target `x86_64-unknown-none` y
`panic = "abort"`, incompatibles con los perfiles globales de brahman.
- `renaser/` — copia del proyecto (sin su `.git`; el repo original
conserva su historia standalone). Workspace propio con su
`rust-toolchain.toml` y `.cargo/`.
- `exclude = ["renaser"]` en el workspace de brahman: Cargo lo trata
como ajeno.
- El kernel de renaser path-depende `mirada-layout` cruzando la
frontera de workspace — primer núcleo compartido. Semilla de la
Fase 8 (compositor): geometría de teselado compartida, framebuffer
nativo de renaser; smithay se queda en el lado Linux.
Verificado: `cargo build -p boot` compila kernel + imagen UEFI con
mirada-layout enlazado para bare-metal.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>