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>
renaser hablaba consigo mismo. Esta fase abre una boca y una oreja al
exterior con una tarjeta de red, reutilizando el `KernelHal` del
disco y el mapeador MMIO (la pieza estructural que hizo esto posible).
- `drivers/red`: monta `VirtIONet<KernelHal, PciTransport, 16>`,
expone `enviar(frame)` y `drenar_rx(callback)`. Sin pila TCP/IP —
solo Ethernet crudo; la composición de paquetes la hace el llamante.
- `componer_arp_request(mac, ip, objetivo)` construye el saludo
inicial: «¿quien tiene 10.0.2.2?» dirigido al gateway de QEMU.
- `interrupts::registrar_irq_red` + handler `irq_red`, gemelo del de
disco. La IRQ del dispositivo activa `red::atender_irq`, que hace
`ack_interrupt` y suelta la línea.
- `tarea_red` en el reactor: al arrancar envía el ARP, después cada
fotograma drena la cola RX y vuelca cada paquete a COM1.
- QEMU args ganan `-netdev user,id=net0 -device virtio-net-pci`.
Verificado con `-object filter-dump,...,file=/tmp/red.pcap`:
red :: virtio-net :: MAC 52:54:00:12:34:56 :: IRQ Some(11)
red :: ARP REQUEST enviado :: ¿quien tiene 10.0.2.2?
red :: RX 64 bytes :: src=52:55:0a:00:02:02 type=0x0806
El src del paquete entrante (`52:55:0a:00:02:02`) codifica `10.0.2.2`
dentro del MAC — es el gateway de QEMU respondiendo. Renaser ya habla
con el exterior.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
memoriosa (Fase 7c) demostró que un app podía persistir su huella.
Esta fase la lleva al gesto natural: un editor de texto. Tecleas,
reinicias renaser, el texto sigue ahí. La huella vive en el grafo
de objetos como todo lo demás.
- Nuevo crate `apps/bitacora/`: lienzo 480×280, tipografía 8×8
embebida (`font8x8 = "0.3"`) escalada x2 a 16×16, render pixel
a pixel desde la memoria del propio app. Buffer 512 bytes con
wrap automático a 28 columnas; `Enter` salta línea, Backspace
borra; al desbordar el buffer se descartan los 64 primeros para
amortizar la mudanza. Cada cambio invoca `sys_estado_guardar`;
al arrancar, `init` llama a `sys_estado_cargar` y reconstruye.
- Mapeo de scancodes US a ASCII (letras, dígitos, puntuación
básica, espacio). Sin shift ni mayúsculas — minimalismo.
- `GENESIS` crece de 7 a 8 apps; `bitacora` es la PRIMERA — gana
la celda maestra al arrancar y te invita a teclear.
- `CELDA_TASKBAR_ANCHO` baja de 150 a 130 px para que las ocho
pestañas + lanzador + reloj quepan holgadas en 1280 px.
Verificado en QEMU: tras escribir "hola renaser" y reiniciar el
kernel con el mismo disk.img, bitácora muestra el texto donde lo
dejó. El `almacen` reporta 24 objetos en el grafo (frente a 9
antes de escribir) y `raiz presente` — cada `guardar` anexó una
versión al log direccionado por contenido.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
La barra de tareas era pasiva: nombraba pero no hacía. Ahora lleva
en sus extremos los dos adornos de toda barra digna.
- Botón «+» indigo a la izquierda (36 px). Un clic incrementa
`PARTOS` — el mismo contador que `Alt+N` — y la tarea del
compositor lo recoge para lanzar la siguiente app de la rotación.
Teclado y ratón comparten ya la misma vía para crear ventanas.
- Reloj `mm:ss` a la derecha (80 px), leído de
`reloj::milisegundos()`. Tinta blanca sobre slate.
- `compositor::tick_reloj()` lo invoca la tarea del compositor cada
fotograma; recompone solo cuando el segundo del reloj monótono
cambia respecto al último mostrado (`ULTIMO_SEGUNDO: AtomicU64`).
Cero coste mientras no toca refrescar.
- `Taskbar` crece con `launcher`, `reloj` y `reloj_region`; el
layout de las pestañas se ajusta entre ambas cuñas. La cruz del
lanzador se dibuja en píxeles directos —dos rectángulos cruzados,
independiente de la tipografía—.
Verificado en QEMU con dos capturas separadas: la barra muestra el
«+» indigo, las siete pestañas (con `glotona` ya legible) y el
reloj. En la primera marca `0:17`; diez segundos después, `0:29` —
la barra se refrescó doce veces sin intervención.
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>
Las ventanas eran anónimas: el escritorio no sabía nombrar lo que
mostraba. Esta fase le pone un nombre a cada cuarto y una barra al
pie con la lista de quienes lo habitan.
- Cada `Ventana` lleva un `nombre: String` —del manifiesto, o del
orquestador al engendrarla en vivo—. `Plantilla` lo guarda para las
copias que `Alt+N` instancia.
- Franja `FRANJA_TASKBAR=40px` reservada al pie. `area_apps` la
descuenta — las ventanas teselan y flotan sin tapar la barra.
- `consola`: tipos `Taskbar` / `CeldaTaskbar` + métodos `pintar_taskbar`
y `pintar_etiqueta` (rasteriza una cadena en (x, base_y) sobre un
fondo conocido, sin tocar la pluma). La pestaña enfocada se pinta con
el índigo del foco, las desalojadas con su color de baliza, el resto
con el slate del panel.
- `compositor::recomponer` arma las celdas y las pasa junto a las capas
a la consola; un único repintado, una única presentación.
- `atender_raton`: si el clic cae en la franja de la barra,
`celda_taskbar_en` localiza la pestaña pulsada y la enfoca (sin
iniciar arrastre).
Verificado en QEMU: al arrancar, la barra al pie muestra las 7
pestañas con sus nombres; `tonada` enfocada en índigo, `discola` y
`glotona` en sus colores de baliza. Un clic sobre `pulso` traslada el
foco al instante — el borde del compositor envuelve `pulso` y su
pestaña se ilumina.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El `-global pci-hole64-size=0` del commit anterior NO movía los BAR:
verifiqué con `info pci` que OVMF seguía alojando el BAR4 prefetchable
64-bit del virtio-blk en `0xc000000000` (mi Proxmox) o `0x800000000`
(la laptop del usuario). El cargador `bootloader_api` 0.11 mapea la
memoria física pero no extiende su mapeo hasta la ventana PCI de 64
bits, y `KernelHal::mmio_phys_to_virt` devolvía `phys + offset` a
ciegas — un puntero a memoria sin tabla de páginas, al primer registro
MMIO leído → #PF.
La solución: un mapeador MMIO propio del kernel.
- `memory::mmio`: envuelve la tabla L4 activa (vía CR3 + el mapeo de
memoria física del cargador) en un `OffsetPageTable`. Su función
`mapear(fisica, tam)` abre, para cada página de la región, una
entrada en la L4 con `PRESENT | WRITABLE | NO_CACHE | WRITE_THROUGH`
— las banderas habituales del MMIO.
- Los marcos para tablas intermedias salen del banco DMA del disco
(`drivers::disco::asignar_marco_para_tabla`, sin pánico). Se ponen
a cero antes de cederlos: las tablas empiezan vacías.
- Tratamos `PageAlreadyMapped` y `ParentEntryHugePage` como éxito: la
región ya estaba cubierta por el cargador (con páginas 4 KiB o
hugepages 2 MiB / 1 GiB) y el acceso ya funciona. Solo abortamos el
mapeo si se nos agota la arena DMA.
- `KernelHal::mmio_phys_to_virt` llama a `memory::mmio::mapear` antes
de devolver el puntero virtual. virtio-drivers lo invoca con la
base y el tamaño exactos de cada BAR; el kernel asegura que cada
uno sea accesible antes de devolverlo.
- `kernel_main` funda el mapeador justo después del heap (paso 4.5),
antes del disco. Necesita `physical_memory_offset` para alcanzar
la L4 activa.
Quito el `-global q35-pcihost.pci-hole64-size=0` que añadí antes: no
movía los BAR (verificado con `info pci`) y solo confundía la
descripción del fix. Esta solución es la robusta: el kernel sabe
mapear sus propios MMIOs y deja de depender del firmware.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Esta era la verdadera causa del «pantalla negra + franja roja» en máquinas
distintas a la del autor. El trace de boot del usuario lo cantó:
boot :: disco :: init <- llegamos aquí
disco :: init offset=0x20000000000 region=[...] base=...
boot :: almacen :: init <- y aquí
*** renaser :: panico ***
EXCEPCION FATAL :: fallo de pagina (#PF) en 0x20800000014
0x20800000014 - phys_offset(0x20000000000) = 0x800000014 (= 32 GiB + 0x14)
Un acceso vía el mapeo de memoria física a phys=32 GiB. Eso es el BAR
MMIO del virtio-blk: OVMF en QEMU q35 moderno con KVM aloja los BARs
prefetchables 64-bit en el «pci hole» de 64 bits (típicamente a partir
de 32 GiB). El `bootloader` 0.11 con `Mapping::Dynamic` mapea la RAM
del sistema, pero no extiende el mapeo hasta los BARs ahí arriba.
KernelHal::mmio_phys_to_virt devolvía `phys + offset` sin verificar
nada — el host esperaba que el BAR estuviese en los primeros 4 GiB,
como mi Proxmox con TCG y mi nightly. En la laptop con KVM y el OVMF
del usuario, OVMF lo subía y todo reventaba al leer el primer registro.
El parche: `-global q35-pcihost.pci-hole64-size=0` en los args por
defecto de QEMU. Apaga la ventana PCI de 64 bits, OVMF se ve forzada
a alojar todos los BARs en los primeros 4 GiB y el mapeo del cargador
los cubre. Verificado: arranca limpio en Proxmox y debería arrancar
también en la laptop del usuario.
(Las verificaciones unchecked_mul del commit anterior eran una pista
falsa — eran solo donde caía la IP del último build; el fallo de
escritura siempre fue el mismo BAR sin mapear.)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Era la causa raíz del «pantalla negra + franja roja» en máquinas con
nightlies recientes (laptops, KVM, etc.) que mi Proxmox no exhibía:
- En modo debug, la stdlib inyecta `<usize>::unchecked_mul::precondition_check`
en cada `unchecked_mul` (RawVec::current_memory, in_place_collect…).
- El camino de pánico de ese check, en bare-metal, escribe en regiones
que el cargador no mapeó → #PF → al panic handler del kernel, que pinta
la franja roja: un colapso DENTRO de la red de seguridad del colapso.
- 1202 callsites en el binario debug — uno fallaba en la laptop del usuario.
El fix: `rustflags = ["-Cdebug-assertions=off", "-Coverflow-checks=off"]`
en `[target.x86_64-unknown-none]` de `.cargo/config.toml`. Los `[profile]`
del manifiesto no propagaban a las deps precompiladas (wasmi, virtio-
drivers, etc., que se quedan como artifact-deps fuera del workspace);
`rustflags` por target sí. Tras un `cargo clean` + rebuild, cero llamadas
a precondition_check, y el boot trace por COM1 corre completo.
También: `[profile.dev]`/`[profile.release]` del kernel y workspace
declaran los flags explícitamente, por si alguna ruta de cargo cambia.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Para localizar dónde colapsa el kernel en máquinas que no son la del
autor, cada hito de `kernel_main` deja una traza por COM1 (con el
panic-handler-a-serie de antes, ya tenemos boot trace + autopsia).
- `baliza::Serie` se hace `pub(crate)` para que cualquier módulo deje
trazas con `writeln!(baliza::Serie, ...)`.
- `kernel_main`: traza tras adoptar el framebuffer, encender la baliza,
fundar GDT/IDT/PIC, fundar el heap, fundar teclado/reloj/texto,
publicar la consola, iniciar disco y almacén, arrancar el ratón,
crear el ejecutor, cargar el userspace y arrancar el reactor. Y un
volcado de `physical_memory_offset` + `region_dma` al inicio.
- `drivers::disco::init`: registra offset, región, base de la arena y
número de marcos disponibles.
- Endurecimiento: `disco::init` ahora salta SIEMPRE la primera página
física al elegir la base de la arena DMA. Algunos cargadores la dejan
sin mapear como protección NULL; un marco DMA ahí se traduce a una
dirección que peta al desreferenciar.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
En pantalla solo cabe la franja roja: un grito breve, sin matiz. Para
diagnosticar colapsos en máquinas distintas a la del autor —donde no
es posible reproducirlos a mano—, los manejadores de fallo escriben
ahora una pista por COM1, además de pintar la franja.
- `baliza`: sumidero `Serie` que formatea sin tocar el heap, escribe a
0x3F8 con espera acotada (antes mudo que colgar el sistema).
- El panic-handler vuelca el mensaje y la ubicación del `panic!`.
- El alloc-error-handler vuelca el `Layout` que reventó el techo.
QEMU con `-serial stdio` enruta COM1 a la terminal de `cargo run` — la
pista llega a quien lanzó el kernel, aunque la pantalla esté en negro.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.
- Driver `drivers/raton`: el ratón PS/2 cuelga del dispositivo
auxiliar del 8042 + IRQ12. El driver despierta el aux, programa
su IRQ, le ordena reportar, ensambla paquetes de 3 bytes con
guarda del bit-3. Posición como atómicos, eventos como cola
lock-free — el mismo guardarraíl que el teclado.
- El puntero, capa de PRESENTACIÓN: `Pantalla::estampar_puntero`
pinta un sprite de flecha 12×18 sobre el framebuffer después de
copiar el lienzo. El lienzo nunca lo contiene — hace de
save-under natural—.
- Compositor: `atender_raton` drena eventos. Botón bajando es un
clic-para-enfocar consistente con `mover_foco` (silencia bocina,
alza si flota). Si la enfocada flota, arranca un arrastre con el
desfase de agarre; el botón sostenido la sigue al puntero; al
soltar, termina.
- `refrescar_puntero` reestampa el framebuffer si el puntero se
movió en una vuelta tranquila en que ninguna app pintó.
Verificado en QEMU (mouse_move / mouse_button del monitor): el
puntero aparece al arrancar, se mueve por la pantalla, un clic
sobre pulso le da el foco, y un arrastre con el botón sostenido
mueve la flotante de la cascada al centro-abajo.
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 censo de aplicaciones deja de fijarse en el arranque: una app puede
nacer o cerrarse con el reactor ya en marcha.
- El reactor admite NACIMIENTOS en vivo: cola `NACIMIENTOS` +
`engendrar()`, drenada al inicio de cada vuelta de `run()`;
`Task::adoptar` acoge un futuro ya empaquetado.
- `Alt+Q` (`Mando::Cerrar`): baja limpia. El compositor saca la
ventana enfocada del teselado y del orden-Z; la app advierte la
baja (`ventana_cerrada`) y concluye su tarea — su memoria, su
combustible y su canal de teclado se liberan. Sin baliza.
- `Alt+N` (`Mando::Lanzar`): alta en vivo. `nacer_ventana` añade la
ventana y entrega su índice; el orquestador instancia el WASM y
engendra su tarea. Las apps de génesis dejan su bytecode cacheado
como `Plantilla`; cada `Alt+N` instancia una en rotación.
Verificado en QEMU (sendkey): tres Alt+N hacen crecer el escritorio
de 5 a 8 ventanas; tres Alt+Q lo reducen de 8 a 5. Kernel estable.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Segundo modelo de composición sobre el teselado de la Fase 8: el
SOLAPAMIENTO. Una ventana puede abandonar el teselado y FLOTAR sobre
las demás.
- `Escritorio` gana `flotantes: Vec<usize>` — la pila orden-Z, de
atrás hacia adelante; con `orden` forma una partición de las
ventanas.
- Mando `Flotar` (`Alt+F`): alterna la ventana enfocada entre
teselada y flotante; una flotante nace con marco propio en cascada,
al frente del orden-Z.
- `compositor::recomponer` + `consola::recomponer` (tipos `Capa` /
`Contenido`): con flotantes vivas el escritorio se repinta entero,
capa a capa de atrás hacia adelante — el solapamiento se resuelve
por el orden del pintado. Sin flotantes, camino rápido de la Fase 8.
- El foco recorre todas las ventanas y alza al frente la flotante
enfocada.
Verificado en QEMU (sendkey): flotar, cascada, alzado-Z y regreso al
teselado.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El escritorio se podía recorrer con el foco, pero no reordenar. La 8d lo
hace manipulable: el orden de teselado se separa de la identidad.
- Escritorio gana `orden: Vec<usize>` — una permutacion que dice que
ventana ocupa cada celda. Mover una ventana cambia su celda, no su
indice_app: conserva su canal de teclado y su ranura de estado.
- aplicar_teselado reparte los marcos segun el orden.
- Alt+Enter promueve la ventana enfocada a la celda maestra; Alt+H/Alt+L
la reordenan. mover_foco recorre ahora el orden, no los indices crudos.
Verificado en QEMU (sendkey): con memoriosa enfocada, Alt+Enter la
promueve a maestra y hola baja a la pila; Alt+L la devuelve a la pila. El
foco —el borde indigo— viaja siempre con la ventana, no con la celda.
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>
El kernel deja de empotrar el userspace por completo. Ya no carga ni un
solo .wasm: es boot quien siembra el disco con el grafo poblado.
- kernel/almacen.rs y manifiesto.rs migran al nucleo compartido `formato`
(tipos, postcard, BLAKE3, trazado de registros). El kernel pierde los
include_bytes!, genesis() y sembrar_genesis().
- boot::sembrar_grafo siembra un disco virgen con el bytecode de las apps
(deduplicado) y el Manifiesto de Genesis anclado en el superbloque.
- cargar_userspace sin rama de siembra; wasm/mod.rs sin TECHO_MEMORIA.
- alias `cargo kernel` -> --manifest-path (esquiva un ICE de cargo con
formato compartido entre el kernel y boot via artifact-dep).
Verificado en QEMU (screendump): disco virgen -> boot siembra 5 objetos,
el kernel monta su grafo; segundo arranque -> boot respeta el disco, la
cronista persiste. formato: 5/5 pruebas.
Nota: el crate `formato` y los 3 Cargo.toml entraron antes en 43e6b32 por
un `git add -A` de un trabajo concurrente; este commit cierra el resto.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El corpus ya rebana la carta en tajadas vivenciales: una sola
configuración mirada plano a plano, sin promediar la contradicción.
- Colocacion / AspectoEnCarta: la posición real de un planeta en una
carta — el puente entre el motor astronómico y las claves del JOIN.
- combinaciones_de_carta: deriva todas las CombinacionId de una carta.
- rebanar_por_dominio: la tomografía — cada planeta@cN cae en el
dominio de su casa, cada planeta·signo hereda el de su casa, y un
aspecto puentea apareciendo en las dos tajadas que conecta.
- Corpus::interpretar_por_dominio: el JOIN agrupado por dominio,
entrada directa del gráfico «por tajadas».
- CombinacionId acepta el alias ASCII '/' del punto medio '·'.
- ejemplo.ron: plantilla cargable y comentada del corpus.
- GUIA.md: los pasos exactos para generar el corpus a mano.
12 tests verdes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Captura headless por el monitor de QEMU (screendump) de los dos caminos
del Manifiesto de Génesis:
- Disco virgen: sembrar_genesis() puebla el grafo y ancla el manifiesto;
consola imprime «genesis sembrada» + «5 apps nacidas del grafo».
- Disco ya sembrado: cargar() lee el manifiesto del ancla del superbloque
sin resembrar; «grafo montado :: 6 objetos :: raíz presente», la
cronista pinta su segunda celda (la cuenta de arranques perdura).
Pantalla idéntica a la Fase 6.2 en ambos casos. CHANGELOG: la sección
«Pendiente de verificación» de la 7a pasa a «Verificado».
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El kernel deja de empotrar las apps. Las cinco aplicaciones ya no
llegan por include_bytes! en main.rs: nacen del grafo, gobernadas por
un Manifiesto de Génesis que también vive en el grafo.
- almacen: el SuperBloque gana el ancla `manifiesto: Option<Hash>`
(gemela de `raiz`, del lado del kernel) + accesores. VERSION 1→2 —
un disco v1 se reformatea.
- manifiesto.rs: implementados `cargar` (lee el manifiesto del grafo)
y `sembrar_genesis` (puebla un disco virgen con las 5 apps de
génesis). El bytecode viaja empotrado AÚN, sólo como semilla
transitoria (la Fase 7b lo mueve al constructor de imagen `boot`).
- kernel_main: `cargar_userspace` reemplaza las 5 `encender_app`
escritas a mano; `encender_app` recupera el bytecode del grafo —
`recuperar` verifica el hash, un módulo corrupto se niega y el
arranque sigue.
- wasm: el techo de memoria pasa a ser por-app (del manifiesto).
Compila limpio. Verificación en QEMU pendiente (la corre el operador):
la pantalla debe verse idéntica a la Fase 6.2 + la línea «manifiesto».
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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>
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>