simi: la receta pineada y el veredicto en el SDD — sin construir todavía, y dicho así
recipes/simi.toml sigue el patrón de hammerd/netup: crate del workspace a un commit fijado, zig cc, musl estático, strip_debug. SIN [build.phases]: el BuildSys::Cargo instala el binario, y el symlink `sh` NO lo pone la receta a propósito — quién gana como /bin/sh lo decide USERLAND_COMPONENTS en takana-bootstrap, que es frente C y su propia unidad de trabajo. El SDD queda con el veredicto (simi 0 divergencias, bash 8, brush 35), el alcance por consumidor, los siete bugs del camino y las seis cosas que faltan. Con dos avisos explícitos: lo medido es el build NATIVO del hub (glibc, dinámico) y el estático musl no se construyó, así que simi no entra en ningún perfil de targets.toml; y la shell interactiva de getty no está cubierta.
This commit is contained in:
@@ -906,3 +906,86 @@ tokenizador viejo se comía, y desapareció `i+1`.
|
||||
corre en el hub; el que corre dentro de la imagen es `takana-live-install.sh`, y ése es POSIX.
|
||||
La lista de «quién corre en la imagen» sigue sin estar medida, salvo los 21 empotrados, que lo son
|
||||
por construcción.
|
||||
|
||||
|
||||
---
|
||||
|
||||
# `simi` — el `/bin/sh` propio, ESCRITO y MEDIDO (2026-09-21)
|
||||
|
||||
**Crate:** `crates/simi/` (4448 líneas, `libc` y nada más) · **receta:** `recipes/simi.toml`
|
||||
(pineada, **sin construir todavía**) · **nombre:** *simi* es «boca, lengua» en quechua — es cómo se
|
||||
le habla a la máquina. `rimay` estaba tomado (la familia de embeddings de tawasuyu).
|
||||
|
||||
## El veredicto, primero
|
||||
|
||||
Banco diferencial contra el ash de busybox 1.36.1, **159 casos** — 10 fixtures de regresión, 107 de
|
||||
tortura de comillas, los 23 fragmentos de las cards y los 19 `/init` empotrados:
|
||||
|
||||
| shell | divergencias duras | binario | latencia |
|
||||
|---|---|---|---|
|
||||
| **simi** | **0** | **0,48 MB** | **1,4×** el ash |
|
||||
| bash 5.3.0 | 8 | 1,57 MB | 1,3× |
|
||||
| brush 0.4.0 | 35 | 6,92 MB | 4,1× |
|
||||
|
||||
Incluye el **bucle real de `config.status`** que genera cualquier `configure` de autotools — el que
|
||||
tumbó a brush. Y 47 pruebas propias del crate en verde.
|
||||
|
||||
⚠ **Lo medido es el build NATIVO del hub** (glibc, dinámico). El estático musl con zig cc —que es
|
||||
como viajaría— **no se construyó**: falta la corrida en el lab y su sello. Hasta entonces, `simi` no
|
||||
va en ningún perfil de `docs/state/targets.toml`.
|
||||
|
||||
## El alcance salió de la medición, no de POSIX
|
||||
|
||||
| consumidor | qué necesita | estado |
|
||||
|---|---|---|
|
||||
| las 23 cards de arje con shell | 8 builtins, 13 construcciones, ningún `if`, ninguna función | ✅ |
|
||||
| los 21 `/init` empotrados | + `if`, funciones, `case`, aquí-documentos, `${…}`, posicionales, `&` | ✅ |
|
||||
| `takana-live-install.sh` (corre en la imagen viva) | POSIX entero | ✅ parsea; sin correr |
|
||||
| la shell interactiva de `getty` | edición de línea, historial, control de trabajos | ❌ **no está** |
|
||||
|
||||
Lo que **no** trae, dicho en vez de fingido: control de trabajos, edición de línea, historial,
|
||||
`alias`, `getopts`, `times`, `[[ ]]`, arrays. El shell de `getty` es otro consumidor y sigue
|
||||
pendiente.
|
||||
|
||||
## Los siete bugs — que es la parte que enseña
|
||||
|
||||
Ninguno se veía en la salida. Todos daban resultados plausibles, y **los seis primeros los destapó
|
||||
el banco diferencial**, no el juicio:
|
||||
|
||||
1. **El lexer fundía lo entrecomillado con lo desnudo.** `x="a b"` quedaba como UN seg
|
||||
entrecomillado, el parser ya no veía la asignación —el prefijo antes del `=` tiene que ser
|
||||
desnudo— y **la ejecutaba como una orden**. El error decía «no encontrado», que manda a buscar al
|
||||
lugar equivocado. Ahora el comillado es por carácter.
|
||||
2. **La marca de escape interna chocaba con las barras reales.** La primera versión usaba `\` como
|
||||
marca y la quitaba al final, así que `$(echo \\$V)` perdía la barra que la sustitución había
|
||||
PRODUCIDO (ash: `\hola`, simi: `hola`). **La quita de comillas es sobre las comillas de la
|
||||
palabra, nunca sobre el resultado de una expansión** — y eso no se representa con un escape
|
||||
dentro del texto: hace falta una máscara de protección por carácter.
|
||||
3. **`set -e` no se suspendía dentro de una función llamada desde una condición.** Ahora es un
|
||||
contador DINÁMICO, y por eso entra solo donde tiene que entrar.
|
||||
4. **Los delimitadores de `$( )` y `${ }` no respetaban la barra invertida**: `$(echo \)` cerraba la
|
||||
sustitución cuando el paréntesis estaba escapado y no debía cerrar nada.
|
||||
5. **Las clases `[…]` no entendían `\`** — y `*[\\\`\"\$]*` es literalmente el patrón del
|
||||
`config.status` de libtool.
|
||||
6. **Dentro de comillas dobles, el cuerpo de un backtick sigue entre comillas**, así que la barra
|
||||
también se elimina ante `"`. Sin eso, dos casos de la tortura divergían en los dos sentidos.
|
||||
7. **Y uno que el banco NO vio:** el `trap EXIT` **heredado** se disparaba en el subshell. POSIX
|
||||
§2.12 manda resetearlo al entrar — es la mitad complementaria de brush#1396, y al revés. Lo
|
||||
encontró la prueba de regresión del crate, porque ningún caso del banco lo probaba. **Los dos
|
||||
oráculos hacen falta**, y el caso quedó agregado al fixture 08.
|
||||
|
||||
Las dos invariantes que el fichero de ejecución sostiene a propósito, las dos porque se midieron
|
||||
rotas en el candidato ajeno: **el `trap EXIT` de un subshell corre** (brush#1396) y **`exec`
|
||||
reemplaza el proceso** (si el shell forkea, arje supervisa al shell y no al daemon).
|
||||
|
||||
## Lo que queda, en orden
|
||||
|
||||
1. **Construir la receta en el lab** (zig cc, musl estático) y sellarla. Hasta ahí no hay artefacto.
|
||||
2. **ADR** — escribir un shell propio y meterlo en `ATTEST_PATHS` es una decisión de frontera, y el
|
||||
nombre `simi` también. Este documento la registra; el ADR la decide.
|
||||
3. **Cablear `/bin/sh`**: `USERLAND_COMPONENTS` + el retiro del homónimo (`lib.rs:676`). Es frente C
|
||||
y toca la raíz de confianza del arranque.
|
||||
4. **Medir EJECUTANDO**, no sólo parseando: los `/init` en un arranque de QEMU
|
||||
(`product-boot-test.sh`) y `takana-live-install.sh` en la imagen viva.
|
||||
5. **La shell interactiva de `getty`**, que es el consumidor que falta entero.
|
||||
6. **El sandbox de build sigue con busybox**, y con razón: eso es otro planeta y no está prometido.
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# simi — el `/bin/sh` del producto. Código takana-PROPIO, no una adopción.
|
||||
#
|
||||
# Mismo patrón de receta que netup/hammerd/arje-zero: construye un crate del workspace a un commit
|
||||
# fijado, deps vendoreadas para build hermético `--offline`, link estático con zig cc. Sólo depende
|
||||
# de libc ⇒ vendor mínimo.
|
||||
#
|
||||
# Por qué propio y no adoptado (ver `docs/plan-botar-busybox.md`): el único candidato Rust maduro es
|
||||
# brush, y se midió — 6,9 MB contra 1,17 del busybox entero, 4,1× la latencia de arranque, y dos
|
||||
# divergencias POSIX medidas (reubeno/brush#1394 y #1396, las dos reportadas por nosotros). simi son
|
||||
# 4448 líneas con CERO divergencias contra el ash de busybox en los 159 casos del banco diferencial.
|
||||
#
|
||||
# ⚠ Esta receta todavía NO se construyó: falta la corrida en el lab (zig cc, musl estático) y su
|
||||
# sello. Lo medido hasta acá es el build nativo del hub (glibc dinámico, 499 KB) más las 47 pruebas
|
||||
# del crate. No declarar `simi` en ningún perfil de `docs/state/targets.toml` antes de sellarla.
|
||||
|
||||
name = "simi"
|
||||
version = "0.0.1"
|
||||
license = "MIT"
|
||||
|
||||
[source]
|
||||
# El propio takana. El commit es el identificador inmutable; subirlo cuando simi avance.
|
||||
repo = "https://git.gioser.net/sergio/takana.git"
|
||||
commit = "6809ef4be28f606aae856890a74667187ff75b05"
|
||||
|
||||
[build]
|
||||
compiler = "zig-cc"
|
||||
target = "x86_64-linux-musl"
|
||||
link = "static"
|
||||
|
||||
# Split de la info de depuración, igual que hammerd. Entra en `hash_inputs`.
|
||||
strip_debug = true
|
||||
# Sólo el binario `simi` del workspace.
|
||||
flags = ["-p", "simi"]
|
||||
|
||||
# Sin `[build.phases]`: igual que hammerd y netup, el BuildSys::Cargo del lab instala el binario del
|
||||
# crate. **El symlink `sh` NO lo pone esta receta**, y eso es a propósito: quién gana como `/bin/sh`
|
||||
# lo decide el ensamblado del producto (`USERLAND_COMPONENTS` en `crates/takana-bootstrap/src/lib.rs`,
|
||||
# que hidrata el userland Rust DESPUÉS de busybox para que ensombrezca sus applets, y `lib.rs:676`,
|
||||
# que retira el homónimo de los otros directorios). Ese cableado es frente C y es su propia unidad de
|
||||
# trabajo: mete a simi en la raíz de confianza del arranque, y eso no se hace de paso.
|
||||
Reference in New Issue
Block a user