takana etapa 5c: comentarios de scripts, MOTD, y un BUG que introdujo la etapa 4
250 líneas de comentario en 151 scripts. Control verificado: el diff no toca NI UNA línea que no empiece por #, y la sintaxis de los 151 pasa. El barrido saltea heredocs y cadenas triples, y el guardián DISPARÓ 3 veces: las tres eran el MOTD que el script escribe DENTRO de la imagen construida — texto del producto, no comentario del script. Se cambiaron aparte y a propósito, que es rebranding, no limpieza. Y el hallazgo caro: casaba contra , que es el TARGET de tracing — o sea el module_path!, o sea el nombre del crate. La etapa 4 lo movió a y el script quedó casando NADA. No fallaba: imprimía cero atribuciones, indistinguible de un log sin problemas. Comprobado con el binario (RUST_LOG=info sobre zlib), no deducido. Ahora acepta las dos, y tiene que seguir aceptándolas porque los logs viejos en disco dicen la vieja. Además 14 rutas de módulo en docs, que el barrido anterior no tocó porque no es frontera de palabra.
This commit is contained in:
@@ -112,7 +112,7 @@ esté probado.
|
|||||||
El crate `takana-agent` (Fase 6) expone:
|
El crate `takana-agent` (Fase 6) expone:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// hammer_agent::client
|
// takana_agent::client
|
||||||
pub struct AgentClient { pub welcome: Welcome, /* … */ }
|
pub struct AgentClient { pub welcome: Welcome, /* … */ }
|
||||||
impl AgentClient {
|
impl AgentClient {
|
||||||
pub fn connect(sock: &Path) -> Result<Self>;
|
pub fn connect(sock: &Path) -> Result<Self>;
|
||||||
@@ -124,12 +124,12 @@ impl AgentClient {
|
|||||||
pub fn next_async(&self, timeout: Duration) -> Result<Event>;
|
pub fn next_async(&self, timeout: Duration) -> Result<Event>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// hammer_agent::translator
|
// takana_agent::translator
|
||||||
pub trait IntentTranslator { fn translate(&self, intent: &str, ctx: &SystemContext) -> Result<Swm, TranslateError>; }
|
pub trait IntentTranslator { fn translate(&self, intent: &str, ctx: &SystemContext) -> Result<Swm, TranslateError>; }
|
||||||
pub struct MockTranslator { /* HashMap<intent, Swm> */ }
|
pub struct MockTranslator { /* HashMap<intent, Swm> */ }
|
||||||
pub struct IntentCatalog { pub intents: Vec<CatalogEntry> } // YAML loader
|
pub struct IntentCatalog { pub intents: Vec<CatalogEntry> } // YAML loader
|
||||||
|
|
||||||
// hammer_agent::orchestrator
|
// takana_agent::orchestrator
|
||||||
pub struct Orchestrator<T: IntentTranslator> { /* … */ }
|
pub struct Orchestrator<T: IntentTranslator> { /* … */ }
|
||||||
impl<T> Orchestrator<T> {
|
impl<T> Orchestrator<T> {
|
||||||
pub fn new(t: T, base: BaseRef, apply: ApplyTarget, compile: CompileMode) -> Self;
|
pub fn new(t: T, base: BaseRef, apply: ApplyTarget, compile: CompileMode) -> Self;
|
||||||
|
|||||||
+5
-5
@@ -71,7 +71,7 @@ pre-requisito de validación.
|
|||||||
`open_by_handle_at`+`CAP_DAC_READ_SEARCH`) queda para el track posterior: `nix` 0.30 no
|
`open_by_handle_at`+`CAP_DAC_READ_SEARCH`) queda para el track posterior: `nix` 0.30 no
|
||||||
parsea los info-records de FID y el modo FID perdería el fd que hoy hashea el contenido.
|
parsea los info-records de FID y el modo FID perdería el fd que hoy hashea el contenido.
|
||||||
- [x] Hash del contenido tras la mutación (`content_hash`) y de-dup idempotente.
|
- [x] Hash del contenido tras la mutación (`content_hash`) y de-dup idempotente.
|
||||||
`hammer_journal::content_hash_of`/`hash_file` (blake3 plano, estilo `b3sum`, distinto del
|
`takana_journal::content_hash_of`/`hash_file` (blake3 plano, estilo `b3sum`, distinto del
|
||||||
`of_inputs` de artefactos). `Journal::record_dedup` omite el evento si deja el archivo
|
`of_inputs` de artefactos). `Journal::record_dedup` omite el evento si deja el archivo
|
||||||
idéntico al último de ese path (o un `Delete` sobre algo ya borrado); `last_for_path` lo
|
idéntico al último de ese path (o un `Delete` sobre algo ya borrado); `last_for_path` lo
|
||||||
resuelve. El watcher hashea cada `CLOSE_WRITE` y usa `record_dedup`: una reescritura sin
|
resuelve. El watcher hashea cada `CLOSE_WRITE` y usa `record_dedup`: una reescritura sin
|
||||||
@@ -86,7 +86,7 @@ pre-requisito de validación.
|
|||||||
- [x] Bridge `Mutation::SourcePatch` → `Recipe` + `build` + hidratación.
|
- [x] Bridge `Mutation::SourcePatch` → `Recipe` + `build` + hidratación.
|
||||||
- [x] CLI: `takana apply [--prefix DIR] [--base-ref base.json]`,
|
- [x] CLI: `takana apply [--prefix DIR] [--base-ref base.json]`,
|
||||||
`takana swm-verify`, `takana export --journal DIR > out.swm`.
|
`takana swm-verify`, `takana export --journal DIR > out.swm`.
|
||||||
- [x] `patch_url` / `content_url` remotos. `hammer_build::download` (curl, sólo fuera del
|
- [x] `patch_url` / `content_url` remotos. `takana_build::download` (curl, sólo fuera del
|
||||||
sandbox; acepta `file://` para tests offline). `build_source_patch` descarga `patch_url`
|
sandbox; acepta `file://` para tests offline). `build_source_patch` descarga `patch_url`
|
||||||
al `swm-recipes/<commit>.patch` antes de compilar; `takana apply` descarga `content_url`
|
al `swm-recipes/<commit>.patch` antes de compilar; `takana apply` descarga `content_url`
|
||||||
y **verifica BLAKE3 antes de escribir** (hash erróneo ⇒ nada tocado). Su integridad la
|
y **verifica BLAKE3 antes de escribir** (hash erróneo ⇒ nada tocado). Su integridad la
|
||||||
@@ -98,7 +98,7 @@ pre-requisito de validación.
|
|||||||
modelados: `Mutation::SourcePatch` (y `RecipeInline`) llevan campos `repo`/`commit`
|
modelados: `Mutation::SourcePatch` (y `RecipeInline`) llevan campos `repo`/`commit`
|
||||||
**xor** `tarball`/`sha256` (resueltos por `swm::swm_source_kind`, misma regla que
|
**xor** `tarball`/`sha256` (resueltos por `swm::swm_source_kind`, misma regla que
|
||||||
`recipe::Source::kind`); `takana export` reconstruye ambos sin caer a `file_drop`.
|
`recipe::Source::kind`); `takana export` reconstruye ambos sin caer a `file_drop`.
|
||||||
- [x] Firma `signature` (ed25519) y `TrustStore` local. `hammer_core::sign`: `KeyPair`
|
- [x] Firma `signature` (ed25519) y `TrustStore` local. `takana_core::sign`: `KeyPair`
|
||||||
(genera/carga/escribe claves), `TrustStore::load(dir)` (lee `*.ed25519.pub`),
|
(genera/carga/escribe claves), `TrustStore::load(dir)` (lee `*.ed25519.pub`),
|
||||||
`Swm::verify_signature(&trust) → SigStatus` (`trusted`/`unknown-key`/`bad-sig`/
|
`Swm::verify_signature(&trust) → SigStatus` (`trusted`/`unknown-key`/`bad-sig`/
|
||||||
`unsigned`) sobre bytes canónicos JSON del manifiesto sin la firma. CLI:
|
`unsigned`) sobre bytes canónicos JSON del manifiesto sin la firma. CLI:
|
||||||
@@ -121,7 +121,7 @@ pre-requisito de validación.
|
|||||||
- [x] Subsistemas independientes en `hammerd::main` (FIFO/watcher/bus en threads); si uno
|
- [x] Subsistemas independientes en `hammerd::main` (FIFO/watcher/bus en threads); si uno
|
||||||
falla en init, los demás siguen.
|
falla en init, los demás siguen.
|
||||||
- [x] Política expresiva leída de `/etc/hammer/agent-caps.toml` (`hammerd --agent-caps`).
|
- [x] Política expresiva leída de `/etc/hammer/agent-caps.toml` (`hammerd --agent-caps`).
|
||||||
`hammer_core::AgentCapsConfig`: `default` + `[[rule]]` por `uid`/`gid` (primera que casa
|
`takana_core::AgentCapsConfig`: `default` + `[[rule]]` por `uid`/`gid` (primera que casa
|
||||||
gana), `caps_for(uid,gid)`. `bus::policy_from_config` la enchufa; sin fichero o con
|
gana), `caps_for(uid,gid)`. `bus::policy_from_config` la enchufa; sin fichero o con
|
||||||
fichero inválido, cae a la política por-UID por defecto (avisando). Ejemplo en
|
fichero inválido, cae a la política por-UID por defecto (avisando). Ejemplo en
|
||||||
`examples/agent-caps.toml`. El `default_policy` hardcoded queda como fallback.
|
`examples/agent-caps.toml`. El `default_policy` hardcoded queda como fallback.
|
||||||
@@ -328,7 +328,7 @@ Diseño completo en [SDD 11 — Bootstrap from-scratch](11-bootstrap.md). Resume
|
|||||||
de-Alpinizados:** `recipes/{flex,bison}.toml` (kconfig), `recipes/openssl.toml` (3.5.4, certs/extract-cert),
|
de-Alpinizados:** `recipes/{flex,bison}.toml` (kconfig), `recipes/openssl.toml` (3.5.4, certs/extract-cert),
|
||||||
`recipes/elfutils.toml` (sólo libelf 0.194 para objtool, con shims musl mínimos). Capa de arranque
|
`recipes/elfutils.toml` (sólo libelf 0.194 para objtool, con shims musl mínimos). Capa de arranque
|
||||||
restante: m4, libz/libzstd, gcc (status libc).
|
restante: m4, libz/libzstd, gcc (status libc).
|
||||||
- ✅ **Etapa A — orquestador `bootstrap all` + log de transparencia exportable:** `hammer_bootstrap::all`
|
- ✅ **Etapa A — orquestador `bootstrap all` + log de transparencia exportable:** `takana_bootstrap::all`
|
||||||
encadena stage0→stage1→stage2 en una corrida del host (`takana bootstrap all --url … --sha256 … --version …`)
|
encadena stage0→stage1→stage2 en una corrida del host (`takana bootstrap all --url … --sha256 … --version …`)
|
||||||
y deja el `bootstrap.json` poblado; `takana bootstrap manifest` lo imprime (la superficie de publicación
|
y deja el `bootstrap.json` poblado; `takana bootstrap manifest` lo imprime (la superficie de publicación
|
||||||
del log, SDD 11 §4). El veredicto `✓ REPRODUCIBLE` lo sigue sellando el rebuild in-VM (`selfhost-verify.sh`),
|
del log, SDD 11 §4). El veredicto `✓ REPRODUCIBLE` lo sigue sellando el rebuild in-VM (`selfhost-verify.sh`),
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ confianza de Alpine y la deriva de su propio [log de transparencia](09-trust-mod
|
|||||||
|
|
||||||
Modelamos el toolchain semilla como una **fuente fijada**, no como un build: un `Source` de
|
Modelamos el toolchain semilla como una **fuente fijada**, no como un build: un `Source` de
|
||||||
tipo tarball con `sha256` pinned (`zig-<ver>-linux-x86_64.tar.xz`, o el tarball de
|
tipo tarball con `sha256` pinned (`zig-<ver>-linux-x86_64.tar.xz`, o el tarball de
|
||||||
`musl-cross-make`). `takana-bootstrap` lo descarga (fuera del sandbox, como `hammer_build::download`
|
`musl-cross-make`). `takana-bootstrap` lo descarga (fuera del sandbox, como `takana_build::download`
|
||||||
ya hace para `patch_url`/`content_url`), verifica el sha256 **antes** de sellarlo, y lo deposita
|
ya hace para `patch_url`/`content_url`), verifica el sha256 **antes** de sellarlo, y lo deposita
|
||||||
en el store con un `artifact_hash` derivado de ese sha256. A partir de ahí el resto del
|
en el store con un `artifact_hash` derivado de ese sha256. A partir de ahí el resto del
|
||||||
bootstrap depende del *hash del store*, no de la ruta del host.
|
bootstrap depende del *hash del store*, no de la ruta del host.
|
||||||
@@ -262,7 +262,7 @@ el toolchain) y **correr el rebuild anidado** en la VM.
|
|||||||
|
|
||||||
### 7.4 Estado: builder ensamblado + rebuild in-VM ejecutado ✅ ✓ REPRODUCIBLE
|
### 7.4 Estado: builder ensamblado + rebuild in-VM ejecutado ✅ ✓ REPRODUCIBLE
|
||||||
|
|
||||||
El **ensamblado** del builder está implementado (`hammer_bootstrap::builder_rootfs`, variante a):
|
El **ensamblado** del builder está implementado (`takana_bootstrap::builder_rootfs`, variante a):
|
||||||
|
|
||||||
```
|
```
|
||||||
takana bootstrap builder --stage1 <H> --seed-hash <H> \
|
takana bootstrap builder --stage1 <H> --seed-hash <H> \
|
||||||
|
|||||||
@@ -80,11 +80,11 @@ kernel en `/boot`, los módulos GRUB en `/boot/grub/i386-pc` y los pasos `grub-m
|
|||||||
anuncia el `of_tree` esperado (de un índice de **mirror E3** o release firmada), el apply lo exige antes
|
anuncia el `of_tree` esperado (de un índice de **mirror E3** o release firmada), el apply lo exige antes
|
||||||
de tocar el root. Maneja ficheros regulares + symlinks; valida E2E en host con `scripts/upgrade-e2e-test.sh`
|
de tocar el root. Maneja ficheros regulares + symlinks; valida E2E en host con `scripts/upgrade-e2e-test.sh`
|
||||||
(apply v1→v2→rollback→rollback contra el binario real). **GC de generaciones ✅** (`takana upgrade
|
(apply v1→v2→rollback→rollback contra el binario real). **GC de generaciones ✅** (`takana upgrade
|
||||||
prune [--keep N]` / `hammer_upgrade::prune`): borra las generaciones que el rollback ya no alcanza
|
prune [--keep N]` / `takana_upgrade::prune`): borra las generaciones que el rollback ya no alcanza
|
||||||
(huérfanas tras un rollback — las de la [cadena viva](#) siempre se conservan); `--keep N` además
|
(huérfanas tras un rollback — las de la [cadena viva](#) siempre se conservan); `--keep N` además
|
||||||
recorta la cadena a sus N más nuevas (limita la profundidad de rollback, como `delete-generations` en
|
recorta la cadena a sus N más nuevas (limita la profundidad de rollback, como `delete-generations` en
|
||||||
NixOS). **Journal de intención + replay ✅** (`takana upgrade recover [--rollback]` /
|
NixOS). **Journal de intención + replay ✅** (`takana upgrade recover [--rollback]` /
|
||||||
`hammer_upgrade::{pending,recover}`): el apply escribe el **plan completo** a `pending.json` ANTES de
|
`takana_upgrade::{pending,recover}`): el apply escribe el **plan completo** a `pending.json` ANTES de
|
||||||
proyectar y lo limpia al commitear; si un corte/reinicio lo interrumpe, `pending.json` sobrevive y el
|
proyectar y lo limpia al commitear; si un corte/reinicio lo interrumpe, `pending.json` sobrevive y el
|
||||||
FHS quedó a medias. La proyección es **re-entrante** (`project_plan`, backups *idempotentes* —
|
FHS quedó a medias. La proyección es **re-entrante** (`project_plan`, backups *idempotentes* —
|
||||||
`backup_existing_once` nunca pisa el original capturado), así `recover` **completa** (roll-forward:
|
`backup_existing_once` nunca pisa el original capturado), así `recover` **completa** (roll-forward:
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ muerto antes del takeover).
|
|||||||
hace `switch_root` a la ext4 real. Ese initrd chico es lo que destraba EFI-stub directo (el cuelgue
|
hace `switch_root` a la ext4 real. Ese initrd chico es lo que destraba EFI-stub directo (el cuelgue
|
||||||
del metal era por un initrd de 100MB). Validado en OVMF por `scripts/efi-disk-boot-test.sh`. (La vía
|
del metal era por un initrd de 100MB). Validado en OVMF por `scripts/efi-disk-boot-test.sh`. (La vía
|
||||||
squashfs+overlay del [post-etapa-e] queda como optimización futura; el pivote a ext4 ya cumple.)
|
squashfs+overlay del [post-etapa-e] queda como optimización futura; el pivote a ext4 ya cumple.)
|
||||||
3. **Contrato de generaciones-grafo** ✅ (módulo `hammer_upgrade::boot_graph` + subcomando `takana
|
3. **Contrato de generaciones-grafo** ✅ (módulo `takana_upgrade::boot_graph` + subcomando `takana
|
||||||
boot`): el modelo in-place de generaciones se lee como un **grafo de estados** navegable (id =
|
boot`): el modelo in-place de generaciones se lee como un **grafo de estados** navegable (id =
|
||||||
`of_tree`, DAG por `parent`), `takana boot graph` emite `/run/hammer/boot-graph.json` con el
|
`of_tree`, DAG por `parent`), `takana boot graph` emite `/run/hammer/boot-graph.json` con el
|
||||||
formato del contrato, y `takana boot activate <id>` (o `--from-select`) deja el sistema en un nodo
|
formato del contrato, y `takana boot activate <id>` (o `--from-select`) deja el sistema en un nodo
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ Es el mismo fichero de lock que toman `scripts/farm/farm-worker-loop.sh` y `camp
|
|||||||
que con esto quedan serializados los tres. Deliberadamente **no** está dentro de `takana build`: los
|
que con esto quedan serializados los tres. Deliberadamente **no** está dentro de `takana build`: los
|
||||||
scripts de la granja ya lo toman por fuera y takana se bloquearía contra ellos.
|
scripts de la granja ya lo toman por fuera y takana se bloquearía contra ellos.
|
||||||
|
|
||||||
Nada más del armador toca el store: `plan` calcula el `ArtifactHash` con `hammer_build::artifact_hash`,
|
Nada más del armador toca el store: `plan` calcula el `ArtifactHash` con `takana_build::artifact_hash`,
|
||||||
que es cómputo puro sobre las recetas, y `probe`/`gate`/`bundles`/`closure` sólo leen.
|
que es cómputo puro sobre las recetas, y `probe`/`gate`/`bundles`/`closure` sólo leen.
|
||||||
|
|
||||||
**Si el build muere con «no encuentro el ejecutable zig en …», el zig está bien: falta ESA versión.**
|
**Si el build muere con «no encuentro el ejecutable zig en …», el zig está bien: falta ESA versión.**
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# alpine-import.sh <pkg> [main|community] — Etapa G, fuente #2: baja el APKBUILD de Alpine aports
|
# alpine-import.sh <pkg> [main|community] — Etapa G, fuente #2: baja el APKBUILD de Alpine aports
|
||||||
# (y SUS PARCHES de musl), y emite la receta hammer vía `hammer import-alpine`. Alpine es la mejor
|
# (y SUS PARCHES de musl), y emite la receta takana vía `takana import-alpine`. Alpine es la mejor
|
||||||
# semilla cuando importar de nix falla en musl: su receta YA incluye el trabajo de portabilidad.
|
# semilla cuando importar de nix falla en musl: su receta YA incluye el trabajo de portabilidad.
|
||||||
#
|
#
|
||||||
# Ej: scripts/alpine-import.sh coreutils main > recipes/coreutils-alpine.toml
|
# Ej: scripts/alpine-import.sh coreutils main > recipes/coreutils-alpine.toml
|
||||||
@@ -18,7 +18,7 @@ BASE="https://gitlab.alpinelinux.org/alpine/aports/-/raw/${BRANCH}/${REPO}/${PKG
|
|||||||
apk=$(curl -fsSL "${BASE}/APKBUILD") || { echo "no encontré ${REPO}/${PKG} en aports@${BRANCH}" >&2; exit 1; }
|
apk=$(curl -fsSL "${BASE}/APKBUILD") || { echo "no encontré ${REPO}/${PKG} en aports@${BRANCH}" >&2; exit 1; }
|
||||||
toml=$(printf '%s' "$apk" | $HAMMER import-alpine -)
|
toml=$(printf '%s' "$apk" | $HAMMER import-alpine -)
|
||||||
|
|
||||||
# sha256 automático: Alpine publica sha512, pero hammer pide sha256. Bajamos el tarball UNA vez y
|
# sha256 automático: Alpine publica sha512, pero takana pide sha256. Bajamos el tarball UNA vez y
|
||||||
# lo calculamos, reemplazando el FIXME ⇒ receta lista para `pack --build` sin tocar el hash a mano.
|
# lo calculamos, reemplazando el FIXME ⇒ receta lista para `pack --build` sin tocar el hash a mano.
|
||||||
url=$(printf '%s\n' "$toml" | sed -n 's/^tarball = "\(.*\)"$/\1/p' | head -1)
|
url=$(printf '%s\n' "$toml" | sed -n 's/^tarball = "\(.*\)"$/\1/p' | head -1)
|
||||||
if [ -n "$url" ]; then
|
if [ -n "$url" ]; then
|
||||||
|
|||||||
@@ -38,7 +38,12 @@ if desde:
|
|||||||
lineas = lineas[ini:]
|
lineas = lineas[ini:]
|
||||||
|
|
||||||
marcas = [(i, m.group(1)) for i, l in enumerate(lineas)
|
marcas = [(i, m.group(1)) for i, l in enumerate(lineas)
|
||||||
if (m := re.search(r"hammer_build: fetch hash=\S+ name=(\S+)", l))]
|
# Las DOS formas del target de tracing (ADR 0016): el target es el module_path!, o sea
|
||||||
|
# el nombre del crate, que pasó de `hammer_build` a `takana_build` en la etapa 4. Hay que
|
||||||
|
# aceptar las dos porque los logs VIEJOS que ya están en disco dicen la forma vieja — y
|
||||||
|
# porque este script no falla si no casa: atribuye cero fallos y se ve igual que un log
|
||||||
|
# sin problemas.
|
||||||
|
if (m := re.search(r"(?:hammer|takana)_build: fetch hash=\S+ name=(\S+)", l))]
|
||||||
if not marcas:
|
if not marcas:
|
||||||
print("sin marcadores `fetch` en la ventana — ¿log equivocado o --desde muy tarde?")
|
print("sin marcadores `fetch` en la ventana — ¿log equivocado o --desde muy tarde?")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# attest-boot-test.sh — valida END-TO-END el gate de atestación (I4): hammer firma el seed (arje-packager)
|
# attest-boot-test.sh — valida END-TO-END el gate de atestación (I4): takana firma el seed (arje-packager)
|
||||||
# y el arje-zero CON gate (arje-zero-attest) lo verifica al arranque. Demuestra ambos caminos:
|
# y el arje-zero CON gate (arje-zero-attest) lo verifica al arranque. Demuestra ambos caminos:
|
||||||
# - íntegro: el gate atesta los binarios críticos ✓ y arranca los servicios (SSH responde);
|
# - íntegro: el gate atesta los binarios críticos ✓ y arranca los servicios (SSH responde);
|
||||||
# - TAMPER=1: se altera 1 byte de un binario crítico DESPUÉS de firmar ⇒ el gate (política Halt)
|
# - TAMPER=1: se altera 1 byte de un binario crítico DESPUÉS de firmar ⇒ el gate (política Halt)
|
||||||
# aborta y cae a la shell de rescate (sin SSH) — la integridad comprometida NO levanta el entorno.
|
# aborta y cae a la shell de rescate (sin SSH) — la integridad comprometida NO levanta el entorno.
|
||||||
#
|
#
|
||||||
# DOS MODOS:
|
# DOS MODOS:
|
||||||
# (A) REAL (preferido) — bootea el `product-attested-rootfs` que produce `hammer bootstrap product
|
# (A) REAL (preferido) — bootea el `product-attested-rootfs` que produce `takana bootstrap product
|
||||||
# --attest` (init con gate + seed firmada ya hidratados). Es el camino de PRODUCCIÓN, no un spike.
|
# --attest` (init con gate + seed firmada ya hidratados). Es el camino de PRODUCCIÓN, no un spike.
|
||||||
# Uso: PRODUCT_ATTESTED=<hash> ./scripts/attest-boot-test.sh
|
# Uso: PRODUCT_ATTESTED=<hash> ./scripts/attest-boot-test.sh
|
||||||
# (B) SPIKE (fallback) — overlaya a mano el arje-zero con gate + firma el seed sobre una copia del
|
# (B) SPIKE (fallback) — overlaya a mano el arje-zero con gate + firma el seed sobre una copia del
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ H="$ROOT/target/release/takana"
|
|||||||
|
|
||||||
# ── EL ROOTFS VA EN EL MISMO MOUNT QUE EL STORE, Y NO ES UN CAPRICHO ───────────────────────────
|
# ── EL ROOTFS VA EN EL MISMO MOUNT QUE EL STORE, Y NO ES UN CAPRICHO ───────────────────────────
|
||||||
# `hydrate` proyecta con HARDLINKS, y `linkat()` rechaza cruzar un punto de montaje aunque los dos
|
# `hydrate` proyecta con HARDLINKS, y `linkat()` rechaza cruzar un punto de montaje aunque los dos
|
||||||
# lados sean el mismo filesystem. Acá el store es `/dev/sdb` bind-monteado en `hammer/store`
|
# lados sean el mismo filesystem. Acá el store es `/dev/sdb` bind-monteado en `takana/store`
|
||||||
# mientras `work/` vive en `/dev/sdc`: hidratar a `work/…` muere con
|
# mientras `work/` vive en `/dev/sdc`: hidratar a `work/…` muere con
|
||||||
# «Invalid cross-device link (os error 18)» — medido, no supuesto.
|
# «Invalid cross-device link (os error 18)» — medido, no supuesto.
|
||||||
# El volumen entero está montado en /mnt/cosecha, así que store y destino comparten mount ahí.
|
# El volumen entero está montado en /mnt/cosecha, así que store y destino comparten mount ahí.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# boot-builder-vm.sh — Bootea el builder rootfs (Stage 1 + toolchain) en QEMU para correr el
|
# boot-builder-vm.sh — Bootea el builder rootfs (Stage 1 + toolchain) en QEMU para correr el
|
||||||
# rebuild in-rootfs (auto-alojamiento, SDD 11 §7; runbook §8c).
|
# rebuild in-rootfs (auto-alojamiento, SDD 11 §7; runbook §8c).
|
||||||
#
|
#
|
||||||
# El builder se arma con `hammer bootstrap builder … --out work/builder-rootfs` y se empaqueta como
|
# El builder se arma con `takana bootstrap builder … --out work/builder-rootfs` y se empaqueta como
|
||||||
# initramfs (cpio newc + gzip). Aquí lo booteamos con arje-zero como PID 1: levanta hammerd + una
|
# initramfs (cpio newc + gzip). Aquí lo booteamos con arje-zero como PID 1: levanta hammerd + una
|
||||||
# getty en consola y deja una shell. Desde ahí se corre el driver embebido:
|
# getty en consola y deja una shell. Desde ahí se corre el driver embebido:
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# bootstrap-devfs.sh — Prepara .dev-fs/ con todo lo que hammer-build necesita:
|
# bootstrap-devfs.sh — Prepara .dev-fs/ con todo lo que takana-build necesita:
|
||||||
# 1. Rootfs Alpine minirootfs como base hermética del sandbox.
|
# 1. Rootfs Alpine minirootfs como base hermética del sandbox.
|
||||||
# 2. Compilador zig oficial bajo .dev-fs/tools/zig (symlink versionado).
|
# 2. Compilador zig oficial bajo .dev-fs/tools/zig (symlink versionado).
|
||||||
# 3. Build tools (make, autoconf, automake, m4, patch, coreutils, libtool,
|
# 3. Build tools (make, autoconf, automake, m4, patch, coreutils, libtool,
|
||||||
@@ -174,7 +174,7 @@ else
|
|||||||
# rust 1.91.1 ⇒ techo MSRV que bloquea recetas modernas (ouch/uv 1.93, oxlint/ruff 1.94,
|
# rust 1.91.1 ⇒ techo MSRV que bloquea recetas modernas (ouch/uv 1.93, oxlint/ruff 1.94,
|
||||||
# zellij 1.92). edge trae rust 1.96.0. Apuntamos los repos del rootfs a EDGE para que `apk add`
|
# zellij 1.92). edge trae rust 1.96.0. Apuntamos los repos del rootfs a EDGE para que `apk add`
|
||||||
# resuelva rust/cargo/clang 1.96 (+ arrastra gcc 15.2/musl 1.2.6/llvm22 como deps). El of_tree
|
# resuelva rust/cargo/clang 1.96 (+ arrastra gcc 15.2/musl 1.2.6/llvm22 como deps). El of_tree
|
||||||
# del 4/4 NO depende de esto (usa SWAP_RUST con el rust hammer-built); esto es el toolchain del
|
# del 4/4 NO depende de esto (usa SWAP_RUST con el rust takana-built); esto es el toolchain del
|
||||||
# CATÁLOGO. OJO: edge es RODANTE y no se puede pinear —sólo publica la última versión y Alpine no
|
# CATÁLOGO. OJO: edge es RODANTE y no se puede pinear —sólo publica la última versión y Alpine no
|
||||||
# da snapshots datados—, así que el paso 3a-quater registra lo resuelto en un lock y AVISA de la
|
# da snapshots datados—, así que el paso 3a-quater registra lo resuelto en un lock y AVISA de la
|
||||||
# deriva. Anclar de verdad exigiría espejar APKINDEX + los .apk, que es un frente aparte.
|
# deriva. Anclar de verdad exigiría espejar APKINDEX + los .apk, que es un frente aparte.
|
||||||
@@ -189,7 +189,7 @@ else
|
|||||||
# verificación de reproducibilidad de Stage 2: con el config determinista, los applets de
|
# verificación de reproducibilidad de Stage 2: con el config determinista, los applets de
|
||||||
# console-tools la exigen.)
|
# console-tools la exigen.)
|
||||||
# `bwrap git curl`: el rebuild *dentro* del builder rootfs (Stage 2 pleno, SDD 11 §7) corre
|
# `bwrap git curl`: el rebuild *dentro* del builder rootfs (Stage 2 pleno, SDD 11 §7) corre
|
||||||
# hammer-build con su propio toolchain. En el host estas tres las aporta el sistema, pero en la
|
# takana-build con su propio toolchain. En el host estas tres las aporta el sistema, pero en la
|
||||||
# VM el toolchain ES el único userland capaz, así que deben vivir aquí: `bwrap` anida el sandbox
|
# VM el toolchain ES el único userland capaz, así que deben vivir aquí: `bwrap` anida el sandbox
|
||||||
# de build, `git` rematerializa las fuentes git (git archive del mirror), `curl` baja tarballs.
|
# de build, `git` rematerializa las fuentes git (git archive del mirror), `curl` baja tarballs.
|
||||||
# `kmod` aporta insmod/modprobe: en la VM el sandbox de build usa overlay (módulo del kernel,
|
# `kmod` aporta insmod/modprobe: en la VM el sandbox de build usa overlay (módulo del kernel,
|
||||||
@@ -206,10 +206,10 @@ else
|
|||||||
# runtime, sigue en el base como tool autotools general.)
|
# runtime, sigue en el base como tool autotools general.)
|
||||||
# NOTA: `elfutils-dev` YA NO va aquí — de-Alpinizado a recipes/elfutils.toml (sólo libelf, con shims
|
# NOTA: `elfutils-dev` YA NO va aquí — de-Alpinizado a recipes/elfutils.toml (sólo libelf, con shims
|
||||||
# musl argp/error/libintl/fts/obstack/rawmemchr), deps.build del kernel. objtool enlaza el libelf
|
# musl argp/error/libintl/fts/obstack/rawmemchr), deps.build del kernel. objtool enlaza el libelf
|
||||||
# hammer desde la capa overlay. (El runtime libelf.so.1 de Alpine, si algún otro tool lo necesita,
|
# takana desde la capa overlay. (El runtime libelf.so.1 de Alpine, si algún otro tool lo necesita,
|
||||||
# es la misma versión 0.194 ABI-compatible.)
|
# es la misma versión 0.194 ABI-compatible.)
|
||||||
# NOTA: `openssl-dev` YA NO va aquí — de-Alpinizado a recipes/openssl.toml (libcrypto estática,
|
# NOTA: `openssl-dev` YA NO va aquí — de-Alpinizado a recipes/openssl.toml (libcrypto estática,
|
||||||
# deps.build del kernel). El host-tool certs/extract-cert lo enlaza desde la capa overlay hammer.
|
# deps.build del kernel). El host-tool certs/extract-cert lo enlaza desde la capa overlay takana.
|
||||||
# El runtime libcrypto3/libssl3 (que curl/git necesitan) lo trae Alpine aparte, no es openssl-dev.
|
# El runtime libcrypto3/libssl3 (que curl/git necesitan) lo trae Alpine aparte, no es openssl-dev.
|
||||||
# `clang-dev clang-libs`: aportan libclang.so — `bindgen` (que usan varios *-sys: libbzip3-sys,
|
# `clang-dev clang-libs`: aportan libclang.so — `bindgen` (que usan varios *-sys: libbzip3-sys,
|
||||||
# etc.) lo carga en build para generar bindings de los headers C. No lo trae el base.
|
# etc.) lo carga en build para generar bindings de los headers C. No lo trae el base.
|
||||||
@@ -344,7 +344,7 @@ fi
|
|||||||
# linkea dinámicamente como intérprete (/lib/ld-musl-x86_64.so.1) — NO el musl target del 4/4
|
# linkea dinámicamente como intérprete (/lib/ld-musl-x86_64.so.1) — NO el musl target del 4/4
|
||||||
# (recipes/musl.toml, estático, intacto). Reconstruimos musl 1.2.5 con 256 keys y reemplazamos el
|
# (recipes/musl.toml, estático, intacto). Reconstruimos musl 1.2.5 con 256 keys y reemplazamos el
|
||||||
# loader. ABI-compat (mismo musl 1.2.5): gcc/make/etc. siguen corriendo. Seguro para of_tree: el
|
# loader. ABI-compat (mismo musl 1.2.5): gcc/make/etc. siguen corriendo. Seguro para of_tree: el
|
||||||
# loader runtime de las tools no afecta los bytes que emiten; el 4/4 es estático contra hammer-musl.
|
# loader runtime de las tools no afecta los bytes que emiten; el 4/4 es estático contra takana-musl.
|
||||||
# Idempotente: si ya existe el backup .orig128, no rehace nada.
|
# Idempotente: si ya existe el backup .orig128, no rehace nada.
|
||||||
# CRÍTICO: el loader reconstruido DEBE ser de la MISMA versión de musl que el rootfs (Alpine edge
|
# CRÍTICO: el loader reconstruido DEBE ser de la MISMA versión de musl que el rootfs (Alpine edge
|
||||||
# es rodante: pasó de 1.2.5 a 1.2.6). Si difieren, los coreutils del rootfs (linkeados contra la
|
# es rodante: pasó de 1.2.5 a 1.2.6). Si difieren, los coreutils del rootfs (linkeados contra la
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ printf '%s\n' "$queue" | xargs -P"$JOBS" -I '{}' sh -c '
|
|||||||
# a la vez en sources/<dep>-<sha>/output ⇒ meson/tar chocan ("Some other Meson process is already using
|
# a la vez en sources/<dep>-<sha>/output ⇒ meson/tar chocan ("Some other Meson process is already using
|
||||||
# this build directory", "Directory not empty", "No such file"). Tras la Fase 1 la dep ya la selló el
|
# this build directory", "Directory not empty", "No such file"). Tras la Fase 1 la dep ya la selló el
|
||||||
# ganador de la carrera ⇒ reconstruir el fallo EN SERIE ahora cache-hitea la dep y compila sin colisión.
|
# ganador de la carrera ⇒ reconstruir el fallo EN SERIE ahora cache-hitea la dep y compila sin colisión.
|
||||||
# Un solo pase basta: cada `hammer build` arrastra sus deps, así que aunque el orden no sea topológico,
|
# Un solo pase basta: cada `takana build` arrastra sus deps, así que aunque el orden no sea topológico,
|
||||||
# la dep se construye/sella dentro del propio reintento. Sólo se reintenta lo que tiene FIRMA de colisión
|
# la dep se construye/sella dentro del propio reintento. Sólo se reintenta lo que tiene FIRMA de colisión
|
||||||
# (no MSRV/dep-faltante reales, que re-fallarían y sólo gastarían tiempo).
|
# (no MSRV/dep-faltante reales, que re-fallarían y sólo gastarían tiempo).
|
||||||
for s in "$FARM"/status/*.fail; do
|
for s in "$FARM"/status/*.fail; do
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# build-repo.sh — Etapa F (dogfood): puebla un REPO DE PAQUETES hammer desde el corpus
|
# build-repo.sh — Etapa F (dogfood): puebla un REPO DE PAQUETES takana desde el corpus
|
||||||
# `recipes/*.toml` y firma el release. Convierte la maquinaria de paquetería en la cadena de
|
# `recipes/*.toml` y firma el release. Convierte la maquinaria de paquetería en la cadena de
|
||||||
# suministro real de la distro: cada receta se vuelve un `.swm` (mutación sobre fuente), el repo
|
# suministro real de la distro: cada receta se vuelve un `.swm` (mutación sobre fuente), el repo
|
||||||
# es el catálogo firmado, y `hammer install <nombre> --repo <dir|url>` lo reproduce localmente.
|
# es el catálogo firmado, y `takana install <nombre> --repo <dir|url>` lo reproduce localmente.
|
||||||
#
|
#
|
||||||
# Para cada receta intenta ANCLAR el `expected_hash` con `pack --build` (instantáneo si el
|
# Para cada receta intenta ANCLAR el `expected_hash` con `pack --build` (instantáneo si el
|
||||||
# artefacto ya está sellado en el store — cache-hit; ver hammer-build::build). Si construir desde
|
# artefacto ya está sellado en el store — cache-hit; ver takana-build::build). Si construir desde
|
||||||
# cero excede el timeout (o falla), cae a `pack` sin ancla: la entrada del catálogo igual existe y
|
# cero excede el timeout (o falla), cae a `pack` sin ancla: la entrada del catálogo igual existe y
|
||||||
# el `source_patch` sigue siendo reproducible, sólo sin hash del autor contra el que comparar.
|
# el `source_patch` sigue siendo reproducible, sólo sin hash del autor contra el que comparar.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
# depende de qué) vivía disperso: en la cabeza del que construía, en docs que envejecen (el de
|
# depende de qué) vivía disperso: en la cabeza del que construía, en docs que envejecen (el de
|
||||||
# matar-gcc decía 47 y eran 16), en el store (que guarda TODOS los sellados históricos, no sólo el
|
# matar-gcc decía 47 y eran 16), en el store (que guarda TODOS los sellados históricos, no sólo el
|
||||||
# vigente). Cada medición a mano mentía distinto. Este script deriva el estado de la ÚNICA fuente de
|
# vigente). Cada medición a mano mentía distinto. Este script deriva el estado de la ÚNICA fuente de
|
||||||
# verdad —las recetas + `hammer hash` + el store— y lo escribe a `docs/state/build-state.json`.
|
# verdad —las recetas + `takana hash` + el store— y lo escribe a `docs/state/build-state.json`.
|
||||||
# Versionado: el `git diff` de ese fichero ES el avance entre dos corridas (qué se saldó, qué se
|
# Versionado: el `git diff` de ese fichero ES el avance entre dos corridas (qué se saldó, qué se
|
||||||
# rompió). La vista humana la arma `build-state-view.py` a partir del mismo JSON.
|
# rompió). La vista humana la arma `build-state-view.py` a partir del mismo JSON.
|
||||||
#
|
#
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
# sealed — el artefacto del hash VIGENTE (el de la receta de hoy) está en el store. Al día.
|
# sealed — el artefacto del hash VIGENTE (el de la receta de hoy) está en el store. Al día.
|
||||||
# debt — hay sellados históricos pero NINGUNO es el vigente ⇒ la receta cambió, falta rebuild.
|
# debt — hay sellados históricos pero NINGUNO es el vigente ⇒ la receta cambió, falta rebuild.
|
||||||
# never — no hay ningún sellado de esta receta en el store.
|
# never — no hay ningún sellado de esta receta en el store.
|
||||||
# unhashable — `hammer hash` falló (receta ilegible / dep rota). Un HUECO real del grafo.
|
# unhashable — `takana hash` falló (receta ilegible / dep rota). Un HUECO real del grafo.
|
||||||
# wanted — NO HAY RECETA: una imagen lo pide (docs/state/targets.toml) y no existe todavía.
|
# wanted — NO HAY RECETA: una imagen lo pide (docs/state/targets.toml) y no existe todavía.
|
||||||
# ARISTA = dep de build (name → dep). El grafo debe CERRAR: toda dep apunta a una receta del corpus.
|
# ARISTA = dep de build (name → dep). El grafo debe CERRAR: toda dep apunta a una receta del corpus.
|
||||||
#
|
#
|
||||||
@@ -128,7 +128,7 @@ def load_recipes():
|
|||||||
# EJECUCIÓN declarada en la receta no entraba en la clausura ni en el rootfs
|
# EJECUCIÓN declarada en la receta no entraba en la clausura ni en el rootfs
|
||||||
# hidratado: `firefox` declaraba `runtime = ["gcc-libs"]` y el grafo seguía sin
|
# hidratado: `firefox` declaraba `runtime = ["gcc-libs"]` y el grafo seguía sin
|
||||||
# conocerla, así que la imagen se armaba sin `libstdc++.so.6` y el navegador no
|
# conocerla, así que la imagen se armaba sin `libstdc++.so.6` y el navegador no
|
||||||
# arrancaba. `deps.runtime` existe en el esquema de hammer desde siempre; lo que
|
# arrancaba. `deps.runtime` existe en el esquema de takana desde siempre; lo que
|
||||||
# faltaba era que ESTE contador lo mirara. Un campo que nadie lee es un campo que
|
# faltaba era que ESTE contador lo mirara. Un campo que nadie lee es un campo que
|
||||||
# miente. La unión es la definición de clausura: para CORRER hacen falta las dos.
|
# miente. La unión es la definición de clausura: para CORRER hacen falta las dos.
|
||||||
deps=sorted(set(d.get("deps", {}).get("build", []))
|
deps=sorted(set(d.get("deps", {}).get("build", []))
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@
|
|||||||
# distinta con su propio OS. Si coinciden ⇒ CONSENSO. Si divergen ⇒ candidato a `why-differs`
|
# distinta con su propio OS. Si coinciden ⇒ CONSENSO. Si divergen ⇒ candidato a `why-differs`
|
||||||
# (SDD 17 §2) — y eso también es información: una divergencia es un canal impuro encontrado.
|
# (SDD 17 §2) — y eso también es información: una divergencia es un canal impuro encontrado.
|
||||||
#
|
#
|
||||||
# Por qué esto no lo puede ofrecer nix/debian: su repro es incompleta. hammer ya paga el
|
# Por qué esto no lo puede ofrecer nix/debian: su repro es incompleta. takana ya paga el
|
||||||
# invariante (bit-repro verificada: selfhost, kernel), así que esto cae casi solo del invariante
|
# invariante (bit-repro verificada: selfhost, kernel), así que esto cae casi solo del invariante
|
||||||
# — que es la tesis del SDD 17: buscar "qué cae del invariante", no "qué frontera agregar".
|
# — que es la tesis del SDD 17: buscar "qué cae del invariante", no "qué frontera agregar".
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ BASE="${BASE:-$ROOT/.dev-fs/alpine}"
|
|||||||
MODE="${MODE:-bare}"; OUT="${OUT:-/mnt/cosecha/escritorios}"; SECS="${SECS:-0}"
|
MODE="${MODE:-bare}"; OUT="${OUT:-/mnt/cosecha/escritorios}"; SECS="${SECS:-0}"
|
||||||
mkdir -p "$OUT"
|
mkdir -p "$OUT"
|
||||||
|
|
||||||
# GL por software. Se resuelve por HASH VIGENTE (`hammer hash`), no por el más reciente del store:
|
# GL por software. Se resuelve por HASH VIGENTE (`takana hash`), no por el más reciente del store:
|
||||||
# con dos artefactos del mismo paquete conviviendo, la fecha miente.
|
# con dos artefactos del mismo paquete conviviendo, la fecha miente.
|
||||||
if [ -z "${MESA+x}" ]; then
|
if [ -z "${MESA+x}" ]; then
|
||||||
MH=$(./target/release/takana --store ./store hash recipes/mesa-llvmpipe.toml 2>/dev/null | tr -d "\n" | sed "s/b3://")
|
MH=$(./target/release/takana --store ./store hash recipes/mesa-llvmpipe.toml 2>/dev/null | tr -d "\n" | sed "s/b3://")
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# hydrate-cosmic.sh — proyecta al FHS el cierre de runtime de COSMIC desde artefactos SELLADOS del
|
# hydrate-cosmic.sh — proyecta al FHS el cierre de runtime de COSMIC desde artefactos SELLADOS del
|
||||||
# store, sin rebuild ni reproduce (`hammer hydrate <hash> --into`).
|
# store, sin rebuild ni reproduce (`takana hydrate <hash> --into`).
|
||||||
#
|
#
|
||||||
# Es el hermano de scripts/gnome/hydrate-gnome.sh y comparte con él lo que importa: el cierre sale
|
# Es el hermano de scripts/gnome/hydrate-gnome.sh y comparte con él lo que importa: el cierre sale
|
||||||
# del GRAFO REAL de recetas (`[deps].build`, resolución hermano→padre, la misma que usa hammer) y el
|
# del GRAFO REAL de recetas (`[deps].build`, resolución hermano→padre, la misma que usa takana) y el
|
||||||
# artefacto se elige por `hammer hash` —el ArtifactHash de la receta de HOY, sin construir—, no por
|
# artefacto se elige por `takana hash` —el ArtifactHash de la receta de HOY, sin construir—, no por
|
||||||
# el más reciente del store. Con dos artefactos del mismo paquete conviviendo, la fecha miente.
|
# el más reciente del store. Con dos artefactos del mismo paquete conviviendo, la fecha miente.
|
||||||
#
|
#
|
||||||
# ── POR QUÉ LAS RAÍCES SE NOMBRAN A MANO ────────────────────────────────────────────────────────
|
# ── POR QUÉ LAS RAÍCES SE NOMBRAN A MANO ────────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -397,7 +397,7 @@ PY
|
|||||||
rm -f "$MERGED/etc/motd"
|
rm -f "$MERGED/etc/motd"
|
||||||
cat > "$MERGED/etc/motd" <<'MOTD'
|
cat > "$MERGED/etc/motd" <<'MOTD'
|
||||||
|
|
||||||
#-- hammer :: escritorio COSMIC (metal, Intel i915 + iris HW) ---------------
|
#-- takana :: escritorio COSMIC (metal, Intel i915 + iris HW) ---------------
|
||||||
GL por HARDWARE (iris). Es la diferencia con la imagen de KDE, y el motivo
|
GL por HARDWARE (iris). Es la diferencia con la imagen de KDE, y el motivo
|
||||||
de este viaje: en QEMU mesa era software y ScreenCast no podía exportar
|
de este viaje: en QEMU mesa era software y ScreenCast no podía exportar
|
||||||
dmabuf.
|
dmabuf.
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ echo " ✓ libc.so + libc.musl-x86_64.so.1"
|
|||||||
|
|
||||||
echo "==> inyectando arje-logind-compat (el login1 del fractal) + su política"
|
echo "==> inyectando arje-logind-compat (el login1 del fractal) + su política"
|
||||||
# cosmic-comp pregunta por su sesión igual que mutter y kwin. El daemon no entra por el cierre porque
|
# cosmic-comp pregunta por su sesión igual que mutter y kwin. El daemon no entra por el cierre porque
|
||||||
# nadie lo declara como dep de build. Se elige por `hammer hash` —la receta de HOY—, no por el más
|
# nadie lo declara como dep de build. Se elige por `takana hash` —la receta de HOY—, no por el más
|
||||||
# reciente del store. Su política D-Bus viaja DENTRO del artefacto desde 2026-07-30.
|
# reciente del store. Su política D-Bus viaja DENTRO del artefacto desde 2026-07-30.
|
||||||
if ALC="${ALC:-store/$(./target/release/takana --store store hash recipes/arje-logind-compat.toml 2>/dev/null | tail -1 | sed 's/^b3://')-arje-logind-compat}"; [ -d "$ALC" ]; then
|
if ALC="${ALC:-store/$(./target/release/takana --store store hash recipes/arje-logind-compat.toml 2>/dev/null | tail -1 | sed 's/^b3://')-arje-logind-compat}"; [ -d "$ALC" ]; then
|
||||||
install -Dm755 "$ALC"/usr/bin/arje-logind-compat "$MERGED"/usr/bin/arje-logind-compat
|
install -Dm755 "$ALC"/usr/bin/arje-logind-compat "$MERGED"/usr/bin/arje-logind-compat
|
||||||
@@ -158,7 +158,7 @@ chmod 1777 "$MERGED/tmp"
|
|||||||
# `<components version=… origin=…>`. Sin ese fichero la tienda abre perfecta y no lista NADA
|
# `<components version=… origin=…>`. Sin ese fichero la tienda abre perfecta y no lista NADA
|
||||||
# —«No results for …»— porque su catálogo está vacío, no porque le falte nada del sistema.
|
# —«No results for …»— porque su catálogo está vacío, no porque le falte nada del sistema.
|
||||||
#
|
#
|
||||||
# hammer no tiene appstreamcli (sería AppStream + glib, o sea la torre de C que esta campaña evita),
|
# takana no tiene appstreamcli (sería AppStream + glib, o sea la torre de C que esta campaña evita),
|
||||||
# pero el formato es XML plano y la agregación es exactamente eso: envolver los `<component>` de cada
|
# pero el formato es XML plano y la agregación es exactamente eso: envolver los `<component>` de cada
|
||||||
# metainfo en una raíz. Doce líneas de python valen la librería entera.
|
# metainfo en una raíz. Doce líneas de python valen la librería entera.
|
||||||
echo "==> catálogo AppStream para cosmic-store (agrega los metainfo del rootfs)"
|
echo "==> catálogo AppStream para cosmic-store (agrega los metainfo del rootfs)"
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
# junto (B2). Es el paso hacia la imagen instalable real: el store y el estado mutable dejan de ser meros
|
# junto (B2). Es el paso hacia la imagen instalable real: el store y el estado mutable dejan de ser meros
|
||||||
# directorios del rootfs y pasan a ser particiones propias, como en un sistema instalado de verdad.
|
# directorios del rootfs y pasan a ser particiones propias, como en un sistema instalado de verdad.
|
||||||
#
|
#
|
||||||
# /dev/vda1 → / rootfs (runtime + toolchain + /work del rebuild) [hammer-root]
|
# /dev/vda1 → / rootfs (runtime + toolchain + /work del rebuild) [takana-root]
|
||||||
# /dev/vda2 → /store artefactos CAS BLAKE3 (inmutables) [hammer-store]
|
# /dev/vda2 → /store artefactos CAS BLAKE3 (inmutables) [takana-store]
|
||||||
# /dev/vda3 → /var/lib/hammer estado mutable: journal + overlays (upper/work) [hammer-state]
|
# /dev/vda3 → /var/lib/hammer estado mutable: journal + overlays (upper/work) [takana-state]
|
||||||
#
|
#
|
||||||
# El kernel (recipes/linux.toml) trae VIRTIO_BLK+EXT4+EFI_PARTITION(=y por defconfig) ⇒ lee la GPT y
|
# El kernel (recipes/linux.toml) trae VIRTIO_BLK+EXT4+EFI_PARTITION(=y por defconfig) ⇒ lee la GPT y
|
||||||
# monta /dev/vda1 como root sin initramfs. Las otras dos particiones las monta un wrapper `/sbin/init`
|
# monta /dev/vda1 como root sin initramfs. Las otras dos particiones las monta un wrapper `/sbin/init`
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ else:
|
|||||||
net = ["-netdev", "user,id=n0", "-device", "e1000,netdev=n0"] if WANT_NET else []
|
net = ["-netdev", "user,id=n0", "-device", "e1000,netdev=n0"] if WANT_NET else []
|
||||||
|
|
||||||
# APPEND override: por defecto consola serie + initramfs. Útil para experimentar con params del kernel
|
# APPEND override: por defecto consola serie + initramfs. Útil para experimentar con params del kernel
|
||||||
# (p.ej. el frente kernel-from-source: el bzImage hammer bootea pero bwrap falla en pivot_root porque /
|
# (p.ej. el frente kernel-from-source: el bzImage takana bootea pero bwrap falla en pivot_root porque /
|
||||||
# es el rootfs absoluto del namespace; `rootfstype=tmpfs` NO lo arregla — la causa es que / no tiene
|
# es el rootfs absoluto del namespace; `rootfstype=tmpfs` NO lo arregla — la causa es que / no tiene
|
||||||
# mount padre, no el tipo de fs). Override con APPEND="…".
|
# mount padre, no el tipo de fs). Override con APPEND="…".
|
||||||
# Boot de disco (Etapa B3) vs initramfs. En disco / ya es un mount ext4 real ⇒ rdinit=/sbin/init directo,
|
# Boot de disco (Etapa B3) vs initramfs. En disco / ya es un mount ext4 real ⇒ rdinit=/sbin/init directo,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# efi-boot-test.sh — valida la rama UEFI del medio live (refinamiento #3): arma un ISO con
|
# efi-boot-test.sh — valida la rama UEFI del medio live (refinamiento #3): arma un ISO con
|
||||||
# iso-image.sh EFI=1 y lo arranca por las DOS firmwares, probando que es un HÍBRIDO BIOS+UEFI:
|
# iso-image.sh EFI=1 y lo arranca por las DOS firmwares, probando que es un HÍBRIDO BIOS+UEFI:
|
||||||
# (A) UEFI — QEMU con OVMF (pflash) → grubx64.efi (de la ESP FAT poblada con mtools de hammer) →
|
# (A) UEFI — QEMU con OVMF (pflash) → grubx64.efi (de la ESP FAT poblada con mtools de takana) →
|
||||||
# kernel EFI-stub + initrd vía EFI → producto + sshd.
|
# kernel EFI-stub + initrd vía EFI → producto + sshd.
|
||||||
# (B) BIOS — el MISMO ISO con SeaBIOS (El Torito i386-pc) → producto + sshd.
|
# (B) BIOS — el MISMO ISO con SeaBIOS (El Torito i386-pc) → producto + sshd.
|
||||||
# La ESP FAT la puebla el mtools construido por hammer (recipes/mtools.toml); el grubx64.efi lo arma
|
# La ESP FAT la puebla el mtools construido por takana (recipes/mtools.toml); el grubx64.efi lo arma
|
||||||
# grub-mkimage -O x86_64-efi. El kernel ya trae EFI_STUB (sin rebuild).
|
# grub-mkimage -O x86_64-efi. El kernel ya trae EFI_STUB (sin rebuild).
|
||||||
#
|
#
|
||||||
# Uso: PRODUCT=<hash-o-prefijo> ./scripts/efi-boot-test.sh
|
# Uso: PRODUCT=<hash-o-prefijo> ./scripts/efi-boot-test.sh
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
# Arma la imagen con install-image-efi.sh y la arranca por UEFI (OVMF pflash, SIN -kernel: la firmware
|
# Arma la imagen con install-image-efi.sh y la arranca por UEFI (OVMF pflash, SIN -kernel: la firmware
|
||||||
# lanza \EFI\BOOT\BOOTX64.EFI). Asevera la cadena soberana completa por marcadores serie deterministas:
|
# lanza \EFI\BOOT\BOOTX64.EFI). Asevera la cadena soberana completa por marcadores serie deterministas:
|
||||||
# 1. EFI-stub cargó el kernel+initrd horneados (sin GRUB ni systemd-boot)
|
# 1. EFI-stub cargó el kernel+initrd horneados (sin GRUB ni systemd-boot)
|
||||||
# 2. el initramfs de pivote resolvió hammer-root por LABEL y montó las ext4
|
# 2. el initramfs de pivote resolvió takana-root por LABEL y montó las ext4
|
||||||
# 3. switch_root: arje-zero re-montó / (re-mounted) = tomó PID1
|
# 3. switch_root: arje-zero re-montó / (re-mounted) = tomó PID1
|
||||||
#
|
#
|
||||||
# Nota: el cmdline horneado termina en console=tty0 ⇒ el stdout de userspace va a la pantalla. Los
|
# Nota: el cmdline horneado termina en console=tty0 ⇒ el stdout de userspace va a la pantalla. Los
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
# efi-install-test.sh — valida el lazo COMPLETO de instalación EFI desde el medio live en OVMF (ADR 0010
|
# efi-install-test.sh — valida el lazo COMPLETO de instalación EFI desde el medio live en OVMF (ADR 0010
|
||||||
# paso 5, hermano UEFI de scripts/iso-install-test.sh que es BIOS):
|
# paso 5, hermano UEFI de scripts/iso-install-test.sh que es BIOS):
|
||||||
# (1) arma un ISO instalador EFI (iso-image.sh EFI=1 INSTALLER=1 AUTO_INSTALL=/dev/vda) — GRUB-EFI carga
|
# (1) arma un ISO instalador EFI (iso-image.sh EFI=1 INSTALLER=1 AUTO_INSTALL=/dev/vda) — GRUB-EFI carga
|
||||||
# el live, cuyo /init desatendido corre hammer-install; el payload trae el kernel metal EFI-stub;
|
# el live, cuyo /init desatendido corre takana-install; el payload trae el kernel metal EFI-stub;
|
||||||
# (2) lo bootea EN OVMF con un disco EN BLANCO ⇒ el live corre bajo UEFI ⇒ hammer-install detecta
|
# (2) lo bootea EN OVMF con un disco EN BLANCO ⇒ el live corre bajo UEFI ⇒ takana-install detecta
|
||||||
# /sys/firmware/efi y toma la RAMA EFI (MBR+ESP-0xEF, EFI-stub soberano), instala y apaga;
|
# /sys/firmware/efi y toma la RAMA EFI (MBR+ESP-0xEF, EFI-stub soberano), instala y apaga;
|
||||||
# (3) bootea ESE disco SOLO en OVMF (sin ISO, sin -kernel) ⇒ la firmware lanza \EFI\BOOT\BOOTX64.EFI →
|
# (3) bootea ESE disco SOLO en OVMF (sin ISO, sin -kernel) ⇒ la firmware lanza \EFI\BOOT\BOOTX64.EFI →
|
||||||
# initramfs de pivote → arje-zero. Cierra "ISO live UEFI → disco EFI instalado → bootea solo".
|
# initramfs de pivote → arje-zero. Cierra "ISO live UEFI → disco EFI instalado → bootea solo".
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# build-timed.sh <receta.toml> — corre `hammer build` MIDIENDO la duración de pared y la registra
|
# build-timed.sh <receta.toml> — corre `takana build` MIDIENDO la duración de pared y la registra
|
||||||
# como metadata, para alimentar el camino crítico PESADO de yupana (el peso que le faltaba a las
|
# como metadata, para alimentar el camino crítico PESADO de yupana (el peso que le faltaba a las
|
||||||
# ondas: sin él, critical-path = nº de pasos; con él, ETA real en segundos).
|
# ondas: sin él, critical-path = nº de pasos; con él, ETA real en segundos).
|
||||||
#
|
#
|
||||||
@@ -12,12 +12,12 @@
|
|||||||
#
|
#
|
||||||
# SÓLO BUILDS REALES. Un cache-hit devuelve al instante; un build C/KDE tarda minutos. Se registra
|
# SÓLO BUILDS REALES. Un cache-hit devuelve al instante; un build C/KDE tarda minutos. Se registra
|
||||||
# sólo si la pared supera UMBRAL_TIEMPO (def 3s), así los cache-hits no envenenan la mediana con ~0.
|
# sólo si la pared supera UMBRAL_TIEMPO (def 3s), así los cache-hits no envenenan la mediana con ~0.
|
||||||
# Limitación honesta: `hammer build` arrastra deps ⇒ la pared incluye deps NO selladas. Construyendo
|
# Limitación honesta: `takana build` arrastra deps ⇒ la pared incluye deps NO selladas. Construyendo
|
||||||
# en orden topológico (drenar) las deps ya están selladas (cache-hit) y la pared mide sobre todo ESTA
|
# en orden topológico (drenar) las deps ya están selladas (cache-hit) y la pared mide sobre todo ESTA
|
||||||
# receta. No es perfecto; es una cota superior buena para pesar. La precisión exacta pediría instrumentar
|
# receta. No es perfecto; es una cota superior buena para pesar. La precisión exacta pediría instrumentar
|
||||||
# el sellado dentro de hammer-build (Rust), deuda futura.
|
# el sellado dentro de takana-build (Rust), deuda futura.
|
||||||
#
|
#
|
||||||
# Sale con el MISMO código que `hammer build` (transparente para el llamador).
|
# Sale con el MISMO código que `takana build` (transparente para el llamador).
|
||||||
set -u
|
set -u
|
||||||
HAMMER="${TAKANA:-${HAMMER:-./target/release/takana}}"
|
HAMMER="${TAKANA:-${HAMMER:-./target/release/takana}}"
|
||||||
STORE="${STORE:-./store}"
|
STORE="${STORE:-./store}"
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
# campana-deuda.sh — muele en el WORKER una lista EXPLÍCITA de recetas en deuda, medida en el HUB.
|
# campana-deuda.sh — muele en el WORKER una lista EXPLÍCITA de recetas en deuda, medida en el HUB.
|
||||||
#
|
#
|
||||||
# POR QUÉ NO `saldar-deuda-static.sh` DIRECTO EN EL WORKER (2026-07-21): ese script calcula la deuda
|
# POR QUÉ NO `saldar-deuda-static.sh` DIRECTO EN EL WORKER (2026-07-21): ese script calcula la deuda
|
||||||
# en vivo con `hammer hash --check` contra el store LOCAL. En el worker el store es PARCIAL (el del
|
# en vivo con `takana hash --check` contra el store LOCAL. En el worker el store es PARCIAL (el del
|
||||||
# volumen: ~290 artefactos vs 720 del hub) ⇒ mide 716 recetas de deuda en vez de 37 y se pone a
|
# volumen: ~290 artefactos vs 720 del hub) ⇒ mide 716 recetas de deuda en vez de 37 y se pone a
|
||||||
# reconstruir media distro. Es la regla de [[frente-harkaq-jaula]] con otra cara: **el worker MIDE,
|
# reconstruir media distro. Es la regla de [[frente-harkaq-jaula]] con otra cara: **el worker MIDE,
|
||||||
# el hub CLASIFICA**. Acá el hub decide la lista (`DRY=1 saldar-deuda-static.sh`) y el worker sólo
|
# el hub CLASIFICA**. Acá el hub decide la lista (`DRY=1 saldar-deuda-static.sh`) y el worker sólo
|
||||||
# ejecuta. La lista se pasa por argumentos o por DEUDA=, no se recalcula.
|
# ejecuta. La lista se pasa por argumentos o por DEUDA=, no se recalcula.
|
||||||
#
|
#
|
||||||
# ORDEN: las RAÍCES del stack GUI primero (glib unblocks=14, luego harfbuzz/cairo/pango → gtk4 →
|
# ORDEN: las RAÍCES del stack GUI primero (glib unblocks=14, luego harfbuzz/cairo/pango → gtk4 →
|
||||||
# libadwaita). `hammer build` arrastra deps recursivamente, así que el orden no es obligatorio —
|
# libadwaita). `takana build` arrastra deps recursivamente, así que el orden no es obligatorio —
|
||||||
# pero empezar por la raíz hace que la cascada caiga cuanto antes y que un corte temprano deje el
|
# pero empezar por la raíz hace que la cascada caiga cuanto antes y que un corte temprano deje el
|
||||||
# máximo destrabado. El stack GUI es lo que el laptop NO puede construir (zig-skew, ver
|
# máximo destrabado. El stack GUI es lo que el laptop NO puede construir (zig-skew, ver
|
||||||
# [[etapa-g-gui-chain-boundary]]) ⇒ es exactamente lo que justifica la granja.
|
# [[etapa-g-gui-chain-boundary]]) ⇒ es exactamente lo que justifica la granja.
|
||||||
@@ -133,11 +133,11 @@ for r in $DEUDA; do
|
|||||||
echo "$(ts) sin intentar: $(echo "$DEUDA" | tr ' ' '\n' | tail -n +"$i" | tr '\n' ' ')" | tee -a "$LOG"
|
echo "$(ts) sin intentar: $(echo "$DEUDA" | tr ' ' '\n' | tail -n +"$i" | tr '\n' ' ')" | tee -a "$LOG"
|
||||||
exit 3
|
exit 3
|
||||||
fi
|
fi
|
||||||
# heartbeat: el dead-man ya cuenta `hammer build` como trabajo, pero entre receta y receta hay
|
# heartbeat: el dead-man ya cuenta `takana build` como trabajo, pero entre receta y receta hay
|
||||||
# huecos (fetch/vendor) donde no hay proceso con ese nombre. Tocarlo evita una muerte espuria.
|
# huecos (fetch/vendor) donde no hay proceso con ese nombre. Tocarlo evita una muerte espuria.
|
||||||
touch /run/hammer-heartbeat 2>/dev/null || true
|
touch /run/hammer-heartbeat 2>/dev/null || true
|
||||||
# build-timed.sh mide la pared y registra la duración en $STORE/.times (sólo builds reales), para
|
# build-timed.sh mide la pared y registra la duración en $STORE/.times (sólo builds reales), para
|
||||||
# el camino crítico pesado de yupana. Transparente: sale con el mismo código que `hammer build`.
|
# el camino crítico pesado de yupana. Transparente: sale con el mismo código que `takana build`.
|
||||||
if HAMMER="$HAMMER" STORE="$STORE" "$HAMMER_DIR/scripts/farm/build-timed.sh" "$f" >>"$LOG" 2>&1; then
|
if HAMMER="$HAMMER" STORE="$STORE" "$HAMMER_DIR/scripts/farm/build-timed.sh" "$f" >>"$LOG" 2>&1; then
|
||||||
ultimo_rc=0; ok=$((ok + 1)); echo "$(ts) [$i/$total] ✓ $r" | tee -a "$LOG"
|
ultimo_rc=0; ok=$((ok + 1)); echo "$(ts) [$i/$total] ✓ $r" | tee -a "$LOG"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ else
|
|||||||
# b) Un PNG NUEVO de una receta tampoco viaja. Y hay recetas cuyo `[source] dir` tiene PNG
|
# b) Un PNG NUEVO de una receta tampoco viaja. Y hay recetas cuyo `[source] dir` tiene PNG
|
||||||
# dentro: los 9 iconos de `recipes/atuq/branding/icons/`.
|
# dentro: los 9 iconos de `recipes/atuq/branding/icons/`.
|
||||||
#
|
#
|
||||||
# Como hammer SÍ hashea el árbol de un `[source] dir` (`recipe.rs`, `dir:<hash>`), el efecto no es
|
# Como takana SÍ hashea el árbol de un `[source] dir` (`recipe.rs`, `dir:<hash>`), el efecto no es
|
||||||
# silencioso —bendito sea—: el worker calcula OTRO ArtifactHash. Medido el mismo día,
|
# silencioso —bendito sea—: el worker calcula OTRO ArtifactHash. Medido el mismo día,
|
||||||
# `atuq` daba `b3:f2960991` en el hub y `b3:b33e81a5` en el worker por ESE único fichero de más.
|
# `atuq` daba `b3:f2960991` en el hub y `b3:b33e81a5` en el worker por ESE único fichero de más.
|
||||||
# O sea que el worker no podía coincidir con el hub ni construyendo bien.
|
# O sea que el worker no podía coincidir con el hub ni construyendo bien.
|
||||||
@@ -162,7 +162,7 @@ fi
|
|||||||
# tiene un token que funciona, y este latido corre cada 30 min aunque no haya sesión (setsid) ⇒ el
|
# tiene un token que funciona, y este latido corre cada 30 min aunque no haya sesión (setsid) ⇒ el
|
||||||
# hub es la AUTORIDAD de vida del worker. Es defensa en profundidad: el dead-man del worker cubre
|
# hub es la AUTORIDAD de vida del worker. Es defensa en profundidad: el dead-man del worker cubre
|
||||||
# "hub caído"; esto cubre "dead-man del worker roto". Un worker sin trabajo activo REAPER_MAX ciclos
|
# "hub caído"; esto cubre "dead-man del worker roto". Un worker sin trabajo activo REAPER_MAX ciclos
|
||||||
# seguidos se BORRA desde acá, con el MISMO blindaje que el dead-man (label role=hammer-worker;
|
# seguidos se BORRA desde acá, con el MISMO blindaje que el dead-man (label role=takana-worker;
|
||||||
# gioser no tiene label ⇒ jamás pasa, ni por accidente).
|
# gioser no tiene label ⇒ jamás pasa, ni por accidente).
|
||||||
REAPER_MAX="${REAPER_MAX:-2}" # 2 ciclos × 30 min ≈ 1 h idle, igual que el dead-man del worker
|
REAPER_MAX="${REAPER_MAX:-2}" # 2 ciclos × 30 min ≈ 1 h idle, igual que el dead-man del worker
|
||||||
if [ -s "$FLEET" ] && command -v hcloud >/dev/null 2>&1; then
|
if [ -s "$FLEET" ] && command -v hcloud >/dev/null 2>&1; then
|
||||||
@@ -205,7 +205,7 @@ if [ -s "$FLEET" ] && command -v hcloud >/dev/null 2>&1; then
|
|||||||
echo "==> reaper: $name SIN trabajo activo — strike $strikes/$REAPER_MAX"
|
echo "==> reaper: $name SIN trabajo activo — strike $strikes/$REAPER_MAX"
|
||||||
if [ "$strikes" -lt "$REAPER_MAX" ]; then sobreviven="${sobreviven}${name} ${ip}
|
if [ "$strikes" -lt "$REAPER_MAX" ]; then sobreviven="${sobreviven}${name} ${ip}
|
||||||
"; continue; fi
|
"; continue; fi
|
||||||
# BLINDAJE (igual que el dead-man): sólo se borra un server con label role=hammer-worker.
|
# BLINDAJE (igual que el dead-man): sólo se borra un server con label role=takana-worker.
|
||||||
if hcloud server describe "$name" -o format='{{.Labels}}' 2>/dev/null | grep -q hammer-worker; then
|
if hcloud server describe "$name" -o format='{{.Labels}}' 2>/dev/null | grep -q hammer-worker; then
|
||||||
echo " ☠ IDLE $strikes ciclos ⇒ el HUB borra $name (label verificado; gioser protegido)"
|
echo " ☠ IDLE $strikes ciclos ⇒ el HUB borra $name (label verificado; gioser protegido)"
|
||||||
if hcloud server delete "$name" >/dev/null 2>&1; then rm -f "$strike_f"
|
if hcloud server delete "$name" >/dev/null 2>&1; then rm -f "$strike_f"
|
||||||
@@ -244,7 +244,7 @@ if [ -x "$ROOT/scripts/poda-fuentes.sh" ]; then
|
|||||||
"$ROOT/scripts/poda-fuentes.sh" --aplicar || echo " ⚠ poda de fuentes falló (rc=$?) — sigo"
|
"$ROOT/scripts/poda-fuentes.sh" --aplicar || echo " ⚠ poda de fuentes falló (rc=$?) — sigo"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 3. Regenerar el grafo de estado desde el store ya cosechado (usa el hammer del laptop, que tiene
|
# 3. Regenerar el grafo de estado desde el store ya cosechado (usa el takana del laptop, que tiene
|
||||||
# el subcomando `hash`). Barato (~14s cada uno). El corpus canónico y el frente KDE, por separado.
|
# el subcomando `hash`). Barato (~14s cada uno). El corpus canónico y el frente KDE, por separado.
|
||||||
echo "==> regenerando grafo de estado"
|
echo "==> regenerando grafo de estado"
|
||||||
if [ -x "$HAMMER" ]; then
|
if [ -x "$HAMMER" ]; then
|
||||||
@@ -289,7 +289,7 @@ if [ -x "$HAMMER" ]; then
|
|||||||
echo "$drenaje_out" | grep '⚠' | sed 's/^/ /'
|
echo "$drenaje_out" | grep '⚠' | sed 's/^/ /'
|
||||||
fi
|
fi
|
||||||
# VIGÍA DE FUENTES (ADR 0013 §3). Desde que el mirror propio se consulta ANTES que upstream,
|
# VIGÍA DE FUENTES (ADR 0013 §3). Desde que el mirror propio se consulta ANTES que upstream,
|
||||||
# `hammer build` deja de avisar cuando una URL de terceros muere: sirve los bytes del mirror y
|
# `takana build` deja de avisar cuando una URL de terceros muere: sirve los bytes del mirror y
|
||||||
# sigue. Eso es lo correcto para construir y sería CIEGO sin este contrapeso — las URLs se irían
|
# sigue. Eso es lo correcto para construir y sería CIEGO sin este contrapeso — las URLs se irían
|
||||||
# muriendo una a una y el corpus resultaría irreconstruible el día que falte el mirror, con todo
|
# muriendo una a una y el corpus resultaría irreconstruible el día que falte el mirror, con todo
|
||||||
# en verde hasta ese momento. Igual que el grafo de wlr, que pasó 17 días anunciando un 121/121
|
# en verde hasta ese momento. Igual que el grafo de wlr, que pasó 17 días anunciando un 121/121
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
# Antes de morir sólo queda una cosa honesta: sync(1) + umount, para que el ext4 del volumen quede
|
# Antes de morir sólo queda una cosa honesta: sync(1) + umount, para que el ext4 del volumen quede
|
||||||
# consistente. No es "guardar" (ya está guardado), es cerrar la puerta al salir.
|
# consistente. No es "guardar" (ya está guardado), es cerrar la puerta al salir.
|
||||||
#
|
#
|
||||||
# QUÉ CUENTA COMO TRABAJO: un `hammer build` en vuelo, el loop del worker, o un heartbeat fresco
|
# QUÉ CUENTA COMO TRABAJO: un `takana build` en vuelo, el loop del worker, o un heartbeat fresco
|
||||||
# (`/run/hammer-heartbeat`, que un job largo puede tocar). Si nada de eso aparece durante
|
# (`/run/hammer-heartbeat`, que un job largo puede tocar). Si nada de eso aparece durante
|
||||||
# IDLE_MAX_TICKS ticks seguidos, se borra.
|
# IDLE_MAX_TICKS ticks seguidos, se borra.
|
||||||
#
|
#
|
||||||
@@ -101,15 +101,15 @@ if [ "${1:-}" = "--verificar" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
hay_trabajo() {
|
hay_trabajo() {
|
||||||
# `hammer build` cubre TODO el build (fetch/vendor/compile) porque el proceso vive toda la
|
# `takana build` cubre TODO el build (fetch/vendor/compile) porque el proceso vive toda la
|
||||||
# invocación. `campana-deuda` = campaña deliberada. NO se cuenta `farm-worker-loop`: ese loop
|
# invocación. `campana-deuda` = campaña deliberada. NO se cuenta `farm-worker-loop`: ese loop
|
||||||
# está SIEMPRE vivo (idle-loopea con la cola vacía) ⇒ contarlo como trabajo hacía que el worker
|
# está SIEMPRE vivo (idle-loopea con la cola vacía) ⇒ contarlo como trabajo hacía que el worker
|
||||||
# NUNCA acumulara ticks y NUNCA se matara — un worker con cola seca quedaba idle para siempre
|
# NUNCA acumulara ticks y NUNCA se matara — un worker con cola seca quedaba idle para siempre
|
||||||
# (incidente 2026-07-23, 2ª vez). El loop construyendo YA se ve por su `hammer build` hijo.
|
# (incidente 2026-07-23, 2ª vez). El loop construyendo YA se ve por su `takana build` hijo.
|
||||||
pgrep -f 'release/hammer.* build ' >/dev/null 2>&1 && { echo "hammer build en vuelo"; return 0; }
|
pgrep -f 'release/hammer.* build ' >/dev/null 2>&1 && { echo "hammer build en vuelo"; return 0; }
|
||||||
pgrep -f 'campana-deuda' >/dev/null 2>&1 && { echo "campaña deliberada en vuelo"; return 0; }
|
pgrep -f 'campana-deuda' >/dev/null 2>&1 && { echo "campaña deliberada en vuelo"; return 0; }
|
||||||
# UNA TRANSFERENCIA TAMBIÉN ES TRABAJO (2026-08-09). Poblar el volumen con el store del hub son
|
# UNA TRANSFERENCIA TAMBIÉN ES TRABAJO (2026-08-09). Poblar el volumen con el store del hub son
|
||||||
# horas de rsync durante las cuales no corre ningún `hammer build` ⇒ el worker acumulaba ticks y
|
# horas de rsync durante las cuales no corre ningún `takana build` ⇒ el worker acumulaba ticks y
|
||||||
# se borraba A SÍ MISMO a mitad de la copia. El volumen sobrevive, pero la transferencia muere y
|
# se borraba A SÍ MISMO a mitad de la copia. El volumen sobrevive, pero la transferencia muere y
|
||||||
# hay que reanudarla a mano; con un enlace lento eso puede no converger nunca.
|
# hay que reanudarla a mano; con un enlace lento eso puede no converger nunca.
|
||||||
# `pgrep -x` (nombre EXACTO del proceso), no `pgrep -f`: `-f` mira la línea de órdenes completa y
|
# `pgrep -x` (nombre EXACTO del proceso), no `pgrep -f`: `-f` mira la línea de órdenes completa y
|
||||||
@@ -145,7 +145,7 @@ self="$(hostname)"
|
|||||||
# una sola no basta cuando el fallo es irreversible:
|
# una sola no basta cuando el fallo es irreversible:
|
||||||
#
|
#
|
||||||
# 1. LISTA NEGRA por nombre — explícita, legible, imposible de malinterpretar.
|
# 1. LISTA NEGRA por nombre — explícita, legible, imposible de malinterpretar.
|
||||||
# 2. LABEL role=hammer-worker — el switch sólo se borra si ÉL MISMO es un worker de la granja.
|
# 2. LABEL role=takana-worker — el switch sólo se borra si ÉL MISMO es un worker de la granja.
|
||||||
# gioser no tiene labels (map[]), así que jamás pasa este filtro ni por accidente.
|
# gioser no tiene labels (map[]), así que jamás pasa este filtro ni por accidente.
|
||||||
#
|
#
|
||||||
# La capa 2 es la fuerte: no depende de acordarse de añadir nombres a una lista. Un server que no
|
# La capa 2 es la fuerte: no depende de acordarse de añadir nombres a una lista. Un server que no
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
# llave del box y se mantiene el invariante del modelo hub-and-spoke: compute puro y descartable.
|
# llave del box y se mantiene el invariante del modelo hub-and-spoke: compute puro y descartable.
|
||||||
#
|
#
|
||||||
# ── EVIDENCIA, NO FE ────────────────────────────────────────────────────────────────────────────
|
# ── EVIDENCIA, NO FE ────────────────────────────────────────────────────────────────────────────
|
||||||
# El paso final NO es "extraje la imagen": es comparar el `hammer hash` de una receta testigo entre
|
# El paso final NO es "extraje la imagen": es comparar el `takana hash` de una receta testigo entre
|
||||||
# worker y hub. Si no coinciden, este script FALLA y el worker no debe construir — un worker que
|
# worker y hub. Si no coinciden, este script FALLA y el worker no debe construir — un worker que
|
||||||
# sella en otra dirección quema dinero produciendo artefactos que nadie va a encontrar.
|
# sella en otra dirección quema dinero produciendo artefactos que nadie va a encontrar.
|
||||||
#
|
#
|
||||||
@@ -53,7 +53,7 @@ $SSH "root@$IP" "set -e
|
|||||||
log "3/4 recompilando hammer en el worker (el binario debe traer el lab en hash_inputs)"
|
log "3/4 recompilando hammer en el worker (el binario debe traer el lab en hash_inputs)"
|
||||||
# `touch` ANTES de compilar, y no es paranoia: `rsync -a` PRESERVA EL MTIME DEL HUB, así que un
|
# `touch` ANTES de compilar, y no es paranoia: `rsync -a` PRESERVA EL MTIME DEL HUB, así que un
|
||||||
# fuente recién sincronizado puede quedar más VIEJO que el binario que el worker compiló hace un
|
# fuente recién sincronizado puede quedar más VIEJO que el binario que el worker compiló hace un
|
||||||
# rato ⇒ cargo dice «Finished in 0.09s» y no recompila nada. El worker se queda con el hammer
|
# rato ⇒ cargo dice «Finished in 0.09s» y no recompila nada. El worker se queda con el takana
|
||||||
# anterior, calcula la huella vieja y el paso 4 falla sin que se vea por qué (2026-08-12).
|
# anterior, calcula la huella vieja y el paso 4 falla sin que se vea por qué (2026-08-12).
|
||||||
$SSH "root@$IP" "cd $REMOTE && . \$HOME/.cargo/env 2>/dev/null
|
$SSH "root@$IP" "cd $REMOTE && . \$HOME/.cargo/env 2>/dev/null
|
||||||
find crates -name '*.rs' -exec touch {} +
|
find crates -name '*.rs' -exec touch {} +
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ LEDGER="work/store-gc-superados.txt"
|
|||||||
# CAS y `.dmerge` hardlinkea los artefactos: en el worker, 25 G medidos con `du` —que deduplica
|
# CAS y `.dmerge` hardlinkea los artefactos: en el worker, 25 G medidos con `du` —que deduplica
|
||||||
# por inodo— son MUCHOS más en el cable, porque cada enlace se transfiere y se escribe como una
|
# por inodo— son MUCHOS más en el cable, porque cada enlace se transfiere y se escribe como una
|
||||||
# copia entera. El tamaño que informa `du` del origen NO es el que hace falta en el destino.
|
# copia entera. El tamaño que informa `du` del origen NO es el que hace falta en el destino.
|
||||||
# 2. **`.dmerge` es CACHÉ PURA y no tiene por qué viajar.** Es la capa de merge que hammer
|
# 2. **`.dmerge` es CACHÉ PURA y no tiene por qué viajar.** Es la capa de merge que takana
|
||||||
# reconstruye sola; copiarla no aporta un solo artefacto y es la parte más pesada del árbol
|
# reconstruye sola; copiarla no aporta un solo artefacto y es la parte más pesada del árbol
|
||||||
# (en el hub llegó a 132 G con 111,7 GiB exclusivos). Cosechar es traerse ARTEFACTOS.
|
# (en el hub llegó a 132 G con 111,7 GiB exclusivos). Cosechar es traerse ARTEFACTOS.
|
||||||
#
|
#
|
||||||
@@ -100,7 +100,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# ── GUARDIÁN: ningún artefacto cosechado puede llegar VACÍO ────────────────────────────────────
|
# ── GUARDIÁN: ningún artefacto cosechado puede llegar VACÍO ────────────────────────────────────
|
||||||
# Un directorio sin ficheros no es un artefacto, es un nombre — y `hammer build` lo lee como
|
# Un directorio sin ficheros no es un artefacto, es un nombre — y `takana build` lo lee como
|
||||||
# presencia y sella sin construir. Barrerlos acá es barato; detectarlos tres eslabones más abajo
|
# presencia y sella sin construir. Barrerlos acá es barato; detectarlos tres eslabones más abajo
|
||||||
# (manifiesto → grafo → build) cuesta una campaña.
|
# (manifiesto → grafo → build) cuesta una campaña.
|
||||||
VACIOS=0
|
VACIOS=0
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# farm-up.sh [N] — levanta N workers EFÍMEROS desde el snapshot golden y los alinea con la cola
|
# farm-up.sh [N] — levanta N workers EFÍMEROS desde el snapshot golden y los alinea con la cola
|
||||||
# actual del laptop. Modelo hub-and-spoke: el worker NO tiene secretos (ni firma ni gitea); es
|
# actual del laptop. Modelo hub-and-spoke: el worker NO tiene secretos (ni firma ni gitea); es
|
||||||
# compute puro y descartable. La imagen 'hammer-golden' trae el toolchain + el store sellado
|
# compute puro y descartable. La imagen 'takana-golden' trae el toolchain + el store sellado
|
||||||
# horneados ⇒ el worker arranca con TODO el catálogo cacheado (cache-hit instantáneo), sólo
|
# horneados ⇒ el worker arranca con TODO el catálogo cacheado (cache-hit instantáneo), sólo
|
||||||
# construye lo NUEVO que el hub le empuje.
|
# construye lo NUEVO que el hub le empuje.
|
||||||
#
|
#
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
# La flota viva se registra en scripts/farm/.fleet ("<name> <ip>" por línea; gitignored).
|
# La flota viva se registra en scripts/farm/.fleet ("<name> <ip>" por línea; gitignored).
|
||||||
# Idempotente al escalar: re-correr con más N agrega workers sin pisar los vivos.
|
# Idempotente al escalar: re-correr con más N agrega workers sin pisar los vivos.
|
||||||
#
|
#
|
||||||
# Env: IMAGE (snapshot, def 417847948=hammer-golden-rust-go-2026-08-08), TYPE (def ccx23),
|
# Env: IMAGE (snapshot, def 417847948=takana-golden-rust-go-2026-08-08), TYPE (def ccx23),
|
||||||
# LOCATION
|
# LOCATION
|
||||||
# (def hel1), SSHKEY (llave del proyecto Hetzner, def desarrollo@jlsoltech.com), SSH_KEY
|
# (def hel1), SSHKEY (llave del proyecto Hetzner, def desarrollo@jlsoltech.com), SSH_KEY
|
||||||
# (privada local p/ SSH, def ~/.ssh/github5), REMOTE (def /opt/hammer).
|
# (privada local p/ SSH, def ~/.ssh/github5), REMOTE (def /opt/hammer).
|
||||||
@@ -20,7 +20,7 @@ set -euo pipefail
|
|||||||
|
|
||||||
N="${1:-1}"
|
N="${1:-1}"
|
||||||
# ── GOLDEN 417847948 (2026-08-08): la anterior NO TENÍA RUST NI GO ─────────────────────────────
|
# ── GOLDEN 417847948 (2026-08-08): la anterior NO TENÍA RUST NI GO ─────────────────────────────
|
||||||
# `hammer` invoca `cargo vendor` (y el toolchain Go) en el HOST, no dentro del sandbox: el vendoreo
|
# `takana` invoca `cargo vendor` (y el toolchain Go) en el HOST, no dentro del sandbox: el vendoreo
|
||||||
# pasa ANTES de entrar a la caja. La golden vieja (408909310) no los traía, así que la granja no
|
# pasa ANTES de entrar a la caja. La golden vieja (408909310) no los traía, así que la granja no
|
||||||
# podía construir NINGUNA receta Rust ni Go — o sea COSMIC entero, las 228 Rust y las 362 Go del
|
# podía construir NINGUNA receta Rust ni Go — o sea COSMIC entero, las 228 Rust y las 362 Go del
|
||||||
# corpus: **el 76% del catálogo sólo se podía construir en el hub**, una sola máquina.
|
# corpus: **el 76% del catálogo sólo se podía construir en el hub**, una sola máquina.
|
||||||
@@ -84,7 +84,7 @@ sin_volumen() {
|
|||||||
fi
|
fi
|
||||||
# El server acaba de nacer y todavía no tiene nada dentro. Dejarlo vivo sería un idle facturando
|
# El server acaba de nacer y todavía no tiene nada dentro. Dejarlo vivo sería un idle facturando
|
||||||
# (es el caso hworker-4, 5 días), así que se borra — con el MISMO blindaje que el dead-man y
|
# (es el caso hworker-4, 5 días), así que se borra — con el MISMO blindaje que el dead-man y
|
||||||
# farm-down: sólo si lleva el label role=hammer-worker. gioser no lo lleva ⇒ jamás cae por acá.
|
# farm-down: sólo si lleva el label role=takana-worker. gioser no lo lleva ⇒ jamás cae por acá.
|
||||||
if hcloud server describe "$name" -o format='{{.Labels}}' 2>/dev/null | grep -q hammer-worker; then
|
if hcloud server describe "$name" -o format='{{.Labels}}' 2>/dev/null | grep -q hammer-worker; then
|
||||||
if hcloud server delete "$name" >/dev/null 2>&1; then
|
if hcloud server delete "$name" >/dev/null 2>&1; then
|
||||||
echo " $name borrado (recién creado, vacío): sin factura colgando." >&2
|
echo " $name borrado (recién creado, vacío): sin factura colgando." >&2
|
||||||
@@ -205,13 +205,13 @@ for k in $(seq 1 "$N"); do
|
|||||||
fi
|
fi
|
||||||
# BIND-MOUNT, NO SYMLINK (2026-07-22). Anclar el store con \`ln -s\` rompía TODA receta con
|
# BIND-MOUNT, NO SYMLINK (2026-07-22). Anclar el store con \`ln -s\` rompía TODA receta con
|
||||||
# \`zig_version\` en el worker, y el síntoma se leía como deuda de la cascada GUI. Por qué:
|
# \`zig_version\` en el worker, y el síntoma se leía como deuda de la cascada GUI. Por qué:
|
||||||
# hammer deriva el lab del PADRE DEL STORE (BuildConfig::defaults_for_store ⇒
|
# takana deriva el lab del PADRE DEL STORE (BuildConfig::defaults_for_store ⇒
|
||||||
# project_root = store_root.parent(), de ahí .dev-fs/{alpine,tools/zig,cache}). Con el symlink
|
# project_root = store_root.parent(), de ahí .dev-fs/{alpine,tools/zig,cache}). Con el symlink
|
||||||
# el store resuelve a /mnt/cosecha/store ⇒ busca /mnt/cosecha/.dev-fs, que no existe, y muere
|
# el store resuelve a /mnt/cosecha/store ⇒ busca /mnt/cosecha/.dev-fs, que no existe, y muere
|
||||||
# con 'no encuentro el ejecutable zig en …' apuntando al lugar equivocado. Un bind-mount deja
|
# con 'no encuentro el ejecutable zig en …' apuntando al lugar equivocado. Un bind-mount deja
|
||||||
# los datos en el volumen igual, pero \$REMOTE/store sigue siendo una ruta REAL bajo
|
# los datos en el volumen igual, pero \$REMOTE/store sigue siendo una ruta REAL bajo
|
||||||
# \$REMOTE ⇒ el padre vuelve a ser /opt/hammer y .dev-fs se encuentra. Mantiene las dos
|
# \$REMOTE ⇒ el padre vuelve a ser /opt/hammer y .dev-fs se encuentra. Mantiene las dos
|
||||||
# invariantes a la vez: sellar = persistir, y el lab donde hammer lo espera.
|
# invariantes a la vez: sellar = persistir, y el lab donde takana lo espera.
|
||||||
if [ -L $REMOTE/store ]; then rm -f $REMOTE/store; fi
|
if [ -L $REMOTE/store ]; then rm -f $REMOTE/store; fi
|
||||||
mkdir -p $REMOTE/store
|
mkdir -p $REMOTE/store
|
||||||
mountpoint -q $REMOTE/store || mount --bind /mnt/cosecha/store $REMOTE/store
|
mountpoint -q $REMOTE/store || mount --bind /mnt/cosecha/store $REMOTE/store
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ SUELO_FRIO_MIN="${SUELO_FRIO_MIN:-120}"
|
|||||||
sleep 180
|
sleep 180
|
||||||
# Protección 1: árboles que un bwrap activo bind-monta (fase compile dentro del sandbox).
|
# Protección 1: árboles que un bwrap activo bind-monta (fase compile dentro del sandbox).
|
||||||
active=$(pgrep -af bwrap 2>/dev/null | grep -oE 'work/sources/[^ ]+' | sort -u)
|
active=$(pgrep -af bwrap 2>/dev/null | grep -oE 'work/sources/[^ ]+' | sort -u)
|
||||||
# Protección 2: árboles cuya receta tiene un `hammer build` EN VUELO. Durante el fetch/`go mod
|
# Protección 2: árboles cuya receta tiene un `takana build` EN VUELO. Durante el fetch/`go mod
|
||||||
# vendor`/resolve_phases (host-side, ANTES de que arranque el bwrap) el árbol no está bind-montado
|
# vendor`/resolve_phases (host-side, ANTES de que arranque el bwrap) el árbol no está bind-montado
|
||||||
# ⇒ la protección 1 no lo cubre. Una tanda Go con árbol de deps enorme (dnscontrol/lazysql) tarda
|
# ⇒ la protección 1 no lo cubre. Una tanda Go con árbol de deps enorme (dnscontrol/lazysql) tarda
|
||||||
# minutos vendoreando; sin esto, el watchdog le borra el go.mod a mitad → "no build system".
|
# minutos vendoreando; sin esto, el watchdog le borra el go.mod a mitad → "no build system".
|
||||||
@@ -85,7 +85,7 @@ SUELO_FRIO_MIN="${SUELO_FRIO_MIN:-120}"
|
|||||||
# mientras un vendor está activo —o en la VENTANA justo antes de que arranque (otra receta de la
|
# mientras un vendor está activo —o en la VENTANA justo antes de que arranque (otra receta de la
|
||||||
# cola en serie)— le arranca el cache bajo los pies (`.partial`/`go-build/...: no such file`) y
|
# cola en serie)— le arranca el cache bajo los pies (`.partial`/`go-build/...: no such file`) y
|
||||||
# ESE vendor falla. La purga de work/sources de arriba ya liberó lo grueso (segura: saltea las
|
# ESE vendor falla. La purga de work/sources de arriba ya liberó lo grueso (segura: saltea las
|
||||||
# protegidas). Por eso NO purgo las caches Go si hay CUALQUIER `hammer build` en vuelo (no solo
|
# protegidas). Por eso NO purgo las caches Go si hay CUALQUIER `takana build` en vuelo (no solo
|
||||||
# un `go mod vendor` visible en este instante): difiero al próximo tick / al gap idle entre
|
# un `go mod vendor` visible en este instante): difiero al próximo tick / al gap idle entre
|
||||||
# ciclos. El sandbox `go install` usa GOCACHE=/src + -mod=vendor ⇒ no toca estas caches del host.
|
# ciclos. El sandbox `go install` usa GOCACHE=/src + -mod=vendor ⇒ no toca estas caches del host.
|
||||||
if pgrep -f 'go mod vendor' >/dev/null 2>&1 || pgrep -f 'release/hammer.* build ' >/dev/null 2>&1; then
|
if pgrep -f 'go mod vendor' >/dev/null 2>&1 || pgrep -f 'release/hammer.* build ' >/dev/null 2>&1; then
|
||||||
@@ -156,13 +156,13 @@ SUELO_FRIO_MIN="${SUELO_FRIO_MIN:-120}"
|
|||||||
# con el MISMO ArtifactHash, o sea la misma dirección del store. Sin divergencias, sin colisión de
|
# con el MISMO ArtifactHash, o sea la misma dirección del store. Sin divergencias, sin colisión de
|
||||||
# nombre y sin un solo artefacto que podar al retirarla. El andamio ya no sostenía nada: el trabajo
|
# nombre y sin un solo artefacto que podar al retirarla. El andamio ya no sostenía nada: el trabajo
|
||||||
# de la isla dinámica vive en `incoming-gnome`, que es la cola que el perfil usa (119/119).
|
# de la isla dinámica vive en `incoming-gnome`, que es la cola que el perfil usa (119/119).
|
||||||
# ⇒ La comprobación que decide NO es `diff` de las recetas sino `hammer hash`: la resolución de deps
|
# ⇒ La comprobación que decide NO es `diff` de las recetas sino `takana hash`: la resolución de deps
|
||||||
# es hermano→padre, así que dos ficheros idénticos en colas distintas PUEDEN sellar distinto.
|
# es hermano→padre, así que dos ficheros idénticos en colas distintas PUEDEN sellar distinto.
|
||||||
# Orden: las colas con deuda van ANTES de las cerradas (kde 163/163, wlr 129/129 salen por cache-hit).
|
# Orden: las colas con deuda van ANTES de las cerradas (kde 163/163, wlr 129/129 salen por cache-hit).
|
||||||
QUEUES="${QUEUES:-recipes/incoming recipes/incoming-go recipes/incoming-gnome recipes/incoming-cosmic recipes/incoming-kde recipes/incoming-wlr}"
|
QUEUES="${QUEUES:-recipes/incoming recipes/incoming-go recipes/incoming-gnome recipes/incoming-cosmic recipes/incoming-kde recipes/incoming-wlr}"
|
||||||
|
|
||||||
# REBUILD DEL BINARIO AL ARRANCAR (2026-07-18): el hammer horneado en la imagen golden ENVEJECE.
|
# REBUILD DEL BINARIO AL ARRANCAR (2026-07-18): el takana horneado en la imagen golden ENVEJECE.
|
||||||
# Caso real que costó una noche de KDE: la golden del 29-jun traía un hammer sin el fix del overlay
|
# Caso real que costó una noche de KDE: la golden del 29-jun traía un takana sin el fix del overlay
|
||||||
# lowerdir (commit e69eaaa, 12-jul) ⇒ toda receta de muchas deps (kio=52, kwin, plasma-*) desbordaba
|
# lowerdir (commit e69eaaa, 12-jul) ⇒ toda receta de muchas deps (kio=52, kwin, plasma-*) desbordaba
|
||||||
# el límite de 4KB del mount options y el sandbox NI ARRANCABA — 43 recetas atascadas jurando "en
|
# el límite de 4KB del mount options y el sandbox NI ARRANCABA — 43 recetas atascadas jurando "en
|
||||||
# cola". El source SÍ llega fresco (farm-sync rsync-ea el repo), pero nadie recompilaba. Reconstruir
|
# cola". El source SÍ llega fresco (farm-sync rsync-ea el repo), pero nadie recompilaba. Reconstruir
|
||||||
@@ -177,10 +177,10 @@ fi
|
|||||||
# UNA vez, y este loop vive días: `uptime` de 8 días con el binario congelado en el arranque. El
|
# UNA vez, y este loop vive días: `uptime` de 8 días con el binario congelado en el arranque. El
|
||||||
# source SÍ sigue llegando fresco cada 30 min (la siembra rsync-ea el repo), así que el worker
|
# source SÍ sigue llegando fresco cada 30 min (la siembra rsync-ea el repo), así que el worker
|
||||||
# termina con FUENTE NUEVO y BINARIO VIEJO — que es peor que el fósil de la golden, porque nada lo
|
# termina con FUENTE NUEVO y BINARIO VIEJO — que es peor que el fósil de la golden, porque nada lo
|
||||||
# delata: el ArtifactHash NO se mueve por la versión de hammer, así que el build se comporta
|
# delata: el ArtifactHash NO se mueve por la versión de takana, así que el build se comporta
|
||||||
# distinto y `build-state.json` sigue en verde.
|
# distinto y `build-state.json` sigue en verde.
|
||||||
#
|
#
|
||||||
# Caso real que lo motiva: el 2026-09-06 el worker corría un hammer de las 04:54 y el arreglo que
|
# Caso real que lo motiva: el 2026-09-06 el worker corría un takana de las 04:54 y el arreglo que
|
||||||
# materializa los submódulos git había entrado a las 15:11 (`114aeba`). `waterfox` moría en 4 s por
|
# materializa los submódulos git había entrado a las 15:11 (`114aeba`). `waterfox` moría en 4 s por
|
||||||
# `waterfox/browser/locales/moz.build` inexistente y el diagnóstico apuntaba a la receta, a los
|
# `waterfox/browser/locales/moz.build` inexistente y el diagnóstico apuntaba a la receta, a los
|
||||||
# parches y al `--filter=blob:none` — a todo menos al binario. `strings` sobre los dos binarios lo
|
# parches y al `--filter=blob:none` — a todo menos al binario. `strings` sobre los dos binarios lo
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ while :; do
|
|||||||
[ -f "recipes/$n.toml" ] || continue
|
[ -f "recipes/$n.toml" ] || continue
|
||||||
if [ -s "$OUT/$n.verdicts" ]; then hechas=$((hechas + 1)); continue; fi
|
if [ -s "$OUT/$n.verdicts" ]; then hechas=$((hechas + 1)); continue; fi
|
||||||
|
|
||||||
# Forzar build real: `hammer build` pega en la caché si el artefacto ya está sellado y no
|
# Forzar build real: `takana build` pega en la caché si el artefacto ya está sellado y no
|
||||||
# correría nada (veredicto vacío que NO es un fallo). La copia va AL LADO del original o se
|
# correría nada (veredicto vacío que NO es un fallo). La copia va AL LADO del original o se
|
||||||
# rompe la resolución de deps.build, que son relativas al dir de la receta.
|
# rompe la resolución de deps.build, que son relativas al dir de la receta.
|
||||||
tmp="recipes/.hk-$n.toml"
|
tmp="recipes/.hk-$n.toml"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
# Ciclo (idempotente, seguro de re-correr):
|
# Ciclo (idempotente, seguro de re-correr):
|
||||||
# 1. git pull --rebase (sincroniza con el otro agente que pushea al mismo main)
|
# 1. git pull --rebase (sincroniza con el otro agente que pushea al mismo main)
|
||||||
# 2. baja el store sellado del worker (rsync)
|
# 2. baja el store sellado del worker (rsync)
|
||||||
# 3. por cada receta en recipes/incoming-go/: ¿está sellada? (hammer build con `timeout` ⇒ cache-hit
|
# 3. por cada receta en recipes/incoming-go/: ¿está sellada? (takana build con `timeout` ⇒ cache-hit
|
||||||
# instantáneo = sí; si se pasa del timeout sería un build local ⇒ se SALTA, no compilamos en el hub)
|
# instantáneo = sí; si se pasa del timeout sería un build local ⇒ se SALTA, no compilamos en el hub)
|
||||||
# 4. SMOKE-TEST del binario instalado: existe + ELF estático + corre version/--help sin panic/segfault.
|
# 4. SMOKE-TEST del binario instalado: existe + ELF estático + corre version/--help sin panic/segfault.
|
||||||
# - PASA ⇒ promueve (mv recipes/, pack --build) — se firma+commitea al final.
|
# - PASA ⇒ promueve (mv recipes/, pack --build) — se firma+commitea al final.
|
||||||
@@ -91,7 +91,7 @@ for f in "$QUEUE"/*.toml; do
|
|||||||
rn=$(sed -n 's/^name *= *"\(.*\)".*/\1/p' "$f" | head -1); [ -n "$rn" ] || rn="$n"
|
rn=$(sed -n 's/^name *= *"\(.*\)".*/\1/p' "$f" | head -1); [ -n "$rn" ] || rn="$n"
|
||||||
|
|
||||||
# Pre-check BARATO: ¿el worker selló algo para este nombre? (tras el rsync el store local lo tiene).
|
# Pre-check BARATO: ¿el worker selló algo para este nombre? (tras el rsync el store local lo tiene).
|
||||||
# Sin esto, `hammer build` de una receta NO sellada ARRANCARÍA un build local (vendor+compile) y lo
|
# Sin esto, `takana build` de una receta NO sellada ARRANCARÍA un build local (vendor+compile) y lo
|
||||||
# mataría el timeout ⇒ CPU del hub desperdiciada cada cosecha. Si no hay seal `*-<rn>`, salto ya.
|
# mataría el timeout ⇒ CPU del hub desperdiciada cada cosecha. Si no hay seal `*-<rn>`, salto ya.
|
||||||
ls "$STORE"/*-"$rn" >/dev/null 2>&1 || { skipped="$skipped $n"; continue; }
|
ls "$STORE"/*-"$rn" >/dev/null 2>&1 || { skipped="$skipped $n"; continue; }
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
# respaldo-promover.sh — mueve lo que el worker depositó en el BUZÓN al respaldo consolidado.
|
# respaldo-promover.sh — mueve lo que el worker depositó en el BUZÓN al respaldo consolidado.
|
||||||
#
|
#
|
||||||
# ── POR QUÉ HAY UN BUZÓN Y NO ESCRITURA DIRECTA ────────────────────────────────────────────────
|
# ── POR QUÉ HAY UN BUZÓN Y NO ESCRITURA DIRECTA ────────────────────────────────────────────────
|
||||||
# El worker es EFÍMERO y se borra solo; darle escritura sobre `hammer/store` sería darle permiso de
|
# El worker es EFÍMERO y se borra solo; darle escritura sobre `takana/store` sería darle permiso de
|
||||||
# borrado sobre el único respaldo que existe. Y los permisos de una subcuenta del Storage Box son
|
# borrado sobre el único respaldo que existe. Y los permisos de una subcuenta del Storage Box son
|
||||||
# BINARIOS: `--readonly` sí o no. No hay append-only, no hay write-sin-delete (verificado en la API
|
# BINARIOS: `--readonly` sí o no. No hay append-only, no hay write-sin-delete (verificado en la API
|
||||||
# el 2026-08-09, no de memoria).
|
# el 2026-08-09, no de memoria).
|
||||||
#
|
#
|
||||||
# Así que la contención no se hace con un permiso sino con el ALCANCE: la subcuenta de escritura
|
# Así que la contención no se hace con un permiso sino con el ALCANCE: la subcuenta de escritura
|
||||||
# tiene su home en `incoming/` y `hammer/store` sencillamente NO EXISTE para ella. Lo máximo que
|
# tiene su home en `incoming/` y `takana/store` sencillamente NO EXISTE para ella. Lo máximo que
|
||||||
# puede destruir es lo que ella misma depositó y todavía no se promovió — que sigue estando en el
|
# puede destruir es lo que ella misma depositó y todavía no se promovió — que sigue estando en el
|
||||||
# volumen de la granja. Un permiso puede estar mal puesto; un directorio que no está en tu home no.
|
# volumen de la granja. Un permiso puede estar mal puesto; un directorio que no está en tu home no.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
# protegerse no es un respaldo. La subcuenta acota el daño posible a cero por construcción:
|
# protegerse no es un respaldo. La subcuenta acota el daño posible a cero por construcción:
|
||||||
# --readonly el sistema de ficheros se monta de sólo lectura del lado del box
|
# --readonly el sistema de ficheros se monta de sólo lectura del lado del box
|
||||||
# --reachable-externally=false sólo desde la red de Hetzner: la credencial no sirve fuera
|
# --reachable-externally=false sólo desde la red de Hetzner: la credencial no sirve fuera
|
||||||
# --home-directory hammer no ve el resto del box
|
# --home-directory takana no ve el resto del box
|
||||||
#
|
#
|
||||||
# ── LA VERIFICACIÓN ES NEGATIVA, Y ESO NO ES OPCIONAL ──────────────────────────────────────────
|
# ── LA VERIFICACIÓN ES NEGATIVA, Y ESO NO ES OPCIONAL ──────────────────────────────────────────
|
||||||
# «Sólo lectura» es una afirmación sobre lo que el sistema **impide**, así que no se comprueba
|
# «Sólo lectura» es una afirmación sobre lo que el sistema **impide**, así que no se comprueba
|
||||||
@@ -24,21 +24,21 @@
|
|||||||
#
|
#
|
||||||
# ── LA LLAVE VIVE EN EL WORKER Y MUERE CON ÉL ──────────────────────────────────────────────────
|
# ── LA LLAVE VIVE EN EL WORKER Y MUERE CON ÉL ──────────────────────────────────────────────────
|
||||||
# Se genera en el worker (nunca viaja una privada desde el laptop) y su pública se autoriza en
|
# Se genera en el worker (nunca viaja una privada desde el laptop) y su pública se autoriza en
|
||||||
# `hammer/.ssh/authorized_keys` del box, escrita CON LA CUENTA PRINCIPAL — la subcuenta no puede
|
# `takana/.ssh/authorized_keys` del box, escrita CON LA CUENTA PRINCIPAL — la subcuenta no puede
|
||||||
# escribir ni su propio authorized_keys, que es justo lo que se quería.
|
# escribir ni su propio authorized_keys, que es justo lo que se quería.
|
||||||
# El home es `hammer` y no `hammer/store` a propósito: el authorized_keys tiene que estar en el home,
|
# El home es `takana` y no `takana/store` a propósito: el authorized_keys tiene que estar en el home,
|
||||||
# y no queremos un `.ssh` dentro del store, que es CAS y se cuenta por entradas.
|
# y no queremos un `.ssh` dentro del store, que es CAS y se cuenta por entradas.
|
||||||
#
|
#
|
||||||
# ⚠ La shell del Storage Box es RESTRINGIDA: acepta `ls`/`mkdir`/`rm` pero **no redirección**.
|
# ⚠ La shell del Storage Box es RESTRINGIDA: acepta `ls`/`mkdir`/`rm` pero **no redirección**.
|
||||||
# `echo k > authorized_keys` falla EN SILENCIO (crea el directorio y no el fichero). Va con `scp`.
|
# `echo k > authorized_keys` falla EN SILENCIO (crea el directorio y no el fichero). Va con `scp`.
|
||||||
#
|
#
|
||||||
# ── DOS SUBCUENTAS, DOS VERBOS (2026-08-09) ────────────────────────────────────────────────────
|
# ── DOS SUBCUENTAS, DOS VERBOS (2026-08-09) ────────────────────────────────────────────────────
|
||||||
# `sub1` (home `hammer`, --readonly) es para MIRAR qué hay ya respaldado y no volver a subirlo.
|
# `sub1` (home `takana`, --readonly) es para MIRAR qué hay ya respaldado y no volver a subirlo.
|
||||||
# `sub2` (home `incoming`, escritura) es el BUZÓN donde el worker DEPOSITA lo nuevo.
|
# `sub2` (home `incoming`, escritura) es el BUZÓN donde el worker DEPOSITA lo nuevo.
|
||||||
#
|
#
|
||||||
# No hay una sola subcuenta que escriba sin poder borrar: los permisos de la API son binarios
|
# No hay una sola subcuenta que escriba sin poder borrar: los permisos de la API son binarios
|
||||||
# (`--readonly` sí o no; verificado, no recordado). La contención se hace por ALCANCE — el buzón no
|
# (`--readonly` sí o no; verificado, no recordado). La contención se hace por ALCANCE — el buzón no
|
||||||
# tiene a `hammer/store` dentro de su home, así que el respaldo consolidado no existe para él. Lo que
|
# tiene a `takana/store` dentro de su home, así que el respaldo consolidado no existe para él. Lo que
|
||||||
# el worker puede destruir se reduce a lo que él mismo depositó y aún no se promovió, que sigue
|
# el worker puede destruir se reduce a lo que él mismo depositó y aún no se promovió, que sigue
|
||||||
# estando en el volumen. Promoción: `scripts/farm/respaldo-promover.sh` (un `mv`, cero bytes de red).
|
# estando en el volumen. Promoción: `scripts/farm/respaldo-promover.sh` (un `mv`, cero bytes de red).
|
||||||
#
|
#
|
||||||
@@ -78,7 +78,7 @@ CRED="$HOME/.config/hammer/storagebox-worker.env"
|
|||||||
# worker», que apunta al worker cuando el problema estaba en el known_hosts del laptop. Un mensaje
|
# worker», que apunta al worker cuando el problema estaba en el known_hosts del laptop. Un mensaje
|
||||||
# que culpa al sitio equivocado cuesta más que no tener mensaje.
|
# que culpa al sitio equivocado cuesta más que no tener mensaje.
|
||||||
# Purgar la entrada vieja es correcto ACÁ y sólo acá: la identidad del worker no es su llave, es el
|
# Purgar la entrada vieja es correcto ACÁ y sólo acá: la identidad del worker no es su llave, es el
|
||||||
# label `role=hammer-worker` del proyecto hcloud; el secreto no viaja por este canal.
|
# label `role=takana-worker` del proyecto hcloud; el secreto no viaja por este canal.
|
||||||
ssh_worker() { # $1 = ip, resto = orden remota
|
ssh_worker() { # $1 = ip, resto = orden remota
|
||||||
ip="$1"; shift
|
ip="$1"; shift
|
||||||
ssh-keygen -R "$ip" >/dev/null 2>&1
|
ssh-keygen -R "$ip" >/dev/null 2>&1
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# saldar-deuda-static.sh — reconstruye las recetas `link = "static"` cuyo hash VIGENTE no está
|
# saldar-deuda-static.sh — reconstruye las recetas `link = "static"` cuyo hash VIGENTE no está
|
||||||
# sellado en el store (la "deuda de rebuild" que destapó `hammer hash`, 2026-07-17).
|
# sellado en el store (la "deuda de rebuild" que destapó `takana hash`, 2026-07-17).
|
||||||
#
|
#
|
||||||
# POR QUÉ EXISTE. El trabajo reciente (matar-gcc migró 27 recetas C a zig, el frente static, harkaq
|
# POR QUÉ EXISTE. El trabajo reciente (matar-gcc migró 27 recetas C a zig, el frente static, harkaq
|
||||||
# declarando deps) cambió muchas recetas base sin re-sellarlas. Cada cambio re-hashea la receta Y
|
# declarando deps) cambió muchas recetas base sin re-sellarlas. Cada cambio re-hashea la receta Y
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
# a la receta de hoy. `scripts/static-audit.sh` las cuenta como "sin artefacto" (deuda real, ya no
|
# a la receta de hoy. `scripts/static-audit.sh` las cuenta como "sin artefacto" (deuda real, ya no
|
||||||
# enmascarada). Este script las salda.
|
# enmascarada). Este script las salda.
|
||||||
#
|
#
|
||||||
# NO HACE FALTA ORDEN TOPOLÓGICO: `hammer build` arrastra sus deps de build recursivamente
|
# NO HACE FALTA ORDEN TOPOLÓGICO: `takana build` arrastra sus deps de build recursivamente
|
||||||
# (resolve_build_dep_hashes), así que construir `curl` construye `openssl` y `perl` primero. Se
|
# (resolve_build_dep_hashes), así que construir `curl` construye `openssl` y `perl` primero. Se
|
||||||
# puede correr en cualquier orden; las cache-hit son instantáneas.
|
# puede correr en cualquier orden; las cache-hit son instantáneas.
|
||||||
#
|
#
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
# `farm-down`. Corre igual en el laptop, pero el stack GUI (cairo/pango/gtk…) fallará por zig-skew:
|
# `farm-down`. Corre igual en el laptop, pero el stack GUI (cairo/pango/gtk…) fallará por zig-skew:
|
||||||
# usá `SKIP_GUI=1` para saltarlo (default en laptop).
|
# usá `SKIP_GUI=1` para saltarlo (default en laptop).
|
||||||
#
|
#
|
||||||
# LA DEUDA SE CALCULA EN VIVO, no de una lista que envejece: `hammer hash --check` por receta. Eso
|
# LA DEUDA SE CALCULA EN VIVO, no de una lista que envejece: `takana hash --check` por receta. Eso
|
||||||
# es exactamente lo que el audit usa para no auditar sellados rancios.
|
# es exactamente lo que el audit usa para no auditar sellados rancios.
|
||||||
#
|
#
|
||||||
# Uso: scripts/farm/saldar-deuda-static.sh # construye toda la deuda
|
# Uso: scripts/farm/saldar-deuda-static.sh # construye toda la deuda
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# tandas.sh — encadena varias campañas de deuda en el worker, en ORDEN y sin solaparse.
|
# tandas.sh — encadena varias campañas de deuda en el worker, en ORDEN y sin solaparse.
|
||||||
#
|
#
|
||||||
# POR QUÉ EN SERIE Y NO EN PARALELO: dos `hammer build` simultáneos sobre el mismo store compiten
|
# POR QUÉ EN SERIE Y NO EN PARALELO: dos `takana build` simultáneos sobre el mismo store compiten
|
||||||
# por el mismo `work/sources` y por el watchdog de disco del worker-loop (que borra árboles que
|
# por el mismo `work/sources` y por el watchdog de disco del worker-loop (que borra árboles que
|
||||||
# ningún bwrap tiene montado). El paralelismo del worker está DENTRO de cada build (`-j$(nproc)`),
|
# ningún bwrap tiene montado). El paralelismo del worker está DENTRO de cada build (`-j$(nproc)`),
|
||||||
# no entre builds.
|
# no entre builds.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# vps-setup.sh — provisiona un WORKER de granja hammer en un VPS o LXC fresco.
|
# vps-setup.sh — provisiona un WORKER de granja takana en un VPS o LXC fresco.
|
||||||
#
|
#
|
||||||
# DOS FAMILIAS SOPORTADAS, detectadas por gestor de paquetes:
|
# DOS FAMILIAS SOPORTADAS, detectadas por gestor de paquetes:
|
||||||
# · apt → Debian/Ubuntu: los workers efímeros de Hetzner (`farm-up.sh`, imagen golden).
|
# · apt → Debian/Ubuntu: los workers efímeros de Hetzner (`farm-up.sh`, imagen golden).
|
||||||
@@ -64,11 +64,11 @@ else
|
|||||||
#
|
#
|
||||||
# ⚠ `patch` VA EXPLÍCITO Y NO ES OBVIO (2026-08-29). En Debian entra de regalo dentro de
|
# ⚠ `patch` VA EXPLÍCITO Y NO ES OBVIO (2026-08-29). En Debian entra de regalo dentro de
|
||||||
# `build-essential`; al desglosar a gcc/g++/make sueltos se cayó sin que nadie lo notara. El
|
# `build-essential`; al desglosar a gcc/g++/make sueltos se cayó sin que nadie lo notara. El
|
||||||
# campo `patches = [...]` de una receta lo aplica hammer DEL LADO DEL HOST, fuera del sandbox
|
# campo `patches = [...]` de una receta lo aplica takana DEL LADO DEL HOST, fuera del sandbox
|
||||||
# ⇒ no alcanza con que el rootfs lo traiga (lo trae: `/usr/bin/patch` está en el alpine). Sin
|
# ⇒ no alcanza con que el rootfs lo traiga (lo trae: `/usr/bin/patch` está en el alpine). Sin
|
||||||
# él, `cairo-shared` muere con `spawn patch: No such file or directory` y detrás caen `pango`
|
# él, `cairo-shared` muere con `spawn patch: No such file or directory` y detrás caen `pango`
|
||||||
# y `gtk4`, o sea el stack GUI entero de GNOME por un binario de 129 KB.
|
# y `gtk4`, o sea el stack GUI entero de GNOME por un binario de 129 KB.
|
||||||
# Regla: toda herramienta que hammer invoque HOST-SIDE va en esta lista, no en `[deps]` de la
|
# Regla: toda herramienta que takana invoque HOST-SIDE va en esta lista, no en `[deps]` de la
|
||||||
# receta — declararla en la receta re-hashearía cairo y todo GNOME debajo para nada.
|
# receta — declararla en la receta re-hashearía cairo y todo GNOME debajo para nada.
|
||||||
$DNF install -y -q git gcc gcc-c++ make patch curl pkgconf-pkg-config openssl-devel \
|
$DNF install -y -q git gcc gcc-c++ make patch curl pkgconf-pkg-config openssl-devel \
|
||||||
bubblewrap rsync ca-certificates shadow-utils xz tar findutils
|
bubblewrap rsync ca-certificates shadow-utils xz tar findutils
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
# El laptop manda ÓRDENES (la promoción es un `mv`, cero bytes); los DATOS van por acá.
|
# El laptop manda ÓRDENES (la promoción es un `mv`, cero bytes); los DATOS van por acá.
|
||||||
#
|
#
|
||||||
# ── LAS DOS CREDENCIALES, Y POR QUÉ HACEN FALTA LAS DOS ────────────────────────────────────────
|
# ── LAS DOS CREDENCIALES, Y POR QUÉ HACEN FALTA LAS DOS ────────────────────────────────────────
|
||||||
# `sub1` (sólo lectura, home `hammer`) sirve para PREGUNTAR qué hay ya respaldado. Sin eso el worker
|
# `sub1` (sólo lectura, home `takana`) sirve para PREGUNTAR qué hay ya respaldado. Sin eso el worker
|
||||||
# resubiría el corpus entero en cada ciclo.
|
# resubiría el corpus entero en cada ciclo.
|
||||||
# `sub2` (escritura, home `incoming`) es el BUZÓN donde deposita. No alcanza a `hammer/store`: el
|
# `sub2` (escritura, home `incoming`) es el BUZÓN donde deposita. No alcanza a `takana/store`: el
|
||||||
# respaldo consolidado no está dentro de su home. Ver `respaldo-subcuenta.sh`.
|
# respaldo consolidado no está dentro de su home. Ver `respaldo-subcuenta.sh`.
|
||||||
#
|
#
|
||||||
# ── UN SOLO rsync CON --files-from, NO UNO POR ARTEFACTO ───────────────────────────────────────
|
# ── UN SOLO rsync CON --files-from, NO UNO POR ARTEFACTO ───────────────────────────────────────
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# fuentes-vigia.sh — comprueba que las URLs de las recetas SIGUEN VIVAS (ADR 0013 §3).
|
# fuentes-vigia.sh — comprueba que las URLs de las recetas SIGUEN VIVAS (ADR 0013 §3).
|
||||||
#
|
#
|
||||||
# ── POR QUÉ ESTO EXISTE APARTE Y NO DENTRO DE `hammer build` ───────────────────────────────────
|
# ── POR QUÉ ESTO EXISTE APARTE Y NO DENTRO DE `takana build` ───────────────────────────────────
|
||||||
# Desde el ADR 0013 el mirror propio se consulta ANTES que upstream, y `hammer build` no avisa
|
# Desde el ADR 0013 el mirror propio se consulta ANTES que upstream, y `takana build` no avisa
|
||||||
# cuando lo usa. Eso es correcto para construir y PELIGROSO sin contrapeso: un mirror que sirve
|
# cuando lo usa. Eso es correcto para construir y PELIGROSO sin contrapeso: un mirror que sirve
|
||||||
# calladamente lo que upstream ya perdió convierte un fallo ruidoso en silencio, y las URLs se van
|
# calladamente lo que upstream ya perdió convierte un fallo ruidoso en silencio, y las URLs se van
|
||||||
# muriendo una por una sin que nadie se entere. El día que el mirror se pierda, el corpus resulta
|
# muriendo una por una sin que nadie se entere. El día que el mirror se pierda, el corpus resulta
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
# . scripts/fuentes/mirror-env.sh
|
# . scripts/fuentes/mirror-env.sh
|
||||||
# flock work/.farm-build.lock ./target/release/takana --store ./store build <receta>
|
# flock work/.farm-build.lock ./target/release/takana --store ./store build <receta>
|
||||||
#
|
#
|
||||||
# Sin esto `hammer build` va derecho a upstream, que es el comportamiento de siempre: el mirror es
|
# Sin esto `takana build` va derecho a upstream, que es el comportamiento de siempre: el mirror es
|
||||||
# ADITIVO y su ausencia nunca rompe un build. Por eso no está horneado en el binario — un default
|
# ADITIVO y su ausencia nunca rompe un build. Por eso no está horneado en el binario — un default
|
||||||
# que apunta a una máquina concreta convertiría un fallo de red en un fallo de hammer para cualquiera
|
# que apunta a una máquina concreta convertiría un fallo de red en un fallo de takana para cualquiera
|
||||||
# que clone el repo.
|
# que clone el repo.
|
||||||
#
|
#
|
||||||
# LISTA, no una URL (ADR 0014): las dos variables aceptan varios orígenes separados por comas y se
|
# LISTA, no una URL (ADR 0014): las dos variables aceptan varios orígenes separados por comas y se
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ def bundle(e, tmpdir):
|
|||||||
# El campo `commit` de una receta NO siempre es un commit: puede pinear un objeto TAG anotado.
|
# El campo `commit` de una receta NO siempre es un commit: puede pinear un objeto TAG anotado.
|
||||||
# Un SHA de tag es una identidad igual de buena (`git archive` lo acepta) y por eso hash_inputs
|
# Un SHA de tag es una identidad igual de buena (`git archive` lo acepta) y por eso hash_inputs
|
||||||
# no lo distingue, pero `refs/heads/*` sólo apunta a commits. Se pela para la rama y, si hubo
|
# no lo distingue, pero `refs/heads/*` sólo apunta a commits. Se pela para la rama y, si hubo
|
||||||
# que pelar, el objeto tag viaja aparte: sin él, el `cat-file -e <commit>` del lado de hammer
|
# que pelar, el objeto tag viaja aparte: sin él, el `cat-file -e <commit>` del lado de takana
|
||||||
# falla y el mirror queda correcto-pero-inútil justo para estas recetas.
|
# falla y el mirror queda correcto-pero-inútil justo para estas recetas.
|
||||||
r = git("rev-parse", e["commit"] + "^{commit}")
|
r = git("rev-parse", e["commit"] + "^{commit}")
|
||||||
if r.returncode != 0:
|
if r.returncode != 0:
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
# mirror-git-poblar.sh — espeja las fuentes GIT del corpus como bundles (ADR 0013).
|
# mirror-git-poblar.sh — espeja las fuentes GIT del corpus como bundles (ADR 0013).
|
||||||
#
|
#
|
||||||
# ── POR QUÉ BUNDLES SHALLOW Y NO CLONES COMPLETOS ──────────────────────────────────────────────
|
# ── POR QUÉ BUNDLES SHALLOW Y NO CLONES COMPLETOS ──────────────────────────────────────────────
|
||||||
# Hammer no usa la historia: lo único que hace con un repo es `git archive <commit> | tar -x`, o sea
|
# Takana no usa la historia: lo único que hace con un repo es `git archive <commit> | tar -x`, o sea
|
||||||
# materializar UN árbol. Un clon `--depth 1` del commit exacto basta, y para `act` son 8,9 MB en
|
# materializar UN árbol. Un clon `--depth 1` del commit exacto basta, y para `act` son 8,9 MB en
|
||||||
# lugar del repositorio entero. Con 606 fuentes git, la diferencia decide si el mirror cabe.
|
# lugar del repositorio entero. Con 606 fuentes git, la diferencia decide si el mirror cabe.
|
||||||
#
|
#
|
||||||
# El objeto se nombra por CONTENIDO igual que los tarballs: `hammer/fuentes-git/{commit}.bundle`.
|
# El objeto se nombra por CONTENIDO igual que los tarballs: `takana/fuentes-git/{commit}.bundle`.
|
||||||
# El commit ES su verificación — git comprueba cada objeto contra su SHA al desempaquetar, así que
|
# El commit ES su verificación — git comprueba cada objeto contra su SHA al desempaquetar, así que
|
||||||
# un bundle alterado no pasa. No hace falta índice ni sha256 aparte.
|
# un bundle alterado no pasa. No hace falta índice ni sha256 aparte.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# mirror-poblar.sh — sube la caché local de tarballs al mirror de fuentes (ADR 0013).
|
# mirror-poblar.sh — sube la caché local de tarballs al mirror de fuentes (ADR 0013).
|
||||||
#
|
#
|
||||||
# El mirror está direccionado por CONTENIDO: `hammer/fuentes/{sha256}.tar`, exactamente el mismo
|
# El mirror está direccionado por CONTENIDO: `takana/fuentes/{sha256}.tar`, exactamente el mismo
|
||||||
# nombre que usa `work/tarballs/`. Por eso subir es un rsync plano y no hace falta índice ninguno:
|
# nombre que usa `work/tarballs/`. Por eso subir es un rsync plano y no hace falta índice ninguno:
|
||||||
# el nombre del fichero ES su verificación.
|
# el nombre del fichero ES su verificación.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# hydrate-gnome.sh — proyecta al FHS el cierre de runtime de una receta GNOME, desde artefactos
|
# hydrate-gnome.sh — proyecta al FHS el cierre de runtime de una receta GNOME, desde artefactos
|
||||||
# SELLADOS del store, sin rebuild ni reproduce (`hammer hydrate <hash> --into`).
|
# SELLADOS del store, sin rebuild ni reproduce (`takana hydrate <hash> --into`).
|
||||||
#
|
#
|
||||||
# DIFERENCIA CON scripts/kde/hydrate-from-store.sh, y por qué importa: aquél resuelve el cierre desde
|
# DIFERENCIA CON scripts/kde/hydrate-from-store.sh, y por qué importa: aquél resuelve el cierre desde
|
||||||
# un `index.json` de repo y elige el artefacto por MTIME con un CUTOFF ("el más nuevo anterior a hoy").
|
# un `index.json` de repo y elige el artefacto por MTIME con un CUTOFF ("el más nuevo anterior a hoy").
|
||||||
# Eso es una heurística: si dos artefactos del mismo paquete conviven en el store, la fecha no dice
|
# Eso es una heurística: si dos artefactos del mismo paquete conviven en el store, la fecha no dice
|
||||||
# cuál corresponde a la receta VIGENTE. Acá el cierre sale del GRAFO REAL de recetas (`[deps].build`,
|
# cuál corresponde a la receta VIGENTE. Acá el cierre sale del GRAFO REAL de recetas (`[deps].build`,
|
||||||
# resolución hermano→padre, la misma que usa hammer) y el artefacto se elige por `hammer hash`, que
|
# resolución hermano→padre, la misma que usa takana) y el artefacto se elige por `takana hash`, que
|
||||||
# calcula el ArtifactHash de la receta de HOY sin construir. O sea: cero ambigüedad, y si falta algo
|
# calcula el ArtifactHash de la receta de HOY sin construir. O sea: cero ambigüedad, y si falta algo
|
||||||
# el reporte dice exactamente qué receta y con qué hash lo buscaba.
|
# el reporte dice exactamente qué receta y con qué hash lo buscaba.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ echo "==> inyectando arje-logind-compat (el login1 del fractal)"
|
|||||||
# LEYENDO /run/systemd/{sessions,users,seats}. Pero alguien tiene que ESCRIBIR esos ficheros, y ese
|
# LEYENDO /run/systemd/{sessions,users,seats}. Pero alguien tiene que ESCRIBIR esos ficheros, y ese
|
||||||
# alguien es arje-logind-compat, el daemon D-Bus que se hace pasar por org.freedesktop.login1.
|
# alguien es arje-logind-compat, el daemon D-Bus que se hace pasar por org.freedesktop.login1.
|
||||||
# libelogind entra solo (es dep de mutter); el daemon no, porque nadie lo declara como dep de build.
|
# libelogind entra solo (es dep de mutter); el daemon no, porque nadie lo declara como dep de build.
|
||||||
# El artefacto se elige por `hammer hash` sobre la receta —el que corresponde a la receta de HOY—, no
|
# El artefacto se elige por `takana hash` sobre la receta —el que corresponde a la receta de HOY—, no
|
||||||
# por el más reciente del store: con dos artefactos del mismo paquete conviviendo, la fecha no dice
|
# por el más reciente del store: con dos artefactos del mismo paquete conviviendo, la fecha no dice
|
||||||
# cuál es el vigente. ALC_BIN permite inyectar un binario RECIÉN COMPILADO en vez del artefacto sellado. Es para probar
|
# cuál es el vigente. ALC_BIN permite inyectar un binario RECIÉN COMPILADO en vez del artefacto sellado. Es para probar
|
||||||
# un cambio en arje-compat antes de commitear/pushear tawasuyu y re-sellar la receta (la receta pina
|
# un cambio en arje-compat antes de commitear/pushear tawasuyu y re-sellar la receta (la receta pina
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# hammer-install.sh — Etapa E2: instalador a disco. Vuelca el `product-rootfs` (lean: 4/4 + userland
|
# takana-install.sh — Etapa E2: instalador a disco. Vuelca el `product-rootfs` (lean: 4/4 + userland
|
||||||
# Rust + sshd) sobre un DISCO destino (block device real `/dev/sdX`, o un fichero pre-dimensionado para
|
# Rust + sshd) sobre un DISCO destino (block device real `/dev/sdX`, o un fichero pre-dimensionado para
|
||||||
# pruebas) con el mismo layout GPT + GRUB BIOS de la imagen E1, pero IN-PLACE sobre el target. Tras
|
# pruebas) con el mismo layout GPT + GRUB BIOS de la imagen E1, pero IN-PLACE sobre el target. Tras
|
||||||
# instalar, el disco arranca solo (SeaBIOS → GRUB → kernel → arje-zero PID1 → hammerd+getty+sshd).
|
# instalar, el disco arranca solo (SeaBIOS → GRUB → kernel → arje-zero PID1 → hammerd+getty+sshd).
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# hammer-install — instalador a disco DESDE el medio live (Etapa E5 / refinamiento #1).
|
# takana-install — instalador a disco DESDE el medio live (Etapa E5 / refinamiento #1).
|
||||||
#
|
#
|
||||||
# Se inyecta en el rootfs del producto como /usr/bin/hammer-install (ver scripts/iso-image.sh
|
# Se inyecta en el rootfs del producto como /usr/bin/hammer-install (ver scripts/iso-image.sh
|
||||||
# INSTALLER=1). Corre DENTRO del live, como root real (arje-zero es PID1) ⇒ NO necesita unshare -r
|
# INSTALLER=1). Corre DENTRO del live, como root real (arje-zero es PID1) ⇒ NO necesita unshare -r
|
||||||
@@ -19,11 +19,11 @@
|
|||||||
# (hd0,msdos1)/boot/grub/grub.cfg → linux /boot/bzImage root=/dev/<dev>1 → wrapper /sbin/init.
|
# (hd0,msdos1)/boot/grub/grub.cfg → linux /boot/bzImage root=/dev/<dev>1 → wrapper /sbin/init.
|
||||||
#
|
#
|
||||||
# Modo de uso:
|
# Modo de uso:
|
||||||
# INTERACTIVO (sin argumentos, con TTY): hammer-install
|
# INTERACTIVO (sin argumentos, con TTY): takana-install
|
||||||
# TUI en busybox sh: detecta discos, el usuario elige destino + confirma el borrado, recoge
|
# TUI en busybox sh: detecta discos, el usuario elige destino + confirma el borrado, recoge
|
||||||
# hostname / credencial de root / zona horaria / teclado / tamaños de partición, y recién ahí
|
# hostname / credencial de root / zona horaria / teclado / tamaños de partición, y recién ahí
|
||||||
# particiona+instala. Es la cara humana del instalador (el /init del ISO installer lo lanza).
|
# particiona+instala. Es la cara humana del instalador (el /init del ISO installer lo lanza).
|
||||||
# DESATENDIDO (con device): hammer-install /dev/vdb [ROOT_MB] [STORE_MB]
|
# DESATENDIDO (con device): takana-install /dev/vdb [ROOT_MB] [STORE_MB]
|
||||||
# Autoinstalador (lo usa iso-install-test.sh con AUTO_INSTALL). La config sale de env:
|
# Autoinstalador (lo usa iso-install-test.sh con AUTO_INSTALL). La config sale de env:
|
||||||
# TAKANA_HOSTNAME / TAKANA_ROOT_PW / TAKANA_ROOT_AUTHKEYS / TAKANA_TZ / TAKANA_KEYMAP.
|
# TAKANA_HOSTNAME / TAKANA_ROOT_PW / TAKANA_ROOT_AUTHKEYS / TAKANA_TZ / TAKANA_KEYMAP.
|
||||||
# Los nombres viejos HAMMER_* se siguen aceptando (ADR 0016); gana el nuevo si están los dos.
|
# Los nombres viejos HAMMER_* se siguen aceptando (ADR 0016); gana el nuevo si están los dos.
|
||||||
@@ -331,7 +331,7 @@ FDISK
|
|||||||
"$BB" mke2fs -F -L hammer-store "$P3" >/dev/null 2>&1
|
"$BB" mke2fs -F -L hammer-store "$P3" >/dev/null 2>&1
|
||||||
"$BB" mke2fs -F -L hammer-state "$P4" >/dev/null 2>&1
|
"$BB" mke2fs -F -L hammer-state "$P4" >/dev/null 2>&1
|
||||||
|
|
||||||
# initramfs de pivote (busybox estático del live + /init: findfs LABEL=hammer-root → switch_root).
|
# initramfs de pivote (busybox estático del live + /init: findfs LABEL=takana-root → switch_root).
|
||||||
echo "==> armando el initramfs de pivote (busybox + /init switch_root a hammer-root)"
|
echo "==> armando el initramfs de pivote (busybox + /init switch_root a hammer-root)"
|
||||||
IRD_TREE=/run/hammer-efi-ird
|
IRD_TREE=/run/hammer-efi-ird
|
||||||
"$BB" rm -rf "$IRD_TREE"
|
"$BB" rm -rf "$IRD_TREE"
|
||||||
@@ -397,8 +397,8 @@ INIT
|
|||||||
"$BB" mkdir -p "$MNT/usr/sbin"
|
"$BB" mkdir -p "$MNT/usr/sbin"
|
||||||
cp "$PAYLOAD/hammer-recover" "$MNT/usr/sbin/hammer-recover"; "$BB" chmod 0755 "$MNT/usr/sbin/hammer-recover"
|
cp "$PAYLOAD/hammer-recover" "$MNT/usr/sbin/hammer-recover"; "$BB" chmod 0755 "$MNT/usr/sbin/hammer-recover"
|
||||||
fi
|
fi
|
||||||
# CLI hammer (static musl) para el menú de arranque por grafo (ADR 0010): lo copia al disco desde el
|
# CLI takana (static musl) para el menú de arranque por grafo (ADR 0010): lo copia al disco desde el
|
||||||
# payload; el wrapper lo invoca como `hammer boot menu`.
|
# payload; el wrapper lo invoca como `takana boot menu`.
|
||||||
if [ -x "$PAYLOAD/hammer" ]; then
|
if [ -x "$PAYLOAD/hammer" ]; then
|
||||||
cp "$PAYLOAD/hammer" "$MNT/usr/bin/hammer"; "$BB" chmod 0755 "$MNT/usr/bin/hammer"
|
cp "$PAYLOAD/hammer" "$MNT/usr/bin/hammer"; "$BB" chmod 0755 "$MNT/usr/bin/hammer"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
# IRREDUCIBLE —nadie la provee— cuenta contra el <5%. Sin esa distinción la métrica mide
|
# IRREDUCIBLE —nadie la provee— cuenta contra el <5%. Sin esa distinción la métrica mide
|
||||||
# ansiedad, no viabilidad.
|
# ansiedad, no viabilidad.
|
||||||
#
|
#
|
||||||
# `hammer build` pega en la caché si el artefacto ya está sellado (no correría nada y el
|
# `takana build` pega en la caché si el artefacto ya está sellado (no correría nada y el
|
||||||
# veredicto saldría vacío sin que sea un fallo). Se fuerza un build real copiando la receta con
|
# veredicto saldría vacío sin que sea un fallo). Se fuerza un build real copiando la receta con
|
||||||
# otro `name` — cambia hash_inputs sin tocar el store real ni la receta del repo.
|
# otro `name` — cambia hash_inputs sin tocar el store real ni la receta del repo.
|
||||||
set -eu
|
set -eu
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
# es un artefacto sellado del store (`store/<hash>-<name>/usr/...`). La clausura es, exactamente,
|
# es un artefacto sellado del store (`store/<hash>-<name>/usr/...`). La clausura es, exactamente,
|
||||||
# el conjunto de ficheros que esas deps aportan — ni uno más.
|
# el conjunto de ficheros que esas deps aportan — ni uno más.
|
||||||
#
|
#
|
||||||
# El sandbox de hammer apila cada dep con `--overlay-src` sobre el rootfs Alpine, así que el
|
# El sandbox de takana apila cada dep con `--overlay-src` sobre el rootfs Alpine, así que el
|
||||||
# fichero `store/<hash>-zlib/usr/include/zlib.h` aparece dentro como `/usr/include/zlib.h`. La
|
# fichero `store/<hash>-zlib/usr/include/zlib.h` aparece dentro como `/usr/include/zlib.h`. La
|
||||||
# traducción es sólo quitar el prefijo del store: el resto del path YA es el path del sandbox.
|
# traducción es sólo quitar el prefijo del store: el resto del path YA es el path del sandbox.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ def main():
|
|||||||
#
|
#
|
||||||
# Este bug costó caro: `/bin/busybox` está concedido (el sandbox corre `sh -c` y /bin/sh→
|
# Este bug costó caro: `/bin/busybox` está concedido (el sandbox corre `sh -c` y /bin/sh→
|
||||||
# busybox), pero como `recipes/busybox.toml` existe, el clasificador propuso "declarar dep:
|
# busybox), pero como `recipes/busybox.toml` existe, el clasificador propuso "declarar dep:
|
||||||
# busybox" y la cosecha lo declaró en 29 recetas. Declararlo apila el busybox de hammer sobre
|
# busybox" y la cosecha lo declaró en 29 recetas. Declararlo apila el busybox de takana sobre
|
||||||
# el de Alpine y ROMPE el build (binutils: "cannot run C compiled programs"). Además va contra
|
# el de Alpine y ROMPE el build (binutils: "cannot run C compiled programs"). Además va contra
|
||||||
# la Etapa C, que reemplaza busybox por uutils. Medir bien y accionar mal.
|
# la Etapa C, que reemplaza busybox por uutils. Medir bien y accionar mal.
|
||||||
concedidos = set()
|
concedidos = set()
|
||||||
@@ -142,7 +142,7 @@ def main():
|
|||||||
# El store es autoritativo: sabe qué ficheros aporta cada artefacto.
|
# El store es autoritativo: sabe qué ficheros aporta cada artefacto.
|
||||||
declarable[p] = sorted({nombre_de(a) for a in provs})
|
declarable[p] = sorted({nombre_de(a) for a in provs})
|
||||||
elif os.path.basename(p) in recetas:
|
elif os.path.basename(p) in recetas:
|
||||||
# Respaldo por catálogo: el artefacto no está construido AQUÍ, pero hammer sabe
|
# Respaldo por catálogo: el artefacto no está construido AQUÍ, pero takana sabe
|
||||||
# construirlo. Es declarable igual — la deuda es de la receta, no del disco.
|
# construirlo. Es declarable igual — la deuda es de la receta, no del disco.
|
||||||
#
|
#
|
||||||
# OJO, heurística por NOMBRE y por eso sólo un respaldo: acierta con `make`, pero
|
# OJO, heurística por NOMBRE y por eso sólo un respaldo: acierta con `make`, pero
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# harkaq-trace-build.sh — orquestador del PILOTO de traza positiva (plan-freebsd T1.1+T1.3).
|
# harkaq-trace-build.sh — orquestador del PILOTO de traza positiva (plan-freebsd T1.1+T1.3).
|
||||||
#
|
#
|
||||||
# Envuelve UN `hammer build` con harkaq-trace enganchado al overlay de CADA fase: un bwrap
|
# Envuelve UN `takana build` con harkaq-trace enganchado al overlay de CADA fase: un bwrap
|
||||||
# por fase ⇒ una traza por fase — la misma granularidad que el veredicto de harkaq. El
|
# por fase ⇒ una traza por fase — la misma granularidad que el veredicto de harkaq. El
|
||||||
# tracer marca `/proc/<pid-bwrap>/root`: el magic-link cae en el SB del OVERLAY, que es el
|
# tracer marca `/proc/<pid-bwrap>/root`: el magic-link cae en el SB del OVERLAY, que es el
|
||||||
# único lugar desde donde los reads del build se ven (la marca sobre el fs del host NO los
|
# único lugar desde donde los reads del build se ven (la marca sobre el fs del host NO los
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
# función que usan `build-state.py` y `vigia-imagen.py`. Si el perfil cambia, esto cambia solo.
|
# función que usan `build-state.py` y `vigia-imagen.py`. Si el perfil cambia, esto cambia solo.
|
||||||
#
|
#
|
||||||
# ══ EL ARTEFACTO SE ELIGE POR HASH, NO POR FECHA ═══════════════════════════════════════════════
|
# ══ EL ARTEFACTO SE ELIGE POR HASH, NO POR FECHA ═══════════════════════════════════════════════
|
||||||
# `hammer hash <receta>` da el ArtifactHash de la receta de HOY sin construir. Con dos artefactos
|
# `takana hash <receta>` da el ArtifactHash de la receta de HOY sin construir. Con dos artefactos
|
||||||
# del mismo paquete conviviendo en el store —lo normal tras cualquier re-hash— el más reciente
|
# del mismo paquete conviviendo en el store —lo normal tras cualquier re-hash— el más reciente
|
||||||
# puede ser el viejo. La fecha miente; el hash no.
|
# puede ser el viejo. La fecha miente; el hash no.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -11,20 +11,20 @@
|
|||||||
# LoadOptions VACÍO ⇒ el kernel usa ese cmdline horneado ⇒ el EFI-stub carga \initramfs.cpio.gz desde la
|
# LoadOptions VACÍO ⇒ el kernel usa ese cmdline horneado ⇒ el EFI-stub carga \initramfs.cpio.gz desde la
|
||||||
# MISMA ESP y corre /init. (En un boot con bootloader que sí pasa LoadOptions, el horneado se ignora.)
|
# MISMA ESP y corre /init. (En un boot con bootloader que sí pasa LoadOptions, el horneado se ignora.)
|
||||||
#
|
#
|
||||||
# El initramfs es MÍNIMO — sólo pivota: findfs LABEL=hammer-root → switch_root a la ext4 real. Ese
|
# El initramfs es MÍNIMO — sólo pivota: findfs LABEL=takana-root → switch_root a la ext4 real. Ese
|
||||||
# "initrd chico" es lo que destraba EFI-stub directo (ADR 0010 paso 2: el cuelgue del metal era por un
|
# "initrd chico" es lo que destraba EFI-stub directo (ADR 0010 paso 2: el cuelgue del metal era por un
|
||||||
# initrd de 100MB). El sistema real vive en las particiones ext4, no en RAM.
|
# initrd de 100MB). El sistema real vive en las particiones ext4, no en RAM.
|
||||||
#
|
#
|
||||||
# Layout (GPT, UEFI):
|
# Layout (GPT, UEFI):
|
||||||
# p1 ESP FAT32 [EFI System Partition] \EFI\BOOT\BOOTX64.EFI (=bzImage) + \initramfs.cpio.gz
|
# p1 ESP FAT32 [EFI System Partition] \EFI\BOOT\BOOTX64.EFI (=bzImage) + \initramfs.cpio.gz
|
||||||
# p2 / ext4 [hammer-root] el rootfs real del producto (/sbin/init → arje-zero)
|
# p2 / ext4 [takana-root] el rootfs real del producto (/sbin/init → arje-zero)
|
||||||
# p3 /store ext4 [hammer-store]
|
# p3 /store ext4 [takana-store]
|
||||||
# p4 /var/lib/hammer ext4 [hammer-state]
|
# p4 /var/lib/hammer ext4 [takana-state]
|
||||||
#
|
#
|
||||||
# Cadena de arranque del disco: firmware UEFI → \EFI\BOOT\BOOTX64.EFI (EFI-stub) → initramfs pivote
|
# Cadena de arranque del disco: firmware UEFI → \EFI\BOOT\BOOTX64.EFI (EFI-stub) → initramfs pivote
|
||||||
# (findfs LABEL=hammer-root → switch_root) → /sbin/init real → arje-zero PID1.
|
# (findfs LABEL=takana-root → switch_root) → /sbin/init real → arje-zero PID1.
|
||||||
#
|
#
|
||||||
# La ESP se puebla con el mtools de hammer (mformat/mcopy, sin root ni loop). Las ext4 con `mke2fs -d`
|
# La ESP se puebla con el mtools de takana (mformat/mcopy, sin root ni loop). Las ext4 con `mke2fs -d`
|
||||||
# bajo `unshare -r` (ficheros root-owned sin sudo), igual que install-image.sh.
|
# bajo `unshare -r` (ficheros root-owned sin sudo), igual que install-image.sh.
|
||||||
#
|
#
|
||||||
# Uso:
|
# Uso:
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
# ROOTFS dir rootfs a instalar (default el product-rootfs más reciente del store)
|
# ROOTFS dir rootfs a instalar (default el product-rootfs más reciente del store)
|
||||||
# KERNEL bzImage EFI-stub a embeber (default store/*-linux-metal/boot/bzImage más reciente)
|
# KERNEL bzImage EFI-stub a embeber (default store/*-linux-metal/boot/bzImage más reciente)
|
||||||
# BUSYBOX busybox ESTÁTICO para el initramfs (default el del ROOTFS)
|
# BUSYBOX busybox ESTÁTICO para el initramfs (default el del ROOTFS)
|
||||||
# MTOOLS dir usr/bin de mtools de hammer (default store/*-mtools/usr/bin)
|
# MTOOLS dir usr/bin de mtools de takana (default store/*-mtools/usr/bin)
|
||||||
# IMG imagen de salida (default work/hammer-efi-disk.img)
|
# IMG imagen de salida (default work/hammer-efi-disk.img)
|
||||||
# ESP_MB MiB de la ESP FAT32 (default 64)
|
# ESP_MB MiB de la ESP FAT32 (default 64)
|
||||||
# ROOT_SIZE MiB de / (default 2048)
|
# ROOT_SIZE MiB de / (default 2048)
|
||||||
@@ -72,7 +72,7 @@ IRD_TREE="$STAGE/initramfs"
|
|||||||
ROOT_IMG="$STAGE/root.img"; STORE_IMG="$STAGE/store.img"; STATE_IMG="$STAGE/state.img"
|
ROOT_IMG="$STAGE/root.img"; STORE_IMG="$STAGE/store.img"; STATE_IMG="$STAGE/state.img"
|
||||||
ESP_IMG="$STAGE/esp.img"; IRD="$STAGE/initramfs.cpio.gz"
|
ESP_IMG="$STAGE/esp.img"; IRD="$STAGE/initramfs.cpio.gz"
|
||||||
|
|
||||||
# --- 1) initramfs de pivote: busybox estático + /init (findfs LABEL=hammer-root → switch_root) --------
|
# --- 1) initramfs de pivote: busybox estático + /init (findfs LABEL=takana-root → switch_root) --------
|
||||||
echo "==> initramfs de pivote (busybox estático + /init switch_root a hammer-root)"
|
echo "==> initramfs de pivote (busybox estático + /init switch_root a hammer-root)"
|
||||||
mkdir -p "$IRD_TREE/bin" "$IRD_TREE/dev" "$IRD_TREE/proc" "$IRD_TREE/sys" "$IRD_TREE/newroot"
|
mkdir -p "$IRD_TREE/bin" "$IRD_TREE/dev" "$IRD_TREE/proc" "$IRD_TREE/sys" "$IRD_TREE/newroot"
|
||||||
cp "$BUSYBOX" "$IRD_TREE/bin/busybox"; chmod 0755 "$IRD_TREE/bin/busybox"
|
cp "$BUSYBOX" "$IRD_TREE/bin/busybox"; chmod 0755 "$IRD_TREE/bin/busybox"
|
||||||
@@ -141,8 +141,8 @@ echo "==> staging root (hardlinks del rootfs, sin /store ni /var/lib/hammer)"
|
|||||||
cp -al "$ROOTFS" "$ROOT_TREE"
|
cp -al "$ROOTFS" "$ROOT_TREE"
|
||||||
rm -rf "$ROOT_TREE/store" "$ROOT_TREE/var/lib/hammer"
|
rm -rf "$ROOT_TREE/store" "$ROOT_TREE/var/lib/hammer"
|
||||||
mkdir -p "$ROOT_TREE/store" "$ROOT_TREE/var/lib/hammer"
|
mkdir -p "$ROOT_TREE/store" "$ROOT_TREE/var/lib/hammer"
|
||||||
# CLI `hammer` (static musl) para el menú de arranque por grafo (ADR 0010): el hook de init lo invoca
|
# CLI `takana` (static musl) para el menú de arranque por grafo (ADR 0010): el hook de init lo invoca
|
||||||
# como `hammer boot menu`. El producto trae arje-zero/hammerd pero NO el CLI ⇒ lo inyectamos acá si
|
# como `takana boot menu`. El producto trae arje-zero/hammerd pero NO el CLI ⇒ lo inyectamos acá si
|
||||||
# está compilado (igual patrón que hammer-recover). Opcional: sin él, el wrapper saltea el menú.
|
# está compilado (igual patrón que hammer-recover). Opcional: sin él, el wrapper saltea el menú.
|
||||||
HAMMER_MUSL="${TAKANA_MUSL:-${HAMMER_MUSL:-$ROOT/target/x86_64-unknown-linux-musl/release/hammer}}"
|
HAMMER_MUSL="${TAKANA_MUSL:-${HAMMER_MUSL:-$ROOT/target/x86_64-unknown-linux-musl/release/hammer}}"
|
||||||
if [ -x "$HAMMER_MUSL" ]; then
|
if [ -x "$HAMMER_MUSL" ]; then
|
||||||
@@ -178,7 +178,7 @@ exec /usr/bin/arje-zero
|
|||||||
RINIT
|
RINIT
|
||||||
chmod +x "$ROOT_TREE/sbin/init"
|
chmod +x "$ROOT_TREE/sbin/init"
|
||||||
|
|
||||||
# --- 3) ESP FAT32: BOOTX64.EFI (=bzImage EFI-stub) + initramfs.cpio.gz, poblada con mtools de hammer ---
|
# --- 3) ESP FAT32: BOOTX64.EFI (=bzImage EFI-stub) + initramfs.cpio.gz, poblada con mtools de takana ---
|
||||||
echo "==> ESP FAT32 (${ESP_MB}M): \\EFI\\BOOT\\BOOTX64.EFI (=bzImage) + \\initramfs.cpio.gz"
|
echo "==> ESP FAT32 (${ESP_MB}M): \\EFI\\BOOT\\BOOTX64.EFI (=bzImage) + \\initramfs.cpio.gz"
|
||||||
rm -f "$ESP_IMG"; truncate -s "$(( ESP_MB * 1024 * 1024 ))" "$ESP_IMG"
|
rm -f "$ESP_IMG"; truncate -s "$(( ESP_MB * 1024 * 1024 ))" "$ESP_IMG"
|
||||||
"$MTOOLS/mformat" -F -v HAMMER -i "$ESP_IMG" ::
|
"$MTOOLS/mformat" -F -v HAMMER -i "$ESP_IMG" ::
|
||||||
@@ -187,7 +187,7 @@ rm -f "$ESP_IMG"; truncate -s "$(( ESP_MB * 1024 * 1024 ))" "$ESP_IMG"
|
|||||||
"$MTOOLS/mcopy" -i "$ESP_IMG" "$IRD" ::/initramfs.cpio.gz
|
"$MTOOLS/mcopy" -i "$ESP_IMG" "$IRD" ::/initramfs.cpio.gz
|
||||||
"$MTOOLS/mdir" -i "$ESP_IMG" ::/EFI/BOOT 2>/dev/null | grep -iE 'BOOTX64|initram' || true
|
"$MTOOLS/mdir" -i "$ESP_IMG" ::/EFI/BOOT 2>/dev/null | grep -iE 'BOOTX64|initram' || true
|
||||||
|
|
||||||
# --- 4) GPT: p1=ESP, p2=hammer-root, p3=hammer-store, p4=hammer-state --------------------------------
|
# --- 4) GPT: p1=ESP, p2=takana-root, p3=takana-store, p4=takana-state --------------------------------
|
||||||
SECT_MIB=2048
|
SECT_MIB=2048
|
||||||
ESP_SECT=$(( ESP_MB * SECT_MIB ))
|
ESP_SECT=$(( ESP_MB * SECT_MIB ))
|
||||||
ROOT_SECT=$(( ROOT_SIZE * SECT_MIB ))
|
ROOT_SECT=$(( ROOT_SIZE * SECT_MIB ))
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
#
|
#
|
||||||
# Layout (GPT, BIOS):
|
# Layout (GPT, BIOS):
|
||||||
# /dev/vda1 BIOS boot (ef02, ~2 MiB, sin fs) core.img de GRUB
|
# /dev/vda1 BIOS boot (ef02, ~2 MiB, sin fs) core.img de GRUB
|
||||||
# /dev/vda2 / ext4 [hammer-root] + /boot/bzImage + /boot/grub
|
# /dev/vda2 / ext4 [takana-root] + /boot/bzImage + /boot/grub
|
||||||
# /dev/vda3 /store ext4 [hammer-store]
|
# /dev/vda3 /store ext4 [takana-store]
|
||||||
# /dev/vda4 /var/lib/hammer ext4 [hammer-state]
|
# /dev/vda4 /var/lib/hammer ext4 [takana-state]
|
||||||
#
|
#
|
||||||
# Instalación de GRUB en USERSPACE (sin root ni loop): grub-mkimage arma core.img; grub-bios-setup
|
# Instalación de GRUB en USERSPACE (sin root ni loop): grub-mkimage arma core.img; grub-bios-setup
|
||||||
# escribe boot.img→MBR + core.img→partición BIOS sobre el fichero imagen (I/O de bloques). Los módulos
|
# escribe boot.img→MBR + core.img→partición BIOS sobre el fichero imagen (I/O de bloques). Los módulos
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#
|
#
|
||||||
# Target IN-PLACE (Etapa E2): si IMG es un block device (o PREALLOC=1 sobre un fichero pre-dimensionado),
|
# Target IN-PLACE (Etapa E2): si IMG es un block device (o PREALLOC=1 sobre un fichero pre-dimensionado),
|
||||||
# se instala EN SITIO — no se trunca ni se borra el nodo, sólo se valida capacidad. Esa es la base de
|
# se instala EN SITIO — no se trunca ni se borra el nodo, sólo se valida capacidad. Esa es la base de
|
||||||
# `hammer install /dev/sdX` (ver scripts/hammer-install.sh): misma lógica, apuntando a un disco real.
|
# `takana install /dev/sdX` (ver scripts/hammer-install.sh): misma lógica, apuntando a un disco real.
|
||||||
#
|
#
|
||||||
# Variables:
|
# Variables:
|
||||||
# ROOTFS dir rootfs a empaquetar (default work/builder-rootfs)
|
# ROOTFS dir rootfs a empaquetar (default work/builder-rootfs)
|
||||||
@@ -109,7 +109,7 @@ START4=$(( START3 + STORE_SECT ))
|
|||||||
TOTAL_SECT=$(( START4 + STATE_SECT + 2048 ))
|
TOTAL_SECT=$(( START4 + STATE_SECT + 2048 ))
|
||||||
BIOS_GUID="21686148-6449-6E6F-744E-656564454649" # GPT "BIOS boot partition"
|
BIOS_GUID="21686148-6449-6E6F-744E-656564454649" # GPT "BIOS boot partition"
|
||||||
|
|
||||||
# Target = block device (instalación in-place, Etapa E2 `hammer install /dev/sdX`) o fichero imagen.
|
# Target = block device (instalación in-place, Etapa E2 `takana install /dev/sdX`) o fichero imagen.
|
||||||
# Un device tiene tamaño fijo: NO se trunca ni se borra el nodo; se valida capacidad. PREALLOC=1 fuerza
|
# Un device tiene tamaño fijo: NO se trunca ni se borra el nodo; se valida capacidad. PREALLOC=1 fuerza
|
||||||
# este modo sobre un fichero pre-dimensionado (para probar el camino de device sin hardware real).
|
# este modo sobre un fichero pre-dimensionado (para probar el camino de device sin hardware real).
|
||||||
TOTAL_BYTES=$(( TOTAL_SECT * 512 ))
|
TOTAL_BYTES=$(( TOTAL_SECT * 512 ))
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# iso-boot-test.sh — valida E5 (medio live): arma el ISO 9660 / El Torito con scripts/iso-image.sh y lo
|
# iso-boot-test.sh — valida E5 (medio live): arma el ISO 9660 / El Torito con scripts/iso-image.sh y lo
|
||||||
# arranca en QEMU desde el CD (sin -kernel ni disco), comprobando que la cadena El Torito → GRUB →
|
# arranca en QEMU desde el CD (sin -kernel ni disco), comprobando que la cadena El Torito → GRUB →
|
||||||
# kernel → initramfs → /init → producto funciona ENTERA desde RAM. El xorriso que arma el ISO es el
|
# kernel → initramfs → /init → producto funciona ENTERA desde RAM. El xorriso que arma el ISO es el
|
||||||
# construido por hammer (recipes/xorriso.toml), así que el test dogfooda también esa receta.
|
# construido por takana (recipes/xorriso.toml), así que el test dogfooda también esa receta.
|
||||||
#
|
#
|
||||||
# Asserts: (1) GRUB arrancó del El Torito; (2) el marcador del /init live; (3) arje-zero PID1 vivo;
|
# Asserts: (1) GRUB arrancó del El Torito; (2) el marcador del /init live; (3) arje-zero PID1 vivo;
|
||||||
# (4) sshd escuchando — i.e. el PRODUCTO llega a servicio corriendo enteramente desde el medio live.
|
# (4) sshd escuchando — i.e. el PRODUCTO llega a servicio corriendo enteramente desde el medio live.
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
# A diferencia de install-image.sh (E1, disco GPT con / persistente en vda2), un medio live arranca
|
# A diferencia de install-image.sh (E1, disco GPT con / persistente en vda2), un medio live arranca
|
||||||
# ENTERO desde RAM: GRUB (El Torito) carga kernel + initramfs desde el ISO 9660, el kernel desempaqueta
|
# ENTERO desde RAM: GRUB (El Torito) carga kernel + initramfs desde el ISO 9660, el kernel desempaqueta
|
||||||
# el initramfs (el rootfs del producto) a un tmpfs y corre /init — sin tocar disco. Es el medio para
|
# el initramfs (el rootfs del producto) a un tmpfs y corre /init — sin tocar disco. Es el medio para
|
||||||
# correr el instalador (`hammer install /dev/sdX`) en hardware nuevo, o para probar el sistema sin
|
# correr el instalador (`takana install /dev/sdX`) en hardware nuevo, o para probar el sistema sin
|
||||||
# instalarlo.
|
# instalarlo.
|
||||||
#
|
#
|
||||||
# El ISO lo ARMA `xorriso` construido por hammer desde fuente (recipes/xorriso.toml) — el host no lo
|
# El ISO lo ARMA `xorriso` construido por takana desde fuente (recipes/xorriso.toml) — el host no lo
|
||||||
# trae. La cadena de boot BIOS reusa los módulos GRUB i386-pc de E1, pero con el core El Torito
|
# trae. La cadena de boot BIOS reusa los módulos GRUB i386-pc de E1, pero con el core El Torito
|
||||||
# (formato i386-pc-eltorito + iso9660) en vez del core de disco (ext2 + biosdisk).
|
# (formato i386-pc-eltorito + iso9660) en vez del core de disco (ext2 + biosdisk).
|
||||||
#
|
#
|
||||||
@@ -37,10 +37,10 @@ KERNEL="${KERNEL:-$(ls store/*-linux/boot/bzImage 2>/dev/null | head -1)}"
|
|||||||
GRUB_LIB="${GRUB_LIB:-/usr/lib/grub/i386-pc}"
|
GRUB_LIB="${GRUB_LIB:-/usr/lib/grub/i386-pc}"
|
||||||
GRUB_EFI_LIB="${GRUB_EFI_LIB:-/usr/lib/grub/x86_64-efi}"
|
GRUB_EFI_LIB="${GRUB_EFI_LIB:-/usr/lib/grub/x86_64-efi}"
|
||||||
CMDLINE="${CMDLINE:-console=ttyS0 rdinit=/init}"
|
CMDLINE="${CMDLINE:-console=ttyS0 rdinit=/init}"
|
||||||
# xorriso: preferimos el construido por hammer (dogfooding de recipes/xorriso.toml); fallback al host.
|
# xorriso: preferimos el construido por takana (dogfooding de recipes/xorriso.toml); fallback al host.
|
||||||
XORRISO="${XORRISO:-$(ls store/*-xorriso/usr/bin/xorriso 2>/dev/null | head -1)}"
|
XORRISO="${XORRISO:-$(ls store/*-xorriso/usr/bin/xorriso 2>/dev/null | head -1)}"
|
||||||
[ -n "$XORRISO" ] && [ -x "$XORRISO" ] || XORRISO="$(command -v xorriso 2>/dev/null || true)"
|
[ -n "$XORRISO" ] && [ -x "$XORRISO" ] || XORRISO="$(command -v xorriso 2>/dev/null || true)"
|
||||||
# mtools (mformat/mcopy): para poblar la ESP FAT del arranque EFI. Preferimos el de hammer (dogfooding).
|
# mtools (mformat/mcopy): para poblar la ESP FAT del arranque EFI. Preferimos el de takana (dogfooding).
|
||||||
MTOOLS_DIR="${MTOOLS_DIR:-$(ls -d store/*-mtools/usr/bin 2>/dev/null | head -1)}"
|
MTOOLS_DIR="${MTOOLS_DIR:-$(ls -d store/*-mtools/usr/bin 2>/dev/null | head -1)}"
|
||||||
|
|
||||||
[ -d "$ROOTFS" ] || { echo "no existe ROOTFS: $ROOTFS" >&2; exit 1; }
|
[ -d "$ROOTFS" ] || { echo "no existe ROOTFS: $ROOTFS" >&2; exit 1; }
|
||||||
@@ -103,7 +103,7 @@ if [ "${INSTALLER:-0}" = 1 ]; then
|
|||||||
cp "$KERNEL" "$IPL/kernel/bzImage"; chmod 0644 "$IPL/kernel/bzImage"
|
cp "$KERNEL" "$IPL/kernel/bzImage"; chmod 0644 "$IPL/kernel/bzImage"
|
||||||
# Rama EFI del instalador (ADR 0010 paso 5): el kernel `linux-metal` hornea CONFIG_CMDLINE con
|
# Rama EFI del instalador (ADR 0010 paso 5): el kernel `linux-metal` hornea CONFIG_CMDLINE con
|
||||||
# initrd=/initramfs.cpio.gz rdinit=/init ⇒ arranca por EFI-stub como \EFI\BOOT\BOOTX64.EFI sin
|
# initrd=/initramfs.cpio.gz rdinit=/init ⇒ arranca por EFI-stub como \EFI\BOOT\BOOTX64.EFI sin
|
||||||
# bootloader. Lo bundleamos junto al genérico; hammer-install lo usa si el live corre en UEFI.
|
# bootloader. Lo bundleamos junto al genérico; takana-install lo usa si el live corre en UEFI.
|
||||||
EFI_KERNEL="${EFI_KERNEL:-$(ls -dt store/*-linux-metal/boot/bzImage 2>/dev/null | head -1)}"
|
EFI_KERNEL="${EFI_KERNEL:-$(ls -dt store/*-linux-metal/boot/bzImage 2>/dev/null | head -1)}"
|
||||||
if [ -n "${EFI_KERNEL:-}" ] && [ -r "$EFI_KERNEL" ]; then
|
if [ -n "${EFI_KERNEL:-}" ] && [ -r "$EFI_KERNEL" ]; then
|
||||||
cp "$EFI_KERNEL" "$IPL/kernel/bzImage-efi"; chmod 0644 "$IPL/kernel/bzImage-efi"
|
cp "$EFI_KERNEL" "$IPL/kernel/bzImage-efi"; chmod 0644 "$IPL/kernel/bzImage-efi"
|
||||||
@@ -125,9 +125,9 @@ if [ "${INSTALLER:-0}" = 1 ]; then
|
|||||||
fi
|
fi
|
||||||
[ -x "$RECOVER_BIN" ] || { echo "no pude construir hammer-recover (target musl?)" >&2; exit 1; }
|
[ -x "$RECOVER_BIN" ] || { echo "no pude construir hammer-recover (target musl?)" >&2; exit 1; }
|
||||||
install -m 0755 "$RECOVER_BIN" "$IPL/hammer-recover"
|
install -m 0755 "$RECOVER_BIN" "$IPL/hammer-recover"
|
||||||
# CLI `hammer` (static musl) para el menú de arranque por grafo (ADR 0010): el hook de init del
|
# CLI `takana` (static musl) para el menú de arranque por grafo (ADR 0010): el hook de init del
|
||||||
# sistema instalado lo invoca como `hammer boot menu`. El producto trae arje-zero/hammerd pero NO el
|
# sistema instalado lo invoca como `takana boot menu`. El producto trae arje-zero/hammerd pero NO el
|
||||||
# CLI ⇒ lo bundleamos al payload; hammer-install lo copia a /usr/bin/hammer del disco.
|
# CLI ⇒ lo bundleamos al payload; takana-install lo copia a /usr/bin/hammer del disco.
|
||||||
HAMMER_BIN="$ROOT/target/x86_64-unknown-linux-musl/release/hammer"
|
HAMMER_BIN="$ROOT/target/x86_64-unknown-linux-musl/release/hammer"
|
||||||
if [ ! -x "$HAMMER_BIN" ]; then
|
if [ ! -x "$HAMMER_BIN" ]; then
|
||||||
echo "==> compilando hammer CLI (static musl) para el payload"
|
echo "==> compilando hammer CLI (static musl) para el payload"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# iso-install-test.sh — valida el lazo COMPLETO de instalación desde el medio live (refinamiento #1):
|
# iso-install-test.sh — valida el lazo COMPLETO de instalación desde el medio live (refinamiento #1):
|
||||||
# (1) arma un ISO instalador (iso-image.sh INSTALLER=1 AUTO_INSTALL=/dev/vda) con el payload de disco
|
# (1) arma un ISO instalador (iso-image.sh INSTALLER=1 AUTO_INSTALL=/dev/vda) con el payload de disco
|
||||||
# (kernel + GRUB MBR + /usr/bin/hammer-install) bundleado;
|
# (kernel + GRUB MBR + /usr/bin/hammer-install) bundleado;
|
||||||
# (2) lo bootea con un disco EN BLANCO ⇒ el /init desatendido corre hammer-install y apaga;
|
# (2) lo bootea con un disco EN BLANCO ⇒ el /init desatendido corre takana-install y apaga;
|
||||||
# (3) bootea ESE disco SOLO (sin ISO, sin -kernel) ⇒ el producto instalado arranca y sirve SSH.
|
# (3) bootea ESE disco SOLO (sin ISO, sin -kernel) ⇒ el producto instalado arranca y sirve SSH.
|
||||||
# Cierra el lazo "ISO live → disco instalado → bootea solo", lo que hace la distro distribuible.
|
# Cierra el lazo "ISO live → disco instalado → bootea solo", lo que hace la distro distribuible.
|
||||||
#
|
#
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@ if [ ! -x "${HARKAQ_BIN:-$HOME/.cache/harkaq}/harkaq-audit" ]; then
|
|||||||
else
|
else
|
||||||
export HARKAQ=1 HARKAQ_BIN="${HARKAQ_BIN:-$HOME/.cache/harkaq}"
|
export HARKAQ=1 HARKAQ_BIN="${HARKAQ_BIN:-$HOME/.cache/harkaq}"
|
||||||
export HARKAQ_BASE="${HARKAQ_BASE:-$HARKAQ_BIN/base.policy}" HARKAQ_TIMEOUT="${HARKAQ_TIMEOUT:-200}"
|
export HARKAQ_BASE="${HARKAQ_BASE:-$HARKAQ_BIN/base.policy}" HARKAQ_TIMEOUT="${HARKAQ_TIMEOUT:-200}"
|
||||||
# Nombre ÚNICO por corrida: con uno fijo, la 2ª vez `hammer build` pega en CACHÉ, no
|
# Nombre ÚNICO por corrida: con uno fijo, la 2ª vez `takana build` pega en CACHÉ, no
|
||||||
# construye nada, no hay veredictos y el juez dice "sin evidencia" — un falso negativo que
|
# construye nada, no hay veredictos y el juez dice "sin evidencia" — un falso negativo que
|
||||||
# parece un problema de la receta. (Gotcha conocido; me mordió al probar el juez.)
|
# parece un problema de la receta. (Gotcha conocido; me mordió al probar el juez.)
|
||||||
uniq="$n-juez-$$"
|
uniq="$n-juez-$$"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# complete-closure.sh — completa el cierre RUNTIME de un FHS hidratado: escanea los `NEEDED` (DT_NEEDED)
|
# complete-closure.sh — completa el cierre RUNTIME de un FHS hidratado: escanea los `NEEDED` (DT_NEEDED)
|
||||||
# de cada ELF del rootfs y, por cada soname AUSENTE, proyecta del store SELLADO el artefacto que lo
|
# de cada ELF del rootfs y, por cada soname AUSENTE, proyecta del store SELLADO el artefacto que lo
|
||||||
# provee (`hammer hydrate`). Itera hasta punto fijo. Resuelve las deps runtime que el índice del repo NO
|
# provee (`takana hydrate`). Itera hasta punto fijo. Resuelve las deps runtime que el índice del repo NO
|
||||||
# lista (p.ej. libmount.so.1 de util-linux, dep de build de kcoreaddons pero .so runtime de libKF6CoreAddons).
|
# lista (p.ej. libmount.so.1 de util-linux, dep de build de kcoreaddons pero .so runtime de libKF6CoreAddons).
|
||||||
#
|
#
|
||||||
# Sonames del SUSTRATO base (musl libc, loader, libgcc) NO se hidratan: los provee la base soberana del
|
# Sonames del SUSTRATO base (musl libc, loader, libgcc) NO se hidratan: los provee la base soberana del
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# hydrate-fhs.sh — hidrata un FHS runtime KDE desde el repo firmado, instalando el CIERRE completo.
|
# hydrate-fhs.sh — hidrata un FHS runtime KDE desde el repo firmado, instalando el CIERRE completo.
|
||||||
#
|
#
|
||||||
# `hammer install <pkg> --prefix P` sólo hidrata los archivos de <pkg>, NO de su cierre. Para un
|
# `takana install <pkg> --prefix P` sólo hidrata los archivos de <pkg>, NO de su cierre. Para un
|
||||||
# rootfs runtime usable (que capture todas las `.so`), hay que instalar cada paquete del cierre en el
|
# rootfs runtime usable (que capture todas las `.so`), hay que instalar cada paquete del cierre en el
|
||||||
# MISMO prefix (igual que product-userland-from-repo.sh). El store del worker está caliente ⇒ cache-hit.
|
# MISMO prefix (igual que product-userland-from-repo.sh). El store del worker está caliente ⇒ cache-hit.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# hydrate-from-store.sh — hidrata un FHS runtime KDE PROYECTANDO artefactos SELLADOS del store, SIN
|
# hydrate-from-store.sh — hidrata un FHS runtime KDE PROYECTANDO artefactos SELLADOS del store, SIN
|
||||||
# reproduce ni rebuild (`hammer hydrate <hash> --into`). Es la vía correcta para el escritorio completo:
|
# reproduce ni rebuild (`takana hydrate <hash> --into`). Es la vía correcta para el escritorio completo:
|
||||||
# `install` reproduce-desde-fuente y el hashing determinista es frágil bajo el régimen dinámico (cada
|
# `install` reproduce-desde-fuente y el hashing determinista es frágil bajo el régimen dinámico (cada
|
||||||
# consumidor puede recomputar un hash distinto de qtbase → rebuild). Aquí se toma la salida ya sellada
|
# consumidor puede recomputar un hash distinto de qtbase → rebuild). Aquí se toma la salida ya sellada
|
||||||
# por la granja.
|
# por la granja.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# NVIDIA Pascal/nouveau) con render por SOFTWARE (mesa-llvmpipe soberano). USB "live" que se adapta a la
|
# NVIDIA Pascal/nouveau) con render por SOFTWARE (mesa-llvmpipe soberano). USB "live" que se adapta a la
|
||||||
# máquina donde se bootee. Ver [[kde-metal-qemu-desktop]] y el runbook docs/runbooks/kde-qemu-desktop.md.
|
# máquina donde se bootee. Ver [[kde-metal-qemu-desktop]] y el runbook docs/runbooks/kde-qemu-desktop.md.
|
||||||
#
|
#
|
||||||
# Por qué software y no iris/nouveau HW: el mesa hammer-built es swrast/llvmpipe; una mesa HW con nouveau
|
# Por qué software y no iris/nouveau HW: el mesa takana-built es swrast/llvmpipe; una mesa HW con nouveau
|
||||||
# hoy sólo existe como binario Alpine (rompe soberanía). llvmpipe sobre el KMS del kernel (i915 O nouveau)
|
# hoy sólo existe como binario Alpine (rompe soberanía). llvmpipe sobre el KMS del kernel (i915 O nouveau)
|
||||||
# funciona idéntico en ambas máquinas y reusa los fixes ya validados. HW-accel = iteración siguiente.
|
# funciona idéntico en ambas máquinas y reusa los fixes ya validados. HW-accel = iteración siguiente.
|
||||||
#
|
#
|
||||||
@@ -116,7 +116,7 @@ PY
|
|||||||
rm -f "$MERGED/etc/motd" # romper el hardlink: `cat >` escribiría el inodo COMPARTIDO con work/metal-rootfs
|
rm -f "$MERGED/etc/motd" # romper el hardlink: `cat >` escribiría el inodo COMPARTIDO con work/metal-rootfs
|
||||||
cat > "$MERGED/etc/motd" <<'MOTD'
|
cat > "$MERGED/etc/motd" <<'MOTD'
|
||||||
|
|
||||||
#-- hammer :: escritorio KDE Plasma 6 (metal, dual-GPU software) ------------
|
#-- takana :: escritorio KDE Plasma 6 (metal, dual-GPU software) ------------
|
||||||
Render por software (llvmpipe soberano) sobre i915 (Intel) o nouveau (NVIDIA).
|
Render por software (llvmpipe soberano) sobre i915 (Intel) o nouveau (NVIDIA).
|
||||||
|
|
||||||
Arrancar el escritorio: plasma-start
|
Arrancar el escritorio: plasma-start
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ chmod 1777 "$MERGED/tmp"
|
|||||||
# motd: que el usuario sepa qué correr al llegar al shell.
|
# motd: que el usuario sepa qué correr al llegar al shell.
|
||||||
cat > "$MERGED/etc/motd" <<'MOTD'
|
cat > "$MERGED/etc/motd" <<'MOTD'
|
||||||
|
|
||||||
#-- hammer :: escritorio KDE Plasma 6 (metal) ------------------------------
|
#-- takana :: escritorio KDE Plasma 6 (metal) ------------------------------
|
||||||
Todo construido desde fuente con hammer (musl + zig-cc), sin binarios ajenos.
|
Todo construido desde fuente con hammer (musl + zig-cc), sin binarios ajenos.
|
||||||
|
|
||||||
Arrancar el escritorio: plasma-start
|
Arrancar el escritorio: plasma-start
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ echo "==> inyectando musl (loader + libc) — los binarios KDE son dinámicos"
|
|||||||
# La base metal es 100% ESTÁTICA (arje-zero+busybox) y el KDE-rootfs no trae libc ⇒ el merge no tiene
|
# La base metal es 100% ESTÁTICA (arje-zero+busybox) y el KDE-rootfs no trae libc ⇒ el merge no tiene
|
||||||
# loader musl. Los binarios KDE piden interp /lib/ld-musl-x86_64.so.1 + NEEDED libc.so (única lib base
|
# loader musl. Los binarios KDE piden interp /lib/ld-musl-x86_64.so.1 + NEEDED libc.so (única lib base
|
||||||
# que falta; el resto del closure Qt/KF6 está). Copiamos el musl soberano del host (mismo que corre la
|
# que falta; el resto del closure Qt/KF6 está). Copiamos el musl soberano del host (mismo que corre la
|
||||||
# mirada del laptop ⇒ ejecuta binarios hammer-musl dinámicos). En musl el loader ES libc (mismo fichero).
|
# mirada del laptop ⇒ ejecuta binarios takana-musl dinámicos). En musl el loader ES libc (mismo fichero).
|
||||||
MUSL="${MUSL:-/usr/lib/musl/lib/libc.so}"
|
MUSL="${MUSL:-/usr/lib/musl/lib/libc.so}"
|
||||||
[ -r "$MUSL" ] || { echo "no encuentro musl libc ($MUSL) — set MUSL=" >&2; exit 1; }
|
[ -r "$MUSL" ] || { echo "no encuentro musl libc ($MUSL) — set MUSL=" >&2; exit 1; }
|
||||||
mkdir -p "$MERGED/usr/lib/musl/lib" "$MERGED/lib"
|
mkdir -p "$MERGED/usr/lib/musl/lib" "$MERGED/lib"
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
# `scripts/vigia-sonames.py` («mesa y wayland pidiendo expat y libffi»), visto desde el lado de la
|
# `scripts/vigia-sonames.py` («mesa y wayland pidiendo expat y libffi»), visto desde el lado de la
|
||||||
# imagen: el cierre de BUILD no es el cierre de RUNTIME.
|
# imagen: el cierre de BUILD no es el cierre de RUNTIME.
|
||||||
#
|
#
|
||||||
# El artefacto se elige por `hammer hash` sobre la receta —el de la receta de HOY—, no por el más
|
# El artefacto se elige por `takana hash` sobre la receta —el de la receta de HOY—, no por el más
|
||||||
# reciente del store: con dos artefactos del mismo paquete conviviendo, la fecha no dice cuál rige.
|
# reciente del store: con dos artefactos del mismo paquete conviviendo, la fecha no dice cuál rige.
|
||||||
# Mismo criterio que `pid1-desde-store.sh` y que los inyectores de arje-*-compat.
|
# Mismo criterio que `pid1-desde-store.sh` y que los inyectores de arje-*-compat.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
# **si algo del rootfs tiene receta, la imagen lo toma del artefacto sellado, no de la copia
|
# **si algo del rootfs tiene receta, la imagen lo toma del artefacto sellado, no de la copia
|
||||||
# congelada.**
|
# congelada.**
|
||||||
#
|
#
|
||||||
# El artefacto se elige por `hammer hash` sobre la receta —el que corresponde a la receta de HOY—, no
|
# El artefacto se elige por `takana hash` sobre la receta —el que corresponde a la receta de HOY—, no
|
||||||
# por el más reciente del store: con dos artefactos del mismo paquete conviviendo, la fecha miente.
|
# por el más reciente del store: con dos artefactos del mismo paquete conviviendo, la fecha miente.
|
||||||
# Mismo criterio que ya usaban los inyectores de arje-logind-compat y arje-polkit-compat.
|
# Mismo criterio que ya usaban los inyectores de arje-logind-compat y arje-polkit-compat.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
# licencias-rootfs.sh — mete los textos de licencia en un rootfs y VETA el que no cumpla.
|
# licencias-rootfs.sh — mete los textos de licencia en un rootfs y VETA el que no cumpla.
|
||||||
#
|
#
|
||||||
# ── EL PUNTO DE ENTREGA ES LA IMAGEN, NO EL PAQUETE ────────────────────────────────────────────
|
# ── EL PUNTO DE ENTREGA ES LA IMAGEN, NO EL PAQUETE ────────────────────────────────────────────
|
||||||
# El canal de paquetes de hammer no distribuye binarios: `pack` produce un `.swm` (receta de
|
# El canal de paquetes de takana no distribuye binarios: `pack` produce un `.swm` (receta de
|
||||||
# transformación sobre fuente pública, «NUNCA transporta binarios cocidos») e `install` REPRODUCE
|
# transformación sobre fuente pública, «NUNCA transporta binarios cocidos») e `install` REPRODUCE
|
||||||
# construyendo con cache-hit del corpus. Donde sí se le entrega un binario a alguien es en la
|
# construyendo con cache-hit del corpus. Donde sí se le entrega un binario a alguien es en la
|
||||||
# **imagen instalable**, cuyo rootfs se puebla con `hammer install` sobre un prefix. Por eso la
|
# **imagen instalable**, cuyo rootfs se puebla con `takana install` sobre un prefix. Por eso la
|
||||||
# obligación de acompañar-el-binario-con-su-licencia se cumple ACÁ. (El SDD 19/20 decía «inyectar en
|
# obligación de acompañar-el-binario-con-su-licencia se cumple ACÁ. (El SDD 19/20 decía «inyectar en
|
||||||
# `hammer pack`»; era una lectura equivocada de por dónde salen los binarios.)
|
# `takana pack`»; era una lectura equivocada de por dónde salen los binarios.)
|
||||||
#
|
#
|
||||||
# ── LO QUE HACE ────────────────────────────────────────────────────────────────────────────────
|
# ── LO QUE HACE ────────────────────────────────────────────────────────────────────────────────
|
||||||
# Para cada paquete del rootfs escribe `/usr/share/licenses/<pkg>/`: el texto canónico de cada
|
# Para cada paquete del rootfs escribe `/usr/share/licenses/<pkg>/`: el texto canónico de cada
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
# informes por imagen); el TEXTO es lo que hay que entregar.
|
# informes por imagen); el TEXTO es lo que hay que entregar.
|
||||||
#
|
#
|
||||||
# ── ⚠ DÓNDE SE ENTREGA, QUE NO ES DONDE YO CREÍA ───────────────────────────────────────────────
|
# ── ⚠ DÓNDE SE ENTREGA, QUE NO ES DONDE YO CREÍA ───────────────────────────────────────────────
|
||||||
# El SDD 19/20 decía «inyectar el texto en `hammer pack`». **Está mal, y por una razón de fondo**:
|
# El SDD 19/20 decía «inyectar el texto en `takana pack`». **Está mal, y por una razón de fondo**:
|
||||||
# `pack` produce un `.swm`, que es una RECETA DE TRANSFORMACIÓN sobre fuente pública y —por diseño
|
# `pack` produce un `.swm`, que es una RECETA DE TRANSFORMACIÓN sobre fuente pública y —por diseño
|
||||||
# explícito— «NUNCA transporta binarios cocidos»; e `install` REPRODUCE construyendo, con cache-hit
|
# explícito— «NUNCA transporta binarios cocidos»; e `install` REPRODUCE construyendo, con cache-hit
|
||||||
# del corpus, en vez de bajar binarios. O sea que el canal de paquetes de hammer **no distribuye
|
# del corpus, en vez de bajar binarios. O sea que el canal de paquetes de takana **no distribuye
|
||||||
# binarios**, y la obligación de acompañar-el-binario ahí casi no aplica.
|
# binarios**, y la obligación de acompañar-el-binario ahí casi no aplica.
|
||||||
#
|
#
|
||||||
# Donde SÍ aplica, y con toda su fuerza, es en **las IMÁGENES INSTALABLES**: el rootfs se puebla con
|
# Donde SÍ aplica, y con toda su fuerza, es en **las IMÁGENES INSTALABLES**: el rootfs se puebla con
|
||||||
# `hammer install` sobre un prefix y de ahí sale un USB/ISO lleno de binarios que se le da a alguien.
|
# `takana install` sobre un prefix y de ahí sale un USB/ISO lleno de binarios que se le da a alguien.
|
||||||
# Ése es el punto de entrega, y por eso el consumidor de estos textos es el armado del rootfs.
|
# Ése es el punto de entrega, y por eso el consumidor de estos textos es el armado del rootfs.
|
||||||
# (La otra obligación, el espejo de FUENTES, no la toca esto y sigue pendiente: las recetas apuntan a
|
# (La otra obligación, el espejo de FUENTES, no la toca esto y sigue pendiente: las recetas apuntan a
|
||||||
# URLs de terceros que se caen.)
|
# URLs de terceros que se caen.)
|
||||||
|
|||||||
@@ -33,10 +33,10 @@
|
|||||||
#
|
#
|
||||||
# ── EL ARREGLO ESTRUCTURAL, QUE ES OTRO TICKET ──────────────────────────────────────────────────
|
# ── EL ARREGLO ESTRUCTURAL, QUE ES OTRO TICKET ──────────────────────────────────────────────────
|
||||||
# Poblar a mano tapa el agujero de hoy pero no impide que vuelva a abrirse: cada receta nueva nace
|
# Poblar a mano tapa el agujero de hoy pero no impide que vuelva a abrirse: cada receta nueva nace
|
||||||
# sin licencia. El cierre de verdad es capturarla donde ya pasa el dato gratis — hammer YA descarga y
|
# sin licencia. El cierre de verdad es capturarla donde ya pasa el dato gratis — takana YA descarga y
|
||||||
# extrae cada tarball al construir, así que la fase de fetch puede guardar el COPYING/LICENSE del
|
# extrae cada tarball al construir, así que la fase de fetch puede guardar el COPYING/LICENSE del
|
||||||
# árbol junto al artefacto, sin descargas extra. Y el texto de la licencia dentro del paquete conviene
|
# árbol junto al artefacto, sin descargas extra. Y el texto de la licencia dentro del paquete conviene
|
||||||
# inyectarlo en `hammer pack`, NO en la fase install de la receta: pack es aguas abajo del
|
# inyectarlo en `takana pack`, NO en la fase install de la receta: pack es aguas abajo del
|
||||||
# ArtifactHash, así que cumplir la GPL no cuesta reconstruir el corpus. Ver SDD 19.
|
# ArtifactHash, así que cumplir la GPL no cuesta reconstruir el corpus. Ver SDD 19.
|
||||||
#
|
#
|
||||||
# Uso: scripts/licencias.sh informe de cobertura (default, no toca nada)
|
# Uso: scripts/licencias.sh informe de cobertura (default, no toca nada)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# metal-firmware.sh — inyecta el firmware del WiFi AX201 (y reg.db) en /lib/firmware de un rootfs.
|
# metal-firmware.sh — inyecta el firmware del WiFi AX201 (y reg.db) en /lib/firmware de un rootfs.
|
||||||
#
|
#
|
||||||
# El firmware de iwlwifi son BLOBS binarios NO compilables desde fuente (Intel no libera el código); la
|
# El firmware de iwlwifi son BLOBS binarios NO compilables desde fuente (Intel no libera el código); la
|
||||||
# soberanía de hammer (build-from-source) no aplica acá — son datos fijos como el microcódigo de la CPU.
|
# soberanía de takana (build-from-source) no aplica acá — son datos fijos como el microcódigo de la CPU.
|
||||||
# Se fijan por contenido (igual que un tarball pinned): se copian de un linux-firmware ya presente y se
|
# Se fijan por contenido (igual que un tarball pinned): se copian de un linux-firmware ya presente y se
|
||||||
# descomprimen a .ucode plano (el kernel metal NO habilita FW_LOADER_COMPRESS, así evitamos esa dep).
|
# descomprimen a .ucode plano (el kernel metal NO habilita FW_LOADER_COMPRESS, así evitamos esa dep).
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
# metal-usb-sdboot.sh — USB raw (GPT + ESP FAT32) que arranca hammer en metal vía systemd-boot.
|
# metal-usb-sdboot.sh — USB raw (GPT + ESP FAT32) que arranca takana en metal vía systemd-boot.
|
||||||
#
|
#
|
||||||
# Alternativa de BRINGUP al boot por EFI-stub directo (que en el firmware del usuario se cuelga tras
|
# Alternativa de BRINGUP al boot por EFI-stub directo (que en el firmware del usuario se cuelga tras
|
||||||
# 'Measured initrd PCR 9', por el quirk de LoadOptions del firmware). systemd-boot:
|
# 'Measured initrd PCR 9', por el quirk de LoadOptions del firmware). systemd-boot:
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# Qué hace:
|
# Qué hace:
|
||||||
# 1) Rootfs SLIM: loader musl + busybox + .so runtime tomados de .dev-fs/alpine (la musl userland
|
# 1) Rootfs SLIM: loader musl + busybox + .so runtime tomados de .dev-fs/alpine (la musl userland
|
||||||
# contra la que se construyeron los binarios), NO el 1.2G entero.
|
# contra la que se construyeron los binarios), NO el 1.2G entero.
|
||||||
# 2) Hydrata los artefactos hammer del stack gráfico + mirada desde el store (por hash).
|
# 2) Hydrata los artefactos takana del stack gráfico + mirada desde el store (por hash).
|
||||||
# 3) Cierra el grafo DT_NEEDED: escanea los ELF, y toda .so que falte la trae de .dev-fs/alpine.
|
# 3) Cierra el grafo DT_NEEDED: escanea los ELF, y toda .so que falte la trae de .dev-fs/alpine.
|
||||||
# 4) Escribe /sbin/init = lanzador (seatd + `mirada-compositor --drm --greeter`).
|
# 4) Escribe /sbin/init = lanzador (seatd + `mirada-compositor --drm --greeter`).
|
||||||
# 5) Empaqueta la imagen USB con el kernel linux-generic vía scripts/metal-usb-sdboot.sh.
|
# 5) Empaqueta la imagen USB con el kernel linux-generic vía scripts/metal-usb-sdboot.sh.
|
||||||
@@ -137,7 +137,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# 5c) STACK GL/VULKAN por SOFTWARE + nouveau — de Alpine edge (musl, mismo libLLVM que el dev-fs).
|
# 5c) STACK GL/VULKAN por SOFTWARE + nouveau — de Alpine edge (musl, mismo libLLVM que el dev-fs).
|
||||||
# Por qué NO la mesa-swrast de hammer: su softpipe basta para el COMPOSITOR, pero el greeter (wgpu)
|
# Por qué NO la mesa-swrast de takana: su softpipe basta para el COMPOSITOR, pero el greeter (wgpu)
|
||||||
# necesita un GL/Vulkan más completo. La mesa 26.1.1 de Alpine trae:
|
# necesita un GL/Vulkan más completo. La mesa 26.1.1 de Alpine trae:
|
||||||
# · llvmpipe (swrast_dri.so + libgallium + libLLVM.so.22) → software GL robusto (compositor),
|
# · llvmpipe (swrast_dri.so + libgallium + libLLVM.so.22) → software GL robusto (compositor),
|
||||||
# · lavapipe (libvulkan_lvp.so + ICD) → software Vulkan (backend primario de wgpu),
|
# · lavapipe (libvulkan_lvp.so + ICD) → software Vulkan (backend primario de wgpu),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# nix-import.sh <attr> — Etapa G: extrae de nixpkgs la "receta" de <attr> (source+hash+deps+flags,
|
# nix-import.sh <attr> — Etapa G: extrae de nixpkgs la "receta" de <attr> (source+hash+deps+flags,
|
||||||
# NO el binario) y la imprime como receta hammer vía `hammer import-nix`. Es la semilla del catálogo:
|
# NO el binario) y la imprime como receta takana vía `takana import-nix`. Es la semilla del catálogo:
|
||||||
# nixpkgs es el mayor set de recetas desde fuente; importamos la receta y hammer reconstruye.
|
# nixpkgs es el mayor set de recetas desde fuente; importamos la receta y takana reconstruye.
|
||||||
#
|
#
|
||||||
# Requiere `nix` (con nix-command). Ej: scripts/nix-import.sh hello > recipes/hello.toml
|
# Requiere `nix` (con nix-command). Ej: scripts/nix-import.sh hello > recipes/hello.toml
|
||||||
# Env: NIXPKGS=<flakeref> (default nixpkgs), HAMMER=<cmd> (default cargo run -q -p takana-cli --)
|
# Env: NIXPKGS=<flakeref> (default nixpkgs), HAMMER=<cmd> (default cargo run -q -p takana-cli --)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
# (`/dev/sdb`, 246 G) estaba al **97%, 8,8 G libres**, con la granja escribiendo ahí.
|
# (`/dev/sdb`, 246 G) estaba al **97%, 8,8 G libres**, con la granja escribiendo ahí.
|
||||||
#
|
#
|
||||||
# Y esos 3,5 G no son fuente: el árbol de `work/sources/<nombre>-<sha>` es a la vez el sitio donde
|
# Y esos 3,5 G no son fuente: el árbol de `work/sources/<nombre>-<sha>` es a la vez el sitio donde
|
||||||
# se extrae Y donde se compila (hammer parchea y vendorea in situ). Lo que engorda es el `target/`
|
# se extrae Y donde se compila (takana parchea y vendorea in situ). Lo que engorda es el `target/`
|
||||||
# de cargo, los `.o`, el `vmlinux`. Es RESIDUO DE BUILD, no código.
|
# de cargo, los `.o`, el `vmlinux`. Es RESIDUO DE BUILD, no código.
|
||||||
#
|
#
|
||||||
# ── POR QUÉ BORRARLO NO CUESTA NADA (esto es lo que hace segura la poda) ────────────────────────
|
# ── POR QUÉ BORRARLO NO CUESTA NADA (esto es lo que hace segura la poda) ────────────────────────
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# product-boot-test.sh — valida que el `product-rootfs` ENSAMBLADO POR LA RUTA REAL
|
# product-boot-test.sh — valida que el `product-rootfs` ENSAMBLADO POR LA RUTA REAL
|
||||||
# (`hammer bootstrap product`) bootea en QEMU y sirve SSH. A diferencia de ssh-e2e-test.sh (spike
|
# (`takana bootstrap product`) bootea en QEMU y sirve SSH. A diferencia de ssh-e2e-test.sh (spike
|
||||||
# que arma un rootfs sucio a mano), acá NO se ensambla nada: se toma el artefacto sellado tal cual
|
# que arma un rootfs sucio a mano), acá NO se ensambla nada: se toma el artefacto sellado tal cual
|
||||||
# (seed de producto, passwd, sshd_config, /var/empty, sshd como card — todo ya inyectado por la capa
|
# (seed de producto, passwd, sshd_config, /var/empty, sshd como card — todo ya inyectado por la capa
|
||||||
# de servicios) y sólo se provisiona una authorized_keys de prueba (lo que en deploy haría el admin).
|
# de servicios) y sólo se provisiona una authorized_keys de prueba (lo que en deploy haría el admin).
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
# bajo arje sin tocar el núcleo verificado.
|
# bajo arje sin tocar el núcleo verificado.
|
||||||
#
|
#
|
||||||
# Uso: PRODUCT=<hash-o-prefijo> ./scripts/product-boot-test.sh
|
# Uso: PRODUCT=<hash-o-prefijo> ./scripts/product-boot-test.sh
|
||||||
# (PRODUCT = el que imprimió `hammer bootstrap product`; default: el más reciente del store)
|
# (PRODUCT = el que imprimió `takana bootstrap product`; default: el más reciente del store)
|
||||||
# Vars: KERNEL MEM (def 2048) KVM (def 1) PORT (def 2223) DEADLINE (def 150)
|
# Vars: KERNEL MEM (def 2048) KVM (def 1) PORT (def 2223) DEADLINE (def 150)
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# product-image-from-repo.sh — CIERRE DEL LAZO Etapa F+G: arma una imagen de producto AUTO-BOOTEABLE
|
# product-image-from-repo.sh — CIERRE DEL LAZO Etapa F+G: arma una imagen de producto AUTO-BOOTEABLE
|
||||||
# cuyo USERLAND CLI se hidrata desde el REPO FIRMADO (no del bootstrap hardcodeado). Pipeline:
|
# cuyo USERLAND CLI se hidrata desde el REPO FIRMADO (no del bootstrap hardcodeado). Pipeline:
|
||||||
# 1. base = product-rootfs del store (init arje-zero + musl/busybox + servicios).
|
# 1. base = product-rootfs del store (init arje-zero + musl/busybox + servicios).
|
||||||
# 2. hidrata el userland rico vía `hammer install --repo --prefix --require-signed` (product-userland-from-repo.sh).
|
# 2. hidrata el userland rico vía `takana install --repo --prefix --require-signed` (product-userland-from-repo.sh).
|
||||||
# 3. arma el disco GRUB-booteable (install-image.sh) y, con BOOT=1, lo arranca en QEMU + handshake SSH.
|
# 3. arma el disco GRUB-booteable (install-image.sh) y, con BOOT=1, lo arranca en QEMU + handshake SSH.
|
||||||
#
|
#
|
||||||
# Uso: ./scripts/product-image-from-repo.sh # crea work/hammer-product-repo.img
|
# Uso: ./scripts/product-image-from-repo.sh # crea work/hammer-product-repo.img
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# product-image.sh — empaqueta el `product-rootfs` (lean: 4/4 + userland Rust + sshd, SIN toolchain)
|
# product-image.sh — empaqueta el `product-rootfs` (lean: 4/4 + userland Rust + sshd, SIN toolchain)
|
||||||
# como imagen de disco AUTO-BOOTEABLE (GRUB BIOS), reusando scripts/install-image.sh. Es el cierre del
|
# como imagen de disco AUTO-BOOTEABLE (GRUB BIOS), reusando scripts/install-image.sh. Es el cierre del
|
||||||
# pipeline: del artefacto sellado por `hammer bootstrap product` a un disco que arranca solo en QEMU
|
# pipeline: del artefacto sellado por `takana bootstrap product` a un disco que arranca solo en QEMU
|
||||||
# (`-drive file=img`, sin -kernel) y, con red, sirve SSH.
|
# (`-drive file=img`, sin -kernel) y, con red, sirve SSH.
|
||||||
#
|
#
|
||||||
# A diferencia de install-image.sh (que por defecto empaqueta el BUILDER rootfs con todo el toolchain),
|
# A diferencia de install-image.sh (que por defecto empaqueta el BUILDER rootfs con todo el toolchain),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# product-userland-from-repo.sh — arma el USERLAND del producto HIDRATÁNDOLO desde el REPO FIRMADO
|
# product-userland-from-repo.sh — arma el USERLAND del producto HIDRATÁNDOLO desde el REPO FIRMADO
|
||||||
# (Etapa F+G, cierre del lazo): por cada paquete corre `hammer install --repo <repo> --prefix <rfs>
|
# (Etapa F+G, cierre del lazo): por cada paquete corre `takana install --repo <repo> --prefix <rfs>
|
||||||
# --require-signed`, que verifica la firma del release, reproduce desde el `.swm` (cache-hit si ya
|
# --require-signed`, que verifica la firma del release, reproduce desde el `.swm` (cache-hit si ya
|
||||||
# está en el store) e hidrata el FHS bajo el prefix. El resultado es un árbol de userland cuya cadena
|
# está en el store) e hidrata el FHS bajo el prefix. El resultado es un árbol de userland cuya cadena
|
||||||
# de suministro entera viene del repo firmado, no del bootstrap hardcodeado.
|
# de suministro entera viene del repo firmado, no del bootstrap hardcodeado.
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ LOG=$(mktemp -d)
|
|||||||
trap 'rm -rf "$LOG"' EXIT
|
trap 'rm -rf "$LOG"' EXIT
|
||||||
|
|
||||||
# ── LA SALIDA VA A FICHERO, NO A `$( )` ─────────────────────────────────────────────────────────
|
# ── LA SALIDA VA A FICHERO, NO A `$( )` ─────────────────────────────────────────────────────────
|
||||||
# MEDIDO acá, y cuesta una hora si no se sabe: `SALIDA=$(timeout … hammer qorpa run …)` **se cuelga
|
# MEDIDO acá, y cuesta una hora si no se sabe: `SALIDA=$(timeout … takana qorpa run …)` **se cuelga
|
||||||
# para siempre** aunque `timeout` mate al hijo. La sustitución de comandos no espera al PROCESO,
|
# para siempre** aunque `timeout` mate al hijo. La sustitución de comandos no espera al PROCESO,
|
||||||
# espera a que se cierre el PIPE, y pressure-vessel deja descendientes (su logger) con el fd
|
# espera a que se cierre el PIPE, y pressure-vessel deja descendientes (su logger) con el fd
|
||||||
# abierto. Con redirección a fichero el mismo comando termina y devuelve su código. Es la misma
|
# abierto. Con redirección a fichero el mismo comando termina y devuelve su código. Es la misma
|
||||||
|
|||||||
@@ -9,13 +9,13 @@
|
|||||||
# la misma dirección).
|
# la misma dirección).
|
||||||
#
|
#
|
||||||
# ── POR QUÉ EN SERIE, Y NO ES NEGOCIABLE ────────────────────────────────────────────────────────
|
# ── POR QUÉ EN SERIE, Y NO ES NEGOCIABLE ────────────────────────────────────────────────────────
|
||||||
# `hammer build` comparte `work/sources/<dep>-<sha>`. Dos builds que compartan una dep se pisan el
|
# `takana build` comparte `work/sources/<dep>-<sha>`. Dos builds que compartan una dep se pisan el
|
||||||
# árbol y queda ROTO PARA SIEMPRE (ADR 0012, sin decidir; ~93 de 205 recetas KDE murieron así al
|
# árbol y queda ROTO PARA SIEMPRE (ADR 0012, sin decidir; ~93 de 205 recetas KDE murieron así al
|
||||||
# invalidar libdrm). Todo el run va bajo UN `flock work/.farm-build.lock`, el mismo que toman los
|
# invalidar libdrm). Todo el run va bajo UN `flock work/.farm-build.lock`, el mismo que toman los
|
||||||
# scripts de la granja, así que también nos serializa con ellos y con cualquier otro agente.
|
# scripts de la granja, así que también nos serializa con ellos y con cualquier otro agente.
|
||||||
#
|
#
|
||||||
# ── REANUDABLE POR CONSTRUCCIÓN ─────────────────────────────────────────────────────────────────
|
# ── REANUDABLE POR CONSTRUCCIÓN ─────────────────────────────────────────────────────────────────
|
||||||
# No lleva estado propio: la pregunta "¿esto ya está?" se la hace al store con `hammer hash --check`
|
# No lleva estado propio: la pregunta "¿esto ya está?" se la hace al store con `takana hash --check`
|
||||||
# (~2 ms, sin construir). Matarlo y relanzarlo continúa donde iba. Un run entero sobre un corpus ya
|
# (~2 ms, sin construir). Matarlo y relanzarlo continúa donde iba. Un run entero sobre un corpus ya
|
||||||
# construido son unos segundos de puros --check.
|
# construido son unos segundos de puros --check.
|
||||||
#
|
#
|
||||||
@@ -52,10 +52,10 @@ SECO=0; [ "${1:-}" = "--seco" ] && SECO=1
|
|||||||
#
|
#
|
||||||
# ── 2026-08-27: MIRA DÓNDE SE GASTA, NO DÓNDE ESTÁ EL REPO ──────────────────────────────────────
|
# ── 2026-08-27: MIRA DÓNDE SE GASTA, NO DÓNDE ESTÁ EL REPO ──────────────────────────────────────
|
||||||
# Medir `$ROOT` dejó de ser correcto al mudar el store al volumen `harkaq-cosecha`. `$ROOT` es
|
# Medir `$ROOT` dejó de ser correcto al mudar el store al volumen `harkaq-cosecha`. `$ROOT` es
|
||||||
# /mnt/vvv, que hammer COMPARTE con tawasuyu, y tawasuyu repuebla su target a ~62 G/h: el 27/08 se
|
# /mnt/vvv, que takana COMPARTE con tawasuyu, y tawasuyu repuebla su target a ~62 G/h: el 27/08 se
|
||||||
# comió los 92 G que se le habían liberado en 70 minutos y el vigía abortó la tanda por un disco
|
# comió los 92 G que se le habían liberado en 70 minutos y el vigía abortó la tanda por un disco
|
||||||
# que hammer ya ni usaba. Un vigía que mide el disco de OTRO no protege la tanda, la mata.
|
# que takana ya ni usaba. Un vigía que mide el disco de OTRO no protege la tanda, la mata.
|
||||||
# Ahora se miden los tres sitios donde hammer SÍ crece —store, árboles de fuentes y CARGO_HOME—
|
# Ahora se miden los tres sitios donde takana SÍ crece —store, árboles de fuentes y CARGO_HOME—
|
||||||
# y se toma el mínimo. Si comparten FS, `df` repite el número y esto es inocuo.
|
# y se toma el mínimo. Si comparten FS, `df` repite el número y esto es inocuo.
|
||||||
CARGO_H="${CARGO_HOME:-$HOME/.cargo}"
|
CARGO_H="${CARGO_HOME:-$HOME/.cargo}"
|
||||||
# ── GOPATH TAMBIÉN CRECE, y llenó `/` hasta 0 BYTES el 2026-08-28 ───────────────────────────────
|
# ── GOPATH TAMBIÉN CRECE, y llenó `/` hasta 0 BYTES el 2026-08-28 ───────────────────────────────
|
||||||
@@ -78,7 +78,7 @@ libre_gb() {
|
|||||||
}
|
}
|
||||||
ts() { date -u +%Y-%m-%dT%H:%M:%SZ; }
|
ts() { date -u +%Y-%m-%dT%H:%M:%SZ; }
|
||||||
|
|
||||||
# EL ORDEN IMPORTA, aunque las deps se resuelvan solas. `hammer build` construye recursivamente lo
|
# EL ORDEN IMPORTA, aunque las deps se resuelvan solas. `takana build` construye recursivamente lo
|
||||||
# que le falta, así que cualquier orden termina — pero no cualquier orden es útil a mitad de camino.
|
# que le falta, así que cualquier orden termina — pero no cualquier orden es útil a mitad de camino.
|
||||||
# Hay 1186 ficheros de receta y sólo ~440 alcanzan alguna imagen; el resto son catálogo y colas de
|
# Hay 1186 ficheros de receta y sólo ~440 alcanzan alguna imagen; el resto son catálogo y colas de
|
||||||
# staging. Construyendo por orden alfabético, tras un día de máquina no habría NI UNA imagen
|
# staging. Construyendo por orden alfabético, tras un día de máquina no habría NI UNA imagen
|
||||||
@@ -146,7 +146,7 @@ mapfile -t RECETAS < "$ORDEN"
|
|||||||
# ── PARTICIÓN ENTRE WORKERS: SHARD=i/N ──────────────────────────────────────────────────────────
|
# ── PARTICIÓN ENTRE WORKERS: SHARD=i/N ──────────────────────────────────────────────────────────
|
||||||
# Con un worker el corpus son ~7 días (medido: ~9 min/receta sobre 1161). Repartirlo es la única
|
# Con un worker el corpus son ~7 días (medido: ~9 min/receta sobre 1161). Repartirlo es la única
|
||||||
# forma de bajarlo, y no hace falta planificador central: cada worker construye SU parte y las deps
|
# forma de bajarlo, y no hace falta planificador central: cada worker construye SU parte y las deps
|
||||||
# que le falten se las construye `hammer build` solo. Al cosechar, todo converge en el mismo store
|
# que le falten se las construye `takana build` solo. Al cosechar, todo converge en el mismo store
|
||||||
# porque las direcciones coinciden — eso está PROBADO por el paso 4 de `farm-lab-sync.sh`, no
|
# porque las direcciones coinciden — eso está PROBADO por el paso 4 de `farm-lab-sync.sh`, no
|
||||||
# supuesto.
|
# supuesto.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Respaldo de hammer al Storage Box de Hetzner (BX11, 1 TiB, hel1).
|
# Respaldo de takana al Storage Box de Hetzner (BX11, 1 TiB, hel1).
|
||||||
#
|
#
|
||||||
# ── POR QUÉ UN STORAGE BOX Y NO EL VOLUMEN ──────────────────────────────────────────────────────
|
# ── POR QUÉ UN STORAGE BOX Y NO EL VOLUMEN ──────────────────────────────────────────────────────
|
||||||
# El usuario pidió respaldar «en el volumen, aunque sea montándolo aquí». **No se puede**: un Hetzner
|
# El usuario pidió respaldar «en el volumen, aunque sea montándolo aquí». **No se puede**: un Hetzner
|
||||||
@@ -70,12 +70,12 @@ if [ "${1:-}" = "--listar" ]; then
|
|||||||
cd "$RAIZ"; mkdir -p work
|
cd "$RAIZ"; mkdir -p work
|
||||||
# `du -s`, NO `ls`. Un `ls` lista NOMBRES DE DIRECTORIO, y un artefacto VACÍO tiene nombre igual
|
# `du -s`, NO `ls`. Un `ls` lista NOMBRES DE DIRECTORIO, y un artefacto VACÍO tiene nombre igual
|
||||||
# que uno bueno ⇒ el manifiesto lo avala, `build-state.py` lo da por sellado, rsync lo baja vacío
|
# que uno bueno ⇒ el manifiesto lo avala, `build-state.py` lo da por sellado, rsync lo baja vacío
|
||||||
# y `hammer build` hace cache-hit sobre el directorio vacío: sella sin construir y sale 0. Toda la
|
# y `takana build` hace cache-hit sobre el directorio vacío: sella sin construir y sale 0. Toda la
|
||||||
# cadena lee el vacío como presencia, y el único síntoma aparece al final, disfrazado de éxito.
|
# cadena lee el vacío como presencia, y el único síntoma aparece al final, disfrazado de éxito.
|
||||||
# (2026-08-10: 7 vacíos de 1749, todos del stack gráfico, de una subida que falló callada.)
|
# (2026-08-10: 7 vacíos de 1749, todos del stack gráfico, de una subida que falló callada.)
|
||||||
# Cuesta 8,6 s sobre 1751 artefactos frente a un `ls` instantáneo — barato para lo que evita.
|
# Cuesta 8,6 s sobre 1751 artefactos frente a un `ls` instantáneo — barato para lo que evita.
|
||||||
# La shell del box no es bash y no tiene `find`, pero SÍ expande globs y SÍ tiene `du`.
|
# La shell del box no es bash y no tiene `find`, pero SÍ expande globs y SÍ tiene `du`.
|
||||||
# `du -s hammer/store/[0-9a-f]*` y NO `store/*`: el glob amplio incluye `.dmerge`, la caché
|
# `du -s takana/store/[0-9a-f]*` y NO `store/*`: el glob amplio incluye `.dmerge`, la caché
|
||||||
# transitoria de fusión —48 GB el 2026-08-12—, y recorrerla hace que el listado tarde tanto que se
|
# transitoria de fusión —48 GB el 2026-08-12—, y recorrerla hace que el listado tarde tanto que se
|
||||||
# corta por timeout. El sufijo del glob además descarta de entrada los `.bootstrap-tmp`/`.mirror-tmp`
|
# corta por timeout. El sufijo del glob además descarta de entrada los `.bootstrap-tmp`/`.mirror-tmp`
|
||||||
# que nunca son artefactos. Un artefacto SIEMPRE empieza por hex: filtrar en el origen es más barato
|
# que nunca son artefactos. Un artefacto SIEMPRE empieza por hex: filtrar en el origen es más barato
|
||||||
@@ -83,7 +83,7 @@ if [ "${1:-}" = "--listar" ]; then
|
|||||||
ssh -4 -p "$SB_PORT" -i "$KEY" -o StrictHostKeyChecking=accept-new \
|
ssh -4 -p "$SB_PORT" -i "$KEY" -o StrictHostKeyChecking=accept-new \
|
||||||
"$SB_USER@$SB_HOST" 'du -s hammer/store/[0-9a-f]*' 2>/dev/null > work/.respaldo-du.tmp
|
"$SB_USER@$SB_HOST" 'du -s hammer/store/[0-9a-f]*' 2>/dev/null > work/.respaldo-du.tmp
|
||||||
# OJO CON EL ORDEN: recortar la ruta ANTES del awk se come el contador (`sed 's#.*/##'` es codicioso
|
# OJO CON EL ORDEN: recortar la ruta ANTES del awk se come el contador (`sed 's#.*/##'` es codicioso
|
||||||
# y borra "5347<TAB>hammer/store/" entero), y entonces $1 es el NOMBRE, no los bloques: el filtro
|
# y borra "5347<TAB>takana/store/" entero), y entonces $1 es el NOMBRE, no los bloques: el filtro
|
||||||
# compara basura y devuelve cualquier cosa. Primero se filtra por número, después se recorta.
|
# compara basura y devuelve cualquier cosa. Primero se filtra por número, después se recorta.
|
||||||
# Campo 1 = bloques. Un directorio sin contenido da 1..4; con contenido, mucho más.
|
# Campo 1 = bloques. Un directorio sin contenido da 1..4; con contenido, mucho más.
|
||||||
awk '$1<=4 {sub(/.*\//,"",$2); print $2}' work/.respaldo-du.tmp \
|
awk '$1<=4 {sub(/.*\//,"",$2); print $2}' work/.respaldo-du.tmp \
|
||||||
@@ -118,7 +118,7 @@ SSH_CMD="ssh -4 -p $SB_PORT -i $KEY -o StrictHostKeyChecking=accept-new -o Serve
|
|||||||
|
|
||||||
# Opciones comunes. `--partial-dir` es lo que hace el respaldo continuable a mitad de fichero.
|
# Opciones comunes. `--partial-dir` es lo que hace el respaldo continuable a mitad de fichero.
|
||||||
# `--exclude /.dmerge`: son directorios TRANSITORIOS de fusión del store — aparecen y desaparecen
|
# `--exclude /.dmerge`: son directorios TRANSITORIOS de fusión del store — aparecen y desaparecen
|
||||||
# mientras hammer sella. rsync los empieza a copiar, se esfuman a media transferencia y devuelve 23
|
# mientras takana sella. rsync los empieza a copiar, se esfuman a media transferencia y devuelve 23
|
||||||
# («some files/attrs were not transferred»). Como 23 está en la lista de reintentables, el bucle los
|
# («some files/attrs were not transferred»). Como 23 está en la lista de reintentables, el bucle los
|
||||||
# reintentó **40 veces seguidas** y se rindió con el respaldo a medias (79 G de 127 G), sin que el
|
# reintentó **40 veces seguidas** y se rindió con el respaldo a medias (79 G de 127 G), sin que el
|
||||||
# mensaje dijera nunca que la culpa era de un directorio temporal. `cosecha-cron.sh` ya los excluía;
|
# mensaje dijera nunca que la culpa era de un directorio temporal. `cosecha-cron.sh` ya los excluía;
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ STAGE0=.scratch/rust-1.91.0-prefix .scratch/run-xpy.sh \
|
|||||||
# PRESEED=hammerd es OBLIGATORIO con SWAP_RUST: arje-zero (monorepo tawasuyu) vendorea
|
# PRESEED=hammerd es OBLIGATORIO con SWAP_RUST: arje-zero (monorepo tawasuyu) vendorea
|
||||||
# ~1973 crates; en un rebuild in-VM completo (PRESEED=all) ese vendor desborda el
|
# ~1973 crates; en un rebuild in-VM completo (PRESEED=all) ese vendor desborda el
|
||||||
# rootfs en RAM de la VM → ENOSPC. Con PRESEED=hammerd se preseedea el arje-zero
|
# rootfs en RAM de la VM → ENOSPC. Con PRESEED=hammerd se preseedea el arje-zero
|
||||||
# host-built (hammer-rust, locked) y sólo hammerd se reconstruye in-VM.
|
# host-built (takana-rust, locked) y sólo hammerd se reconstruye in-VM.
|
||||||
SWAP_RUST=1 KVM=1 MEM=16384 PRESEED=hammerd ./scripts/selfhost-verify.sh
|
SWAP_RUST=1 KVM=1 MEM=16384 PRESEED=hammerd ./scripts/selfhost-verify.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# bootstrap.toml — hammer self-host climb hop 2 (1.91.0 -> 1.91.1), musl host.
|
# bootstrap.toml — takana self-host climb hop 2 (1.91.0 -> 1.91.1), musl host.
|
||||||
# stage0 rustc = the installed hammer-built 1.91.0 (bound read-only at /stage0);
|
# stage0 rustc = the installed takana-built 1.91.0 (bound read-only at /stage0);
|
||||||
# stage0 cargo = the run_rustc mrustc-bootstrapped 1.90.0 cargo (1.90 satisfies
|
# stage0 cargo = the run_rustc mrustc-bootstrapped 1.90.0 cargo (1.90 satisfies
|
||||||
# bootstrap's "minor-1" check for a 1.91.x source). LLVM 20.1.8 reused externally.
|
# bootstrap's "minor-1" check for a 1.91.x source). LLVM 20.1.8 reused externally.
|
||||||
# extended+cargo so the install includes a hammer-built cargo 1.91.1 (final toolchain).
|
# extended+cargo so the install includes a takana-built cargo 1.91.1 (final toolchain).
|
||||||
change-id = "ignore"
|
change-id = "ignore"
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# bootstrap.toml — hammer self-host climb (musl host, hermetic Alpine devfs sandbox).
|
# bootstrap.toml — takana self-host climb (musl host, hermetic Alpine devfs sandbox).
|
||||||
# stage0 = the mrustc-bootstrapped rustc/cargo 1.90.0 (musl host); LLVM 20.1.8 reused
|
# stage0 = the mrustc-bootstrapped rustc/cargo 1.90.0 (musl host); LLVM 20.1.8 reused
|
||||||
# externally; dynamic link against the devfs's system musl (crt-static = false), exactly
|
# externally; dynamic link against the devfs's system musl (crt-static = false), exactly
|
||||||
# like Alpine's own rust and the run_rustc stage-3 toolchain.
|
# like Alpine's own rust and the run_rustc stage-3 toolchain.
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# swap-rust-into-toolchain.sh — overlay the hammer-built rust 1.91.1 onto a toolchain
|
# swap-rust-into-toolchain.sh — overlay the takana-built rust 1.91.1 onto a toolchain
|
||||||
# dir (default .dev-fs/alpine), so `hammer build` / `bootstrap stage1` compile the
|
# dir (default .dev-fs/alpine), so `takana build` / `bootstrap stage1` compile the
|
||||||
# 4/4 rust inputs (arje-zero, hammerd) with hammer-rust instead of Alpine's rustc.
|
# 4/4 rust inputs (arje-zero, hammerd) with takana-rust instead of Alpine's rustc.
|
||||||
#
|
#
|
||||||
# This is the rust tool-swap of the selfhost-verify "variante b". Unlike make/bwrap/…
|
# This is the rust tool-swap of the selfhost-verify "variante b". Unlike make/bwrap/…
|
||||||
# (tools that orchestrate/copy → identical bytes), **rustc emits the 4/4 binaries**, so
|
# (tools that orchestrate/copy → identical bytes), **rustc emits the 4/4 binaries**, so
|
||||||
# a hammer-built rustc produces a DIFFERENT of_tree than Alpine's 9adefb82. Success
|
# a takana-built rustc produces a DIFFERENT of_tree than Alpine's 9adefb82. Success
|
||||||
# criterion is therefore AUTO-CONSISTENCY: stage1' built with hammer-rust == stage1''
|
# criterion is therefore AUTO-CONSISTENCY: stage1' built with takana-rust == stage1''
|
||||||
# rebuilt with hammer-rust (a NEW EXPECT_REF), not byte-identity with the Alpine baseline.
|
# rebuilt with takana-rust (a NEW EXPECT_REF), not byte-identity with the Alpine baseline.
|
||||||
#
|
#
|
||||||
# The overlay is mostly ADDITIVE and fully reversible:
|
# The overlay is mostly ADDITIVE and fully reversible:
|
||||||
# - hammer's rustc/cargo use host triple x86_64-unknown-linux-musl and hash-suffixed
|
# - takana's rustc/cargo use host triple x86_64-unknown-linux-musl and hash-suffixed
|
||||||
# .so names that DON'T collide with Alpine's (x86_64-alpine-linux-musl / other
|
# .so names that DON'T collide with Alpine's (x86_64-alpine-linux-musl / other
|
||||||
# hashes), so the new rustlib triple + librustc_driver just sit alongside Alpine's.
|
# hashes), so the new rustlib triple + librustc_driver just sit alongside Alpine's.
|
||||||
# - only /usr/bin/{rustc,cargo} are REPLACED; the originals are backed up to
|
# - only /usr/bin/{rustc,cargo} are REPLACED; the originals are backed up to
|
||||||
# usr/bin/<name>.alpine so `--restore` can put them back.
|
# usr/bin/<name>.alpine so `--restore` can put them back.
|
||||||
# The 4/4 rust recipes build NATIVE (target x86_64-linux-musl == SANDBOX_NATIVE_TARGET
|
# The 4/4 rust recipes build NATIVE (target x86_64-linux-musl == SANDBOX_NATIVE_TARGET
|
||||||
# ⇒ no --target, see takana-build/src/lib.rs:269), so hammer-rustc compiles them for
|
# ⇒ no --target, see takana-build/src/lib.rs:269), so takana-rustc compiles them for
|
||||||
# its OWN native triple x86_64-unknown-linux-musl.
|
# its OWN native triple x86_64-unknown-linux-musl.
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
@@ -51,7 +51,7 @@ if [ "$RESTORE" = 1 ]; then
|
|||||||
echo " (sin backup de usr/bin/$b — ¿ya restaurado?)"
|
echo " (sin backup de usr/bin/$b — ¿ya restaurado?)"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
# Quitar también lo AÑADIDO por el swap: el librustc_driver de hammer (hash propio, distinto del
|
# Quitar también lo AÑADIDO por el swap: el librustc_driver de takana (hash propio, distinto del
|
||||||
# de Alpine) y el sysroot del triple x86_64-unknown-linux-musl (un devfs Alpine prístino NO los
|
# de Alpine) y el sysroot del triple x86_64-unknown-linux-musl (un devfs Alpine prístino NO los
|
||||||
# tiene). Inertes para el rustc de Alpine, pero dejarlos es ~350 MB de cruft y deja el toolchain
|
# tiene). Inertes para el rustc de Alpine, pero dejarlos es ~350 MB de cruft y deja el toolchain
|
||||||
# no-prístino; lo limpiamos para que --restore sea reversibilidad total.
|
# no-prístino; lo limpiamos para que --restore sea reversibilidad total.
|
||||||
@@ -70,11 +70,11 @@ fi
|
|||||||
|
|
||||||
say "swap: overlay hammer-rust 1.91.1 ($PREFIX) → $TOOLCHAIN"
|
say "swap: overlay hammer-rust 1.91.1 ($PREFIX) → $TOOLCHAIN"
|
||||||
|
|
||||||
# 1) librustc_driver de hammer (hash único, no choca con el de Alpine).
|
# 1) librustc_driver de takana (hash único, no choca con el de Alpine).
|
||||||
cp -a "$PREFIX"/lib/librustc_driver-*.so "$TOOLCHAIN/usr/lib/"
|
cp -a "$PREFIX"/lib/librustc_driver-*.so "$TOOLCHAIN/usr/lib/"
|
||||||
echo " + usr/lib/$(basename "$PREFIX"/lib/librustc_driver-*.so)"
|
echo " + usr/lib/$(basename "$PREFIX"/lib/librustc_driver-*.so)"
|
||||||
|
|
||||||
# 2) sysroot de hammer para su triple nativo (dir nuevo, no choca con x86_64-alpine-linux-musl).
|
# 2) sysroot de takana para su triple nativo (dir nuevo, no choca con x86_64-alpine-linux-musl).
|
||||||
rm -rf "$TOOLCHAIN/usr/lib/rustlib/x86_64-unknown-linux-musl"
|
rm -rf "$TOOLCHAIN/usr/lib/rustlib/x86_64-unknown-linux-musl"
|
||||||
cp -a "$PREFIX/lib/rustlib/x86_64-unknown-linux-musl" "$TOOLCHAIN/usr/lib/rustlib/"
|
cp -a "$PREFIX/lib/rustlib/x86_64-unknown-linux-musl" "$TOOLCHAIN/usr/lib/rustlib/"
|
||||||
echo " + usr/lib/rustlib/x86_64-unknown-linux-musl ($(du -sh "$PREFIX/lib/rustlib/x86_64-unknown-linux-musl" | cut -f1))"
|
echo " + usr/lib/rustlib/x86_64-unknown-linux-musl ($(du -sh "$PREFIX/lib/rustlib/x86_64-unknown-linux-musl" | cut -f1))"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# nix, ADR 0004: sólo lee deps). Corre `sembrar_cierre` de seed-graph sobre las raíces de una sesión
|
# nix, ADR 0004: sólo lee deps). Corre `sembrar_cierre` de seed-graph sobre las raíces de una sesión
|
||||||
# GNOME y clasifica el cierre:
|
# GNOME y clasifica el cierre:
|
||||||
# conocida → ya hay receta en el corpus (cache-hit potencial)
|
# conocida → ya hay receta en el corpus (cache-hit potencial)
|
||||||
# frontera → nixpkgs lo pide y hammer NO tiene receta → HAY QUE AUTORAR (esto es el trabajo real)
|
# frontera → nixpkgs lo pide y takana NO tiene receta → HAY QUE AUTORAR (esto es el trabajo real)
|
||||||
# nix-ismo/lab → ruido de nixpkgs o lo provee el sandbox (se descarta)
|
# nix-ismo/lab → ruido de nixpkgs o lo provee el sandbox (se descarta)
|
||||||
#
|
#
|
||||||
# Cada `frontera` es una HIPÓTESIS a clasificar/autorar por un humano (o un subagente-por-receta), NO
|
# Cada `frontera` es una HIPÓTESIS a clasificar/autorar por un humano (o un subagente-por-receta), NO
|
||||||
@@ -33,7 +33,7 @@ MINIMA = [ # lo que una sesión GNOME necesita para BOOTEAR a un shell usable (
|
|||||||
]
|
]
|
||||||
|
|
||||||
# ── LA OPTIMIZACIÓN (el "yupana de gnome", no un sembrador crudo). El cierre de metadata de nixpkgs
|
# ── LA OPTIMIZACIÓN (el "yupana de gnome", no un sembrador crudo). El cierre de metadata de nixpkgs
|
||||||
# SOBREESTIMA ~5-10× la frontera real de hammer, porque declara buildInputs de features MÁXIMAS. Estas
|
# SOBREESTIMA ~5-10× la frontera real de takana, porque declara buildInputs de features MÁXIMAS. Estas
|
||||||
# tablas son HIPÓTESIS de triage (NO verdad — la verdad emerge autorando feature-minimal), para que el
|
# tablas son HIPÓTESIS de triage (NO verdad — la verdad emerge autorando feature-minimal), para que el
|
||||||
# reporte no mienta con "465 recetas". Cada una vuelve legible por qué un candidato probablemente NO es
|
# reporte no mienta con "465 recetas". Cada una vuelve legible por qué un candidato probablemente NO es
|
||||||
# hueco. Clasificar a mano al autorar; mover entre cubetas es esperable.
|
# hueco. Clasificar a mano al autorar; mover entre cubetas es esperable.
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
# Cada arista sembrada se CLASIFICA, que es donde está el valor:
|
# Cada arista sembrada se CLASIFICA, que es donde está el valor:
|
||||||
# conocida — tras normalizar, hay receta con ese nombre. Arista utilizable ya.
|
# conocida — tras normalizar, hay receta con ese nombre. Arista utilizable ya.
|
||||||
# frontera — no hay receta y no es un nix-ismo ⇒ candidato a nodo `wanted` nuevo.
|
# frontera — no hay receta y no es un nix-ismo ⇒ candidato a nodo `wanted` nuevo.
|
||||||
# nix-ismo — andamiaje de nixpkgs que en hammer no existe (hooks, wrappers, doc tooling).
|
# nix-ismo — andamiaje de nixpkgs que en takana no existe (hooks, wrappers, doc tooling).
|
||||||
# lab — toolchain que provee el rootfs del sandbox, no una receta (cargo/rustc).
|
# lab — toolchain que provee el rootfs del sandbox, no una receta (cargo/rustc).
|
||||||
#
|
#
|
||||||
# CALIBRADO, no supuesto (medición completa en el plan). Muestra de 60 recetas / 686 deps:
|
# CALIBRADO, no supuesto (medición completa en el plan). Muestra de 60 recetas / 686 deps:
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
# transitividad la hace el grafo**, que es lo que `build-state.py` ya sabe hacer con las aristas.
|
# transitividad la hace el grafo**, que es lo que `build-state.py` ya sabe hacer con las aristas.
|
||||||
#
|
#
|
||||||
# Uso: scripts/seed-graph.py --calibrar [N] [--transitivo] # mide el ruido contra recetas escritas
|
# Uso: scripts/seed-graph.py --calibrar [N] [--transitivo] # mide el ruido contra recetas escritas
|
||||||
# scripts/seed-graph.py --frontera <perfil> # qué pide nixpkgs y hammer no tiene → seed-frontera.json
|
# scripts/seed-graph.py --frontera <perfil> # qué pide nixpkgs y takana no tiene → seed-frontera.json
|
||||||
# scripts/seed-graph.py --perfil <perfil> # siembra los nodos `wanted` → seed-edges.json
|
# scripts/seed-graph.py --perfil <perfil> # siembra los nodos `wanted` → seed-edges.json
|
||||||
# scripts/seed-graph.py <nombre...> # siembra nombres sueltos
|
# scripts/seed-graph.py <nombre...> # siembra nombres sueltos
|
||||||
# Env: NIXPKGS (def nixpkgs), NIX_ROOT (def ~/.nixstore; vacío = store del sistema)
|
# Env: NIXPKGS (def nixpkgs), NIX_ROOT (def ~/.nixstore; vacío = store del sistema)
|
||||||
@@ -52,7 +52,7 @@ OUT = ROOT / "docs/state/seed-edges.json"
|
|||||||
FRONTERA = ROOT / "docs/state/seed-frontera.json"
|
FRONTERA = ROOT / "docs/state/seed-frontera.json"
|
||||||
LOTE = 120 # nombres por proceso de `nix eval` (uno solo evalúa 6 en 0.7s; el costo es el arranque)
|
LOTE = 120 # nombres por proceso de `nix eval` (uno solo evalúa 6 en 0.7s; el costo es el arranque)
|
||||||
|
|
||||||
# --- normalización nix → hammer -------------------------------------------------------------------
|
# --- normalización nix → takana -------------------------------------------------------------------
|
||||||
# Mapeo por evidencia, no por intuición: cada entrada salió de una discrepancia vista en --calibrar.
|
# Mapeo por evidencia, no por intuición: cada entrada salió de una discrepancia vista en --calibrar.
|
||||||
MAPA = {
|
MAPA = {
|
||||||
"ninja": "samurai", # hammer usa samurai como backend de meson
|
"ninja": "samurai", # hammer usa samurai como backend de meson
|
||||||
@@ -66,7 +66,7 @@ MAPA = {
|
|||||||
"util-linux-minimal": "util-linux",
|
"util-linux-minimal": "util-linux",
|
||||||
"cacert": "ca-certificates",
|
"cacert": "ca-certificates",
|
||||||
}
|
}
|
||||||
# Andamiaje de nixpkgs sin contraparte en hammer: hooks del stdenv, wrappers, tooling de docs.
|
# Andamiaje de nixpkgs sin contraparte en takana: hooks del stdenv, wrappers, tooling de docs.
|
||||||
NIXISMOS_EXACTOS = {
|
NIXISMOS_EXACTOS = {
|
||||||
"", "which", "stdenv", "gtk-doc", "docbook-xml", "docbook-xsl", "docbook-xsl-nons",
|
"", "which", "stdenv", "gtk-doc", "docbook-xml", "docbook-xsl", "docbook-xsl-nons",
|
||||||
"docbook-xsl-ns", "docbook2X", "asciidoc", "asciidoctor", "install-shell-files",
|
"docbook-xsl-ns", "docbook2X", "asciidoc", "asciidoctor", "install-shell-files",
|
||||||
@@ -94,13 +94,13 @@ if _ALIAS.exists():
|
|||||||
NIXISMOS_INFIJOS = ("-hook",) # `cargo-build-hook.sh` no termina en `-hook`, lo contiene
|
NIXISMOS_INFIJOS = ("-hook",) # `cargo-build-hook.sh` no termina en `-hook`, lo contiene
|
||||||
# Toolchains que provee el LAB (el rootfs del sandbox), no una receta: ninguna receta Rust declara
|
# Toolchains que provee el LAB (el rootfs del sandbox), no una receta: ninguna receta Rust declara
|
||||||
# `rust` ni `cargo` en `[deps].build` — están vacías y el toolchain viene de abajo. Que nixpkgs los
|
# `rust` ni `cargo` en `[deps].build` — están vacías y el toolchain viene de abajo. Que nixpkgs los
|
||||||
# liste no es un hueco de hammer; es que las dos distros ponen la frontera en lugares distintos.
|
# liste no es un hueco de takana; es que las dos distros ponen la frontera en lugares distintos.
|
||||||
PROVISTO_POR_EL_LAB = {"cargo", "rustc", "rust"}
|
PROVISTO_POR_EL_LAB = {"cargo", "rustc", "rust"}
|
||||||
# Deps que hammer declara SIEMPRE y nix nunca lista porque las provee el stdenv implícito. No son
|
# Deps que takana declara SIEMPRE y nix nunca lista porque las provee el stdenv implícito. No son
|
||||||
# un fallo del sembrador: son convención del sandbox de hammer (cada dep es una capa --overlay-src).
|
# un fallo del sembrador: son convención del sandbox de takana (cada dep es una capa --overlay-src).
|
||||||
CONVENCION_HAMMER = {"make", "binutils", "linux-headers"}
|
CONVENCION_HAMMER = {"make", "binutils", "linux-headers"}
|
||||||
# Sufijos de VARIANTE de hammer: `zlib` y `zlib-shared` son el mismo paquete con otra decisión de
|
# Sufijos de VARIANTE de takana: `zlib` y `zlib-shared` son el mismo paquete con otra decisión de
|
||||||
# enlazado. nixpkgs no puede saber cuál eligió hammer ⇒ no es un fallo del sembrador, es una
|
# enlazado. nixpkgs no puede saber cuál eligió takana ⇒ no es un fallo del sembrador, es una
|
||||||
# decisión nuestra. Se cuenta aparte para no inflar ni el acierto ni el error.
|
# decisión nuestra. Se cuenta aparte para no inflar ni el acierto ni el error.
|
||||||
VARIANTES = ("-shared", "-static")
|
VARIANTES = ("-shared", "-static")
|
||||||
|
|
||||||
|
|||||||
+15
-15
@@ -53,7 +53,7 @@ die() { printf '\033[1;31mERROR: %s\033[0m\n' "$*" >&2; exit 1; }
|
|||||||
[[ -r "$KERNEL" ]] || die "no puedo leer el kernel $KERNEL (set KERNEL=…)"
|
[[ -r "$KERNEL" ]] || die "no puedo leer el kernel $KERNEL (set KERNEL=…)"
|
||||||
command -v qemu-system-x86_64 >/dev/null || die "falta qemu-system-x86_64"
|
command -v qemu-system-x86_64 >/dev/null || die "falta qemu-system-x86_64"
|
||||||
|
|
||||||
# 0) Binario hammer estático (musl, crt-static) — el builder lo bootea adentro.
|
# 0) Binario takana estático (musl, crt-static) — el builder lo bootea adentro.
|
||||||
HAMMER_BIN="target/x86_64-unknown-linux-musl/release/hammer"
|
HAMMER_BIN="target/x86_64-unknown-linux-musl/release/hammer"
|
||||||
say "build hammer estático ($HAMMER_BIN)"
|
say "build hammer estático ($HAMMER_BIN)"
|
||||||
cargo build --release --target x86_64-unknown-linux-musl -p takana-cli
|
cargo build --release --target x86_64-unknown-linux-musl -p takana-cli
|
||||||
@@ -71,16 +71,16 @@ say "semilla: $SEED_HASH"
|
|||||||
# 0c) Auto-alojamiento del COMPILADOR (variante b, pieza rust). A DIFERENCIA de make/busybox/bwrap/…
|
# 0c) Auto-alojamiento del COMPILADOR (variante b, pieza rust). A DIFERENCIA de make/busybox/bwrap/…
|
||||||
# (herramientas que ORQUESTAN o COPIAN ⇒ bytes idénticos), **rustc EMITE los binarios del 4/4**
|
# (herramientas que ORQUESTAN o COPIAN ⇒ bytes idénticos), **rustc EMITE los binarios del 4/4**
|
||||||
# (arje-zero, hammerd): un rustc distinto ⇒ of_tree DIVERGE del baseline Alpine 9adefb82. Por eso
|
# (arje-zero, hammerd): un rustc distinto ⇒ of_tree DIVERGE del baseline Alpine 9adefb82. Por eso
|
||||||
# el criterio no es igualdad con Alpine sino AUTO-CONSISTENCIA: el REF se RECOMPUTA con hammer-rust
|
# el criterio no es igualdad con Alpine sino AUTO-CONSISTENCIA: el REF se RECOMPUTA con takana-rust
|
||||||
# (nuevo EXPECT_REF) y la VM debe reproducir ESE. El swap entra en $TOOLCHAIN, que sirve TANTO al
|
# (nuevo EXPECT_REF) y la VM debe reproducir ESE. El swap entra en $TOOLCHAIN, que sirve TANTO al
|
||||||
# build host del REF (este script, abajo) COMO al toolchain in-VM del builder (--toolchain); se
|
# build host del REF (este script, abajo) COMO al toolchain in-VM del builder (--toolchain); se
|
||||||
# restaura al salir (trap). hammer-rust se construye con scripts/rust-frontier (climb mrustc→1.91.1).
|
# restaura al salir (trap). takana-rust se construye con scripts/rust-frontier (climb mrustc→1.91.1).
|
||||||
# SWAP_RUST=1 → overlay .scratch/rust-1.91.1-prefix sobre /toolchain/usr/{bin,lib}.
|
# SWAP_RUST=1 → overlay .scratch/rust-1.91.1-prefix sobre /toolchain/usr/{bin,lib}.
|
||||||
# RUST_PREFIX=DIR → prefix hammer-rust alternativo (default .scratch/rust-1.91.1-prefix).
|
# RUST_PREFIX=DIR → prefix takana-rust alternativo (default .scratch/rust-1.91.1-prefix).
|
||||||
# RUST_EXPECT_REF=… → REF conocido-bueno de hammer-rust (cross-check; vacío ⇒ sólo lo imprime).
|
# RUST_EXPECT_REF=… → REF conocido-bueno de takana-rust (cross-check; vacío ⇒ sólo lo imprime).
|
||||||
# ⚠️ Usá PRESEED=hammerd con SWAP_RUST: arje-zero (monorepo tawasuyu) vendorea ~1973 crates;
|
# ⚠️ Usá PRESEED=hammerd con SWAP_RUST: arje-zero (monorepo tawasuyu) vendorea ~1973 crates;
|
||||||
# en un rebuild in-VM completo (PRESEED=all) ese vendor desborda el rootfs en RAM de la VM
|
# en un rebuild in-VM completo (PRESEED=all) ese vendor desborda el rootfs en RAM de la VM
|
||||||
# (ENOSPC). PRESEED=hammerd preseedea el arje-zero host-built (hammer-rust, locked) y sólo
|
# (ENOSPC). PRESEED=hammerd preseedea el arje-zero host-built (takana-rust, locked) y sólo
|
||||||
# reconstruye hammerd in-VM. ✓ REPRODUCIBLE verificado así (2026-06-18, of_tree 7fa6cb4e).
|
# reconstruye hammerd in-VM. ✓ REPRODUCIBLE verificado así (2026-06-18, of_tree 7fa6cb4e).
|
||||||
if [[ "${SWAP_RUST:-0}" == 1 ]]; then
|
if [[ "${SWAP_RUST:-0}" == 1 ]]; then
|
||||||
RUST_PREFIX="${RUST_PREFIX:-.scratch/rust-1.91.1-prefix}"
|
RUST_PREFIX="${RUST_PREFIX:-.scratch/rust-1.91.1-prefix}"
|
||||||
@@ -91,11 +91,11 @@ if [[ "${SWAP_RUST:-0}" == 1 ]]; then
|
|||||||
# OJO: el input-hash del store NO incluye el rustc (recipe.hash_inputs = source+compiler+target+
|
# OJO: el input-hash del store NO incluye el rustc (recipe.hash_inputs = source+compiler+target+
|
||||||
# link+patches+flags+phases+deps), así que en el ./store compartido arje-zero/hammerd quedarían
|
# link+patches+flags+phases+deps), así que en el ./store compartido arje-zero/hammerd quedarían
|
||||||
# CACHEADOS con los bytes de Alpine y el swap sería un no-op. Usamos un store DEDICADO (store-rust)
|
# CACHEADOS con los bytes de Alpine y el swap sería un no-op. Usamos un store DEDICADO (store-rust)
|
||||||
# para forzar el rebuild de los 4/4 con hammer-rust; así el of_tree refleja el compilador nuevo.
|
# para forzar el rebuild de los 4/4 con takana-rust; así el of_tree refleja el compilador nuevo.
|
||||||
STORE="${RUST_STORE:-store-rust}"
|
STORE="${RUST_STORE:-store-rust}"
|
||||||
say "SWAP_RUST: store dedicado $STORE (el ./store baseline no se toca; fuerza rebuild con hammer-rust)"
|
say "SWAP_RUST: store dedicado $STORE (el ./store baseline no se toca; fuerza rebuild con hammer-rust)"
|
||||||
# Con hammer-rust el REF NO es el 9adefb82 de Alpine; comparamos contra RUST_EXPECT_REF, el
|
# Con takana-rust el REF NO es el 9adefb82 de Alpine; comparamos contra RUST_EXPECT_REF, el
|
||||||
# of_tree(stage1) auto-consistente de hammer-rust 1.91.1 (reproducido 2× en host, 2026-06-17,
|
# of_tree(stage1) auto-consistente de takana-rust 1.91.1 (reproducido 2× en host, 2026-06-17,
|
||||||
# store-rust y store-rust2). Override con RUST_EXPECT_REF= para re-anclar.
|
# store-rust y store-rust2). Override con RUST_EXPECT_REF= para re-anclar.
|
||||||
EXPECT_REF="${RUST_EXPECT_REF:-b3:7fa6cb4e70a934d72206cf3d95cf46a13f0a6464ec73855b98d547195f4ed047}"
|
EXPECT_REF="${RUST_EXPECT_REF:-b3:7fa6cb4e70a934d72206cf3d95cf46a13f0a6464ec73855b98d547195f4ed047}"
|
||||||
fi
|
fi
|
||||||
@@ -143,10 +143,10 @@ for m in overlay e1000; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
# 3b) Auto-alojamiento *puro* (variante b, SDD 11 §7.2b): reemplazar piezas del toolchain Alpine por
|
# 3b) Auto-alojamiento *puro* (variante b, SDD 11 §7.2b): reemplazar piezas del toolchain Alpine por
|
||||||
# recetas hammer construidas desde fuente, con Stage 2 reverificando que `of_tree(stage1')` NO
|
# recetas takana construidas desde fuente, con Stage 2 reverificando que `of_tree(stage1')` NO
|
||||||
# cambia (el make hammer compila los 4/4 igual de bit-a-bit que el de Alpine). Opt-in:
|
# cambia (el make takana compila los 4/4 igual de bit-a-bit que el de Alpine). Opt-in:
|
||||||
# SWAP_MAKE=1 → construye recipes/make.toml y lo monta sobre /toolchain/usr/bin/make.
|
# SWAP_MAKE=1 → construye recipes/make.toml y lo monta sobre /toolchain/usr/bin/make.
|
||||||
# SWAP_BUSYBOX=1 → monta el busybox de hammer sobre /toolchain/bin/busybox (los symlinks de
|
# SWAP_BUSYBOX=1 → monta el busybox de takana sobre /toolchain/bin/busybox (los symlinks de
|
||||||
# applets de Alpine — sh/sed/grep/awk/tar/find — pasan a usarlo; cp/mkdir/
|
# applets de Alpine — sh/sed/grep/awk/tar/find — pasan a usarlo; cp/mkdir/
|
||||||
# install siguen siendo GNU coreutils, intactos).
|
# install siguen siendo GNU coreutils, intactos).
|
||||||
# SWAP_LINUX_HEADERS=1 → construye recipes/linux-headers.toml y swap-directorio de los 13 subdirs
|
# SWAP_LINUX_HEADERS=1 → construye recipes/linux-headers.toml y swap-directorio de los 13 subdirs
|
||||||
@@ -195,7 +195,7 @@ if [[ "${SWAP_BWRAP:-0}" == 1 ]]; then
|
|||||||
# Pieza 4: bwrap (bubblewrap), EL sandbox del lab. Binario estático ⇒ swap de archivo sobre
|
# Pieza 4: bwrap (bubblewrap), EL sandbox del lab. Binario estático ⇒ swap de archivo sobre
|
||||||
# /toolchain/usr/bin/bwrap. Su dep libcap la construye y materializa el lab solo (deps.build).
|
# /toolchain/usr/bin/bwrap. Su dep libcap la construye y materializa el lab solo (deps.build).
|
||||||
# bwrap es herramienta, no input del 4/4: no necesita casar byte-a-byte con Alpine, sólo aislar
|
# bwrap es herramienta, no input del 4/4: no necesita casar byte-a-byte con Alpine, sólo aislar
|
||||||
# igual (validado en host — musl rebuildeó byte-idéntico bajo hammer-bwrap).
|
# igual (validado en host — musl rebuildeó byte-idéntico bajo takana-bwrap).
|
||||||
say "variante b — construir bwrap (+libcap) desde fuente y swapearlo en /toolchain/usr/bin/bwrap"
|
say "variante b — construir bwrap (+libcap) desde fuente y swapearlo en /toolchain/usr/bin/bwrap"
|
||||||
BW_HASH="$("$HAMMER" --store "$STORE" build recipes/bwrap.toml | grep -oE 'b3:[0-9a-f]{64}' | tail -1)"
|
BW_HASH="$("$HAMMER" --store "$STORE" build recipes/bwrap.toml | grep -oE 'b3:[0-9a-f]{64}' | tail -1)"
|
||||||
[[ "$BW_HASH" == b3:* ]] || die "no obtuve el hash sellado de bwrap"
|
[[ "$BW_HASH" == b3:* ]] || die "no obtuve el hash sellado de bwrap"
|
||||||
@@ -206,7 +206,7 @@ if [[ "${SWAP_COREUTILS:-0}" == 1 ]]; then
|
|||||||
# Pieza 5: GNU coreutils (cp/mkdir/ln/chmod/mv/install…). Multicall (--enable-single-binary), igual
|
# Pieza 5: GNU coreutils (cp/mkdir/ln/chmod/mv/install…). Multicall (--enable-single-binary), igual
|
||||||
# layout que Alpine: un binario /bin/coreutils + ~100 symlinks. UN swap del binario rutea todos los
|
# layout que Alpine: un binario /bin/coreutils + ~100 symlinks. UN swap del binario rutea todos los
|
||||||
# applets (los symlinks del toolchain ya apuntan a coreutils). Tool, no input: validado en host —
|
# applets (los symlinks del toolchain ya apuntan a coreutils). Tool, no input: validado en host —
|
||||||
# musl Y busybox rebuildearon byte-idéntico bajo hammer-coreutils.
|
# musl Y busybox rebuildearon byte-idéntico bajo takana-coreutils.
|
||||||
say "variante b — construir coreutils desde fuente y swapearlo en /toolchain/bin/coreutils"
|
say "variante b — construir coreutils desde fuente y swapearlo en /toolchain/bin/coreutils"
|
||||||
CU_HASH="$("$HAMMER" --store "$STORE" build recipes/coreutils.toml | grep -oE 'b3:[0-9a-f]{64}' | tail -1)"
|
CU_HASH="$("$HAMMER" --store "$STORE" build recipes/coreutils.toml | grep -oE 'b3:[0-9a-f]{64}' | tail -1)"
|
||||||
[[ "$CU_HASH" == b3:* ]] || die "no obtuve el hash sellado de coreutils"
|
[[ "$CU_HASH" == b3:* ]] || die "no obtuve el hash sellado de coreutils"
|
||||||
@@ -235,7 +235,7 @@ if [[ "$PRESEED" == "hammerd" ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# 4c) HAMMER_KERNEL=1 — wrapper /init para escapar del rootfs (frente kernel-from-source).
|
# 4c) HAMMER_KERNEL=1 — wrapper /init para escapar del rootfs (frente kernel-from-source).
|
||||||
# Con un kernel hammer-built (recipes/linux.toml) el `/` del initramfs es el rootfs ABSOLUTO del
|
# Con un kernel takana-built (recipes/linux.toml) el `/` del initramfs es el rootfs ABSOLUTO del
|
||||||
# mount-namespace (su propio padre, no movible) y bwrap del sandbox falla en `pivot_root: Invalid
|
# mount-namespace (su propio padre, no movible) y bwrap del sandbox falla en `pivot_root: Invalid
|
||||||
# argument` (el kernel host no lo exigía — quirk suyo). El fix portable (funciona en cualquier
|
# argument` (el kernel host no lo exigía — quirk suyo). El fix portable (funciona en cualquier
|
||||||
# kernel): un /init PID1 que copia el rootfs a un tmpfs y hace `switch_root`, dejando `/` como un
|
# kernel): un /init PID1 que copia el rootfs a un tmpfs y hace `switch_root`, dejando `/` como un
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# ssh-e2e-test.sh — SPIKE de validación (sucio, temporal) del Paso 1: probar el handshake SSH REAL
|
# ssh-e2e-test.sh — SPIKE de validación (sucio, temporal) del Paso 1: probar el handshake SSH REAL
|
||||||
# contra un hammer booteado en QEMU, con sshd supervisado por arje-zero como genesis card.
|
# contra un takana booteado en QEMU, con sshd supervisado por arje-zero como genesis card.
|
||||||
#
|
#
|
||||||
# Esto NO es plomería de producto: arma un `work/rootfs-ssh-test` desechable = el 4/4 limpio del
|
# Esto NO es plomería de producto: arma un `work/rootfs-ssh-test` desechable = el 4/4 limpio del
|
||||||
# store + openssh + netup (todos PRECOMPILADOS de la caché del lab, no rebuild) + una seed con un
|
# store + openssh + netup (todos PRECOMPILADOS de la caché del lab, no rebuild) + una seed con un
|
||||||
@@ -78,7 +78,7 @@ chmod 0600 "$RFS/root/.ssh/authorized_keys"
|
|||||||
|
|
||||||
# ── 3) seed card: console-getty + un card `sshd` (Native, Restart) ───────────────────────────────
|
# ── 3) seed card: console-getty + un card `sshd` (Native, Restart) ───────────────────────────────
|
||||||
# El card sshd arranca la red (netup, DHCP slirp), genera host keys (ssh-keygen -A) y exec sshd -D.
|
# El card sshd arranca la red (netup, DHCP slirp), genera host keys (ssh-keygen -A) y exec sshd -D.
|
||||||
# Mismo esquema validado de STAGE1_SEED_CARD (hammer-bootstrap); ULIDs nuevos A10/A11/A12.
|
# Mismo esquema validado de STAGE1_SEED_CARD (takana-bootstrap); ULIDs nuevos A10/A11/A12.
|
||||||
SSHD_CMD='/usr/bin/netup; /usr/bin/ssh-keygen -A; exec /usr/sbin/sshd -D -e'
|
SSHD_CMD='/usr/bin/netup; /usr/bin/ssh-keygen -A; exec /usr/sbin/sshd -D -e'
|
||||||
cat > "$RFS/ente/seed.card.json" <<EOF
|
cat > "$RFS/ente/seed.card.json" <<EOF
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
# RELINKEA al instalar, así que sólo en compile no basta), nunca en configure. Patrón ya usado en
|
# RELINKEA al instalar, así que sólo en compile no basta), nunca en configure. Patrón ya usado en
|
||||||
# jq/parted/shadow/procps-ng.
|
# jq/parted/shadow/procps-ng.
|
||||||
#
|
#
|
||||||
# Por qué esto es un script y no un gate duro dentro de `hammer build`: hacerlo fallar hoy rompe
|
# Por qué esto es un script y no un gate duro dentro de `takana build`: hacerlo fallar hoy rompe
|
||||||
# 28 recetas selladas de golpe, varias del sistema base (curl, util-linux, sudo). Primero se
|
# 28 recetas selladas de golpe, varias del sistema base (curl, util-linux, sudo). Primero se
|
||||||
# arreglan con evidencia, después se cierra la puerta. Mientras tanto esto es la evidencia.
|
# arreglan con evidencia, después se cierra la puerta. Mientras tanto esto es la evidencia.
|
||||||
#
|
#
|
||||||
@@ -50,14 +50,14 @@ mienten=0; honestos=0; sin=0
|
|||||||
for f in $recetas; do
|
for f in $recetas; do
|
||||||
n=$(basename "$f" .toml)
|
n=$(basename "$f" .toml)
|
||||||
grep -qE '^[[:space:]]*link[[:space:]]*=[[:space:]]*"static"' "$f" || continue
|
grep -qE '^[[:space:]]*link[[:space:]]*=[[:space:]]*"static"' "$f" || continue
|
||||||
# EL ARTEFACTO VIGENTE, por hash — NO el más reciente por mtime. `hammer hash` calcula el
|
# EL ARTEFACTO VIGENTE, por hash — NO el más reciente por mtime. `takana hash` calcula el
|
||||||
# ArtifactHash de la receta de HOY sin construir (~2ms, puro sobre las recetas). El store guarda
|
# ArtifactHash de la receta de HOY sin construir (~2ms, puro sobre las recetas). El store guarda
|
||||||
# TODOS los sellados históricos de una receta (expat tenía 5); auditar el más reciente por mtime
|
# TODOS los sellados históricos de una receta (expat tenía 5); auditar el más reciente por mtime
|
||||||
# sobre-reportaba (acusaba a dbus/libnl, ya sanas, por un sellado anterior a sus flags). Ahora
|
# sobre-reportaba (acusaba a dbus/libnl, ya sanas, por un sellado anterior a sus flags). Ahora
|
||||||
# auditamos EXACTAMENTE el sellado que corresponde a la receta actual, o ninguno.
|
# auditamos EXACTAMENTE el sellado que corresponde a la receta actual, o ninguno.
|
||||||
#
|
#
|
||||||
# Fallback a `ls -dt` si `hammer` no está compilado: el audit sigue corriendo, sólo vuelve a
|
# Fallback a `ls -dt` si `takana` no está compilado: el audit sigue corriendo, sólo vuelve a
|
||||||
# poder sobre-reportar (como antes de que existiera `hammer hash`).
|
# poder sobre-reportar (como antes de que existiera `takana hash`).
|
||||||
if [ -x "$HAMMER" ]; then
|
if [ -x "$HAMMER" ]; then
|
||||||
h=$("$HAMMER" --store "$STORE" hash "$f" 2>/dev/null) || h=""
|
h=$("$HAMMER" --store "$STORE" hash "$f" 2>/dev/null) || h=""
|
||||||
if [ -n "$h" ] && [ -d "$STORE/${h#b3:}-$n" ]; then
|
if [ -n "$h" ] && [ -d "$STORE/${h#b3:}-$n" ]; then
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# store-gc.sh — recolector de basura del store content-addressed. `hammer gc` no existe; esto es.
|
# store-gc.sh — recolector de basura del store content-addressed. `takana gc` no existe; esto es.
|
||||||
#
|
#
|
||||||
# ── EL PROBLEMA QUE RESUELVE ────────────────────────────────────────────────────────────────────
|
# ── EL PROBLEMA QUE RESUELVE ────────────────────────────────────────────────────────────────────
|
||||||
# El store acumula un artefacto por cada SELLADO, no uno por receta. Cuando una dep cambia, el
|
# El store acumula un artefacto por cada SELLADO, no uno por receta. Cuando una dep cambia, el
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
# `libqalculate`, 9 de `qt6-qtdeclarative`, 8 de `gtk4`. 51G de los 74G eran versiones anteriores.
|
# `libqalculate`, 9 de `qt6-qtdeclarative`, 8 de `gtk4`. 51G de los 74G eran versiones anteriores.
|
||||||
#
|
#
|
||||||
# ── EL CRITERIO, Y POR QUÉ TIENE DOS ESCALONES ──────────────────────────────────────────────────
|
# ── EL CRITERIO, Y POR QUÉ TIENE DOS ESCALONES ──────────────────────────────────────────────────
|
||||||
# El conjunto VIVO es `hammer hash` sobre TODAS las recetas de TODAS las colas: es la respuesta a
|
# El conjunto VIVO es `takana hash` sobre TODAS las recetas de TODAS las colas: es la respuesta a
|
||||||
# «¿cuál es el hash vigente de esta receta HOY?», que el store solo no puede dar. Lo que no está en
|
# «¿cuál es el hash vigente de esta receta HOY?», que el store solo no puede dar. Lo que no está en
|
||||||
# ese conjunto es RANCIO — pero rancio se parte en dos cosas muy distintas:
|
# ese conjunto es RANCIO — pero rancio se parte en dos cosas muy distintas:
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ def fatal(msg):
|
|||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
|
||||||
# ── El artefacto se resuelve por `hammer hash`, NUNCA por glob ────────────────────────────────
|
# ── El artefacto se resuelve por `takana hash`, NUNCA por glob ────────────────────────────────
|
||||||
# Con dos artefactos de la misma receta conviviendo en el store, `ls | head -1` es una ruleta: se
|
# Con dos artefactos de la misma receta conviviendo en el store, `ls | head -1` es una ruleta: se
|
||||||
# puede estar probando el de ayer y leerlo como éxito. La receta dice cuál es el vigente.
|
# puede estar probando el de ayer y leerlo como éxito. La receta dice cuál es el vigente.
|
||||||
def artefacto(receta, nombre):
|
def artefacto(receta, nombre):
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
# POR QUÉ EXISTE. Un guardián que nunca falló no se sabe si sirve, y uno que falla SIEMPRE se ve
|
# POR QUÉ EXISTE. Un guardián que nunca falló no se sabe si sirve, y uno que falla SIEMPRE se ve
|
||||||
# idéntico a uno que funciona: por eso el control no es un extra, es la mitad de la prueba. El
|
# idéntico a uno que funciona: por eso el control no es un extra, es la mitad de la prueba. El
|
||||||
# método lo aportó la sesión hammer-f8 (su scripts/test-atuq-politica.py hace lo mismo con el cruce
|
# método lo aportó la sesión takana-f8 (su scripts/test-atuq-politica.py hace lo mismo con el cruce
|
||||||
# política↔XPI).
|
# política↔XPI).
|
||||||
#
|
#
|
||||||
# NO CONSTRUYE NADA, NO TOMA EL LOCK Y NO ESCRIBE EN EL STORE: trabaja sobre copias temporales de
|
# NO CONSTRUYE NADA, NO TOMA EL LOCK Y NO ESCRIBE EN EL STORE: trabaja sobre copias temporales de
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@
|
|||||||
# triaje.py — convierte los CANDIDATOS de la frontera en VEREDICTOS durables. (P5 del plan
|
# triaje.py — convierte los CANDIDATOS de la frontera en VEREDICTOS durables. (P5 del plan
|
||||||
# docs/plan-catalogo-objetivo.md.)
|
# docs/plan-catalogo-objetivo.md.)
|
||||||
#
|
#
|
||||||
# POR QUÉ. `seed-graph.py --frontera` produce hipótesis: 137 nombres que nixpkgs pide y hammer no
|
# POR QUÉ. `seed-graph.py --frontera` produce hipótesis: 137 nombres que nixpkgs pide y takana no
|
||||||
# puede construir. Clasificarlos es decisión HUMANA (la regla de la granja: el worker MIDE, el hub
|
# puede construir. Clasificarlos es decisión HUMANA (la regla de la granja: el worker MIDE, el hub
|
||||||
# CLASIFICA). Pero si ese juicio se queda en la cabeza o en un mensaje, se repite entero cada vez que
|
# CLASIFICA). Pero si ese juicio se queda en la cabeza o en un mensaje, se repite entero cada vez que
|
||||||
# alguien vuelve a correr el sembrador. Este fichero lo hace durable y consumible por máquina.
|
# alguien vuelve a correr el sembrador. Este fichero lo hace durable y consumible por máquina.
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
# TRES VEREDICTOS, tres destinos distintos — y ahí está el valor, porque cada uno CIERRA un lazo:
|
# TRES VEREDICTOS, tres destinos distintos — y ahí está el valor, porque cada uno CIERRA un lazo:
|
||||||
# hueco → falta de verdad ⇒ va como raíz a `targets.toml` y nace un nodo `wanted` en el grafo,
|
# hueco → falta de verdad ⇒ va como raíz a `targets.toml` y nace un nodo `wanted` en el grafo,
|
||||||
# que el sembrador siembra y el drenaje ordena. Es lo que da trabajo nuevo al worker.
|
# que el sembrador siembra y el drenaje ordena. Es lo que da trabajo nuevo al worker.
|
||||||
# opcional → dep que nixpkgs habilita y hammer no quiere (gstreamer en un escritorio sin audio).
|
# opcional → dep que nixpkgs habilita y takana no quiere (gstreamer en un escritorio sin audio).
|
||||||
# Queda registrada para que deje de reaparecer como pregunta.
|
# Queda registrada para que deje de reaparecer como pregunta.
|
||||||
# nix-ismo → andamiaje de nixpkgs sin contraparte acá ⇒ vuelve a `seed-graph.py` como descarte,
|
# nix-ismo → andamiaje de nixpkgs sin contraparte acá ⇒ vuelve a `seed-graph.py` como descarte,
|
||||||
# así la próxima corrida es más limpia. El sembrador aprende de su propio triaje.
|
# así la próxima corrida es más limpia. El sembrador aprende de su propio triaje.
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# E2E de la Etapa E4 (upgrades atómicos con rollback) contra el binario `hammer` REAL.
|
# E2E de la Etapa E4 (upgrades atómicos con rollback) contra el binario `takana` REAL.
|
||||||
#
|
#
|
||||||
# Monta un store sintético con dos árboles "producto" (v1, v2), un root FHS vivo, y ejercita:
|
# Monta un store sintético con dos árboles "producto" (v1, v2), un root FHS vivo, y ejercita:
|
||||||
# apply v1 → apply v2 → rollback → rollback, verificando el estado del root en cada paso.
|
# apply v1 → apply v2 → rollback → rollback, verificando el estado del root en cada paso.
|
||||||
# Todo en host, sin VM: valida el cableado del CLI + la semántica generación/rollback de hammer-upgrade.
|
# Todo en host, sin VM: valida el cableado del CLI + la semántica generación/rollback de takana-upgrade.
|
||||||
#
|
#
|
||||||
# Uso: scripts/upgrade-e2e-test.sh
|
# Uso: scripts/upgrade-e2e-test.sh
|
||||||
set -eu
|
set -eu
|
||||||
@@ -28,8 +28,8 @@ up() { "$HAMMER" --store "$STORE" upgrade --root "$ROOT" --state-root "$STATE" -
|
|||||||
printf 'PRISTINE-ls' > "$ROOT/usr/bin/ls"
|
printf 'PRISTINE-ls' > "$ROOT/usr/bin/ls"
|
||||||
printf 'motd original\n' > "$ROOT/etc/motd"
|
printf 'motd original\n' > "$ROOT/etc/motd"
|
||||||
|
|
||||||
# --- sella dos árboles producto sintéticos en el store (vía `hammer build`? no: usamos un mini-store
|
# --- sella dos árboles producto sintéticos en el store (vía `takana build`? no: usamos un mini-store
|
||||||
# a mano replicando la forma <64hex>-<name>; el of_tree lo computa hammer al aplicar) ---
|
# a mano replicando la forma <64hex>-<name>; el of_tree lo computa takana al aplicar) ---
|
||||||
seal_tree() {
|
seal_tree() {
|
||||||
# $1=hex64 $2=name $3=builder-fn
|
# $1=hex64 $2=name $3=builder-fn
|
||||||
dir="$STORE/$1-$2"
|
dir="$STORE/$1-$2"
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
# ── EL MÉTODO, Y POR QUÉ ES BARATO ─────────────────────────────────────────────────────────────
|
# ── EL MÉTODO, Y POR QUÉ ES BARATO ─────────────────────────────────────────────────────────────
|
||||||
# Se APARTA el artefacto (no se borra) y se reconstruye. Como las DEPS siguen en el store, el rebuild
|
# Se APARTA el artefacto (no se borra) y se reconstruye. Como las DEPS siguen en el store, el rebuild
|
||||||
# es sólo el paquete en cuestión, no su cadena — que es lo que hace viable verificar decenas. Después
|
# es sólo el paquete en cuestión, no su cadena — que es lo que hace viable verificar decenas. Después
|
||||||
# `hammer why-differs` compara los dos árboles y nombra la causa si divergen.
|
# `takana why-differs` compara los dos árboles y nombra la causa si divergen.
|
||||||
#
|
#
|
||||||
# ── LA RED DE SEGURIDAD ────────────────────────────────────────────────────────────────────────
|
# ── LA RED DE SEGURIDAD ────────────────────────────────────────────────────────────────────────
|
||||||
# Si el rebuild FALLA (y fallará en alguna: hay recetas que sólo construyen en ciertas máquinas), el
|
# Si el rebuild FALLA (y fallará en alguna: hay recetas que sólo construyen en ciertas máquinas), el
|
||||||
@@ -51,7 +51,7 @@ ROOT="$(cd "$(dirname "$0")/.." && pwd)"; cd "$ROOT"
|
|||||||
STORE="${STORE:-./store}"; HAMMER="${TAKANA:-${HAMMER:-./target/release/takana}}"; N="${N:-30}"
|
STORE="${STORE:-./store}"; HAMMER="${TAKANA:-${HAMMER:-./target/release/takana}}"; N="${N:-30}"
|
||||||
|
|
||||||
# ── EL LOCK LO TOMA EL SCRIPT, Y ANTES DE TOCAR NADA ───────────────────────────────────────────
|
# ── EL LOCK LO TOMA EL SCRIPT, Y ANTES DE TOCAR NADA ───────────────────────────────────────────
|
||||||
# Este script llama a `hammer build`, y la regla 1 del repo es que todo build va envuelto en el
|
# Este script llama a `takana build`, y la regla 1 del repo es que todo build va envuelto en el
|
||||||
# `flock` de la granja: dos builds que compartan una dep se pisan el árbol de `work/sources` y lo
|
# `flock` de la granja: dos builds que compartan una dep se pisan el árbol de `work/sources` y lo
|
||||||
# rompen PARA SIEMPRE (ADR 0012). Lo toma el script y no quien lo llama, por lo mismo que en
|
# rompen PARA SIEMPRE (ADR 0012). Lo toma el script y no quien lo llama, por lo mismo que en
|
||||||
# `poda-fuentes.sh`: así no hay forma de correrlo mal — y correrlo mal fue exactamente lo que pasó.
|
# `poda-fuentes.sh`: así no hay forma de correrlo mal — y correrlo mal fue exactamente lo que pasó.
|
||||||
@@ -68,7 +68,7 @@ if [ -z "${VERIFICAR_REPRO_CON_LOCK:-}" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# ── ⚠ EL APARTADERO VA DENTRO DEL STORE, NO EN /tmp ────────────────────────────────────────────
|
# ── ⚠ EL APARTADERO VA DENTRO DEL STORE, NO EN /tmp ────────────────────────────────────────────
|
||||||
# Para verificar hay que sacar el artefacto de su sitio y dejar que hammer lo reconstruya. Ese
|
# Para verificar hay que sacar el artefacto de su sitio y dejar que takana lo reconstruya. Ese
|
||||||
# `mv` era a un `mktemp -d`, o sea a `/tmp`, y ahí se juntan tres cosas que costaron un artefacto
|
# `mv` era a un `mktemp -d`, o sea a `/tmp`, y ahí se juntan tres cosas que costaron un artefacto
|
||||||
# el 2026-09-05:
|
# el 2026-09-05:
|
||||||
#
|
#
|
||||||
@@ -175,7 +175,7 @@ else
|
|||||||
# caliente puede tardar muchos minutos acá en frío — `angle-grinder` y `amp` entraron por el
|
# caliente puede tardar muchos minutos acá en frío — `angle-grinder` y `amp` entraron por el
|
||||||
# filtro y se comieron el disco. El tope acota el build DE ESA RECETA en LA MÁQUINA QUE LO
|
# filtro y se comieron el disco. El tope acota el build DE ESA RECETA en LA MÁQUINA QUE LO
|
||||||
# MIDIÓ, no acá.
|
# MIDIÓ, no acá.
|
||||||
# · Y no cuenta la CASCADA: `hammer build` reconstruye las deps que falten en el store local, y
|
# · Y no cuenta la CASCADA: `takana build` reconstruye las deps que falten en el store local, y
|
||||||
# eso no está en el tiempo del sidecar. Es la misma sorpresa que dio `gjs`, cuyo grafo decía
|
# eso no está en el tiempo del sidecar. Es la misma sorpresa que dio `gjs`, cuyo grafo decía
|
||||||
# «una receta» y se puso a rehacer spidermonkey entero.
|
# «una receta» y se puso a rehacer spidermonkey entero.
|
||||||
# ⇒ con disco justo, mejor pasar las recetas a mano que confiar en el tope.
|
# ⇒ con disco justo, mejor pasar las recetas a mano que confiar en el tope.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# vigia-parches.py — ¿los parches de la receta AGARRAN todavía en la fuente que la receta pinea?
|
# vigia-parches.py — ¿los parches de la receta AGARRAN todavía en la fuente que la receta pinea?
|
||||||
#
|
#
|
||||||
# ══ EL PUNTO CIEGO QUE ESTE VIGÍA CUBRE ════════════════════════════════════════════════════════
|
# ══ EL PUNTO CIEGO QUE ESTE VIGÍA CUBRE ════════════════════════════════════════════════════════
|
||||||
# `hammer build` aplica los parches DESPUÉS de materializar las dependencias. En una receta hoja de
|
# `takana build` aplica los parches DESPUÉS de materializar las dependencias. En una receta hoja de
|
||||||
# la plataforma Gecko eso significa que el `patch` que no agarra se descubre detrás de horas de
|
# la plataforma Gecko eso significa que el `patch` que no agarra se descubre detrás de horas de
|
||||||
# compilar OTRA COSA: waterfox estrena su primer build reconstruyendo nodejs (4414 objetivos de V8,
|
# compilar OTRA COSA: waterfox estrena su primer build reconstruyendo nodejs (4414 objetivos de V8,
|
||||||
# a `-j2` porque el propio recipe capa por RAM). El parche que falla es el paso 3 de un camino cuyo
|
# a `-j2` porque el propio recipe capa por RAM). El parche que falla es el paso 3 de un camino cuyo
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
# La receta de waterfox además hace una APUESTA EXPLÍCITA y escrita: la base es Gecko 153.1.0 y los
|
# La receta de waterfox además hace una APUESTA EXPLÍCITA y escrita: la base es Gecko 153.1.0 y los
|
||||||
# once parches de musl son los de Firefox 154, una release por encima. Su propio comentario dice
|
# once parches de musl son los de Firefox 154, una release por encima. Su propio comentario dice
|
||||||
# «si `patch` falla, falla TEMPRANO, antes de compilar nada». Con el orden real de `hammer build`
|
# «si `patch` falla, falla TEMPRANO, antes de compilar nada». Con el orden real de `takana build`
|
||||||
# eso no es cierto: falla tarde. Este vigía es lo que lo vuelve cierto.
|
# eso no es cierto: falla tarde. Este vigía es lo que lo vuelve cierto.
|
||||||
#
|
#
|
||||||
# ══ Y EL SEGUNDO PUNTO CIEGO, QUE ES EL CARO ═══════════════════════════════════════════════════
|
# ══ Y EL SEGUNDO PUNTO CIEGO, QUE ES EL CARO ═══════════════════════════════════════════════════
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user