diff --git a/docs/renaser-integracion.md b/docs/renaser-integracion.md new file mode 100644 index 0000000..c465c4e --- /dev/null +++ b/docs/renaser-integracion.md @@ -0,0 +1,94 @@ +# renaser ↔ brahman — integración en el monorepo + +`renaser` es un kernel bare-metal SASOS (espacio de direcciones único, +no-POSIX, `no_std`, x86_64). Vive en `renaser/` dentro de este repo. Este +documento explica **cómo** convive con brahman y **qué** comparten. + +## Por qué un workspace de Cargo aparte + +renaser está en el mismo repo git pero es **su propio workspace de Cargo** — +no un miembro del de brahman. Tres incompatibilidades lo imponen: + +| | brahman | renaser | +| --- | --- | --- | +| toolchain | `stable` | `nightly` (artifact-deps, `rust-src`) | +| `panic` | unwind (lo necesita tokio) | `abort` (sin SO no hay unwinding) | +| `cargo build` en la raíz | compila todo para el host | el kernel jamás debe compilarse para el host | + +`[profile]` y `rust-toolchain.toml` son **globales al workspace**: no se pueden +mezclar. Por eso `brahman/Cargo.toml` lleva `exclude = ["renaser"]` y +`renaser/Cargo.toml` es un `[workspace]` raíz independiente, con su propio +`rust-toolchain.toml` y `.cargo/`. Cargo los trata como ajenos; los crates +compartidos se referencian por `path` cruzando la frontera. + +## El modelo: núcleos duales, superficies por-plataforma + +La integración **no** es «cada crate compila para los dos lados». Es: + +- **Núcleos** — lógica pura (`*-core`, geometría, contratos). Se hacen + `no_std + alloc` y se comparten: el mismo crate compila para Linux y para + `x86_64-unknown-none`. +- **Superficies** — IO y plataforma (daemons tokio, `sled`, gpui, smithay, + init con `nix`/`libc`; del lado renaser, el kernel y sus drivers). **No** se + comparten: cada plataforma tiene la suya. renaser no «importa» smithay; + provee su propio framebuffer. + +Un crate gana el tratamiento `no_std` **sólo cuando renaser de verdad lo +enlaza**. La mayoría de brahman (apps gpui, ERP, transpilador, daemons) nunca +corre en renaser y se queda `std`. + +## Núcleos compartidos + +| crate | rol | consumidor renaser | +| --- | --- | --- | +| `mirada-layout` | motor de teselado del compositor (geometría pura) | kernel, Fase 8 (compositor) | + +Cómo se hace `no_std` un núcleo (patrón de `mirada-layout`): + +1. `#![cfg_attr(not(test), no_std)]` + `extern crate alloc;` — los tests + siguen corriendo con `std`; el crate enviado es `no_std`. +2. `std::collections` → `alloc::collections`; `Vec`/`vec!` → `use alloc::…`. +3. Punto flotante (`sqrt`/`ceil`/`round`) → crate `libm` (no están en `core`). +4. `serde` opcional tras una feature: los consumidores Linux la activan, el + kernel no. +5. Dependencias declaradas directas (no `workspace = true`): un núcleo que + cruza fronteras de workspace se mantiene autocontenido. + +### El guardián + +`scripts/check-shared-cores.sh` compila cada núcleo registrado para +`x86_64-unknown-none`. Si un núcleo recobra `std` (p. ej. al añadir una +dependencia descuidada), falla ahí. **Correrlo tras tocar un núcleo +compartido.** Al promover un crate nuevo, añadirlo al array `CORES` del script. + +## Plan por etapas — estado + +- **Paso 0 ✅** — renaser movido a `renaser/`, workspace propio, `exclude`. +- **Paso 1 ✅** — `mirada-layout` → `no_std`; el kernel de renaser lo + `path`-depende cruzando workspaces. Mecanismo validado. +- **Paso 2 — descartado.** El plan era «converger el CAS». Al leer el código + no se sostiene: son **tres capas distintas**, no una duplicación. + - `arje-cas` — blobs SHA256 sobre el sistema de archivos. SHA256 lo fija el + contrato `Card` (`module_sha256`); es una *superficie* Linux. + - `renaser/almacen` — DAG de objetos (payload + hijos), hash + `blake3(postcard)`, log sobre virtio-blk. Es una *superficie* bare-metal. + - `minga-core` — Merkle-AST con hash **estructural** (`hash_components`, + campo a campo, no `blake3(postcard)`): un esquema deliberadamente + distinto que permite verificar un nodo sin los bytes de sus hijos. + - Forzar un núcleo común impondría una abstracción equivocada (romper la + verificación estructural de minga, o cambiar el SHA256 del protocolo + `Card`). Lo único común —un newtype de hash de 32 bytes— no justifica + tocar el kernel verificado. +- **Paso 3 — pendiente, bloqueado.** Converger el ABI WASM/`Card`. Requiere + primero unificar `wasmi`: brahman usa `0.40`, renaser `1.0`. +- **Paso 4 ✅** — el guardián `no_std` (`scripts/check-shared-cores.sh`). + +Fase 8 de renaser (su propia hoja de ruta): el kernel usa `mirada-layout` para +el compositor, con su framebuffer nativo. + +## Construir + +- brahman: `cargo build` en la raíz (ignora `renaser/`). +- renaser: `cd renaser && cargo build -p boot` (kernel + imagen UEFI) o + `cargo run -p boot` (+ QEMU). Toma su toolchain nightly automáticamente. +- guardián: `./scripts/check-shared-cores.sh`. diff --git a/scripts/check-shared-cores.sh b/scripts/check-shared-cores.sh new file mode 100755 index 0000000..b335a59 --- /dev/null +++ b/scripts/check-shared-cores.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +# ============================================================================= +# brahman :: check-shared-cores.sh — guardián no_std de los núcleos compartidos +# ----------------------------------------------------------------------------- +# Algunos crates de brahman son NÚCLEOS COMPARTIDOS: lógica pura que también +# compila el kernel bare-metal de renaser (ver docs/renaser-integracion.md). +# Para seguir siéndolo deben permanecer `no_std` — y eso se rompe en silencio +# con sólo añadir una dependencia que arrastre `std`. +# +# Este script es la red de seguridad: compila cada núcleo registrado para +# `x86_64-unknown-none` (el target del kernel de renaser). Si un núcleo +# recobró `std`, la compilación falla aquí y no semanas después en renaser. +# +# Uso: ./scripts/check-shared-cores.sh +# Sale 0 si todos los núcleos compilan no_std; 1 si alguno falla. +# ============================================================================= +set -euo pipefail + +# --- Núcleos compartidos registrados ----------------------------------------- +# Al promover un crate a núcleo compartido (hacerlo `no_std` y enlazarlo desde +# renaser), añádelo a esta lista. Es el contrato: lo que está aquí, renaser lo +# puede consumir; mantenerlo no_std es obligatorio. +CORES=( + mirada-layout # motor de teselado del compositor (Fase 8 de renaser) +) + +TARGET="x86_64-unknown-none" + +cd "$(dirname "$0")/.." + +echo "guardián no_std — núcleos compartidos brahman ↔ renaser" +echo "target bare-metal: ${TARGET}" +echo + +# El target bare-metal debe estar instalado para el toolchain activo. +if ! rustup target list --installed 2>/dev/null | grep -qx "${TARGET}"; then + echo "instalando el target ${TARGET}…" + rustup target add "${TARGET}" +fi + +fallos=0 +for core in "${CORES[@]}"; do + printf ' %-20s ' "${core}" + if cargo build -q -p "${core}" --target "${TARGET}" 2>/tmp/check-core-"${core}".log; then + echo "ok — compila no_std" + else + echo "FALLA — recobró std o no compila bare-metal" + sed 's/^/ /' /tmp/check-core-"${core}".log + fallos=$((fallos + 1)) + fi +done + +echo +if [ "${fallos}" -eq 0 ]; then + echo "todos los núcleos siguen siendo no_std (${#CORES[@]}/${#CORES[@]})." + exit 0 +else + echo "${fallos} núcleo(s) rompieron la garantía no_std." + exit 1 +fi