feat: guardián no_std de núcleos compartidos + doc de integración renaser
Endurece y documenta la integración renaser↔brahman tras el piloto mirada-layout. - scripts/check-shared-cores.sh: compila cada núcleo compartido registrado para x86_64-unknown-none. Si un núcleo recobra `std` en silencio (dep descuidada), falla aquí y no semanas después en renaser. Hoy cubre mirada-layout. - docs/renaser-integracion.md: por qué renaser es un workspace aparte, el modelo núcleos-duales/superficies-por-plataforma, cómo se hace no_std un núcleo, y el estado del plan por etapas. Paso 2 (converger el CAS) DESCARTADO tras leer el código: arje-cas (blobs SHA256 sobre FS), renaser/almacen (DAG blake3+postcard sobre virtio-blk) y minga-core (Merkle-AST con hash estructural) son tres capas distintas, no una duplicación — converger impondría una abstracción equivocada. Razonado en el doc. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -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`.
|
||||
Executable
+60
@@ -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
|
||||
Reference in New Issue
Block a user