diff --git a/.claude/skills/granja/SKILL.md b/.claude/skills/granja/SKILL.md index e8cc76b1..bcec774b 100644 --- a/.claude/skills/granja/SKILL.md +++ b/.claude/skills/granja/SKILL.md @@ -3,7 +3,7 @@ name: granja description: Cómo se compila en este proyecto — dónde está el worker, cómo se enchufa, y por qué NO se levantan cajas de pago. Usar al empezar cualquier trabajo de build, cosecha o estado de la granja. --- -# La granja de hammer +# La granja de takana ## Lo primero, porque cuesta dinero equivocarse @@ -32,7 +32,7 @@ worker vivo» aunque el worker esté compilando. Comprobar el fichero antes de c ## Reglas que no son estilo -1. **Todo `hammer build` bajo `flock -o work/.farm-build.lock`.** El `-o` no es opcional: sin él un +1. **Todo `takana build` bajo `flock -o work/.farm-build.lock`.** El `-o` no es opcional: sin él un proceso fugado hereda el fd y deja la granja sin compilar, en silencio. Ver regla 1 de CLAUDE.md. 2. **Un lock tomado sin build a la vista se diagnostica con `fuser -v work/.farm-build.lock`**, que nombra al fugado. Pasó dos veces el mismo día. diff --git a/CLAUDE.md b/CLAUDE.md index 81887b0f..5771db47 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ Este repo lo trabajan **varios agentes a la vez** (hoy: frente granja/store y fr aquí abajo no son preferencias de estilo: son las dos formas conocidas de que un agente destruya el trabajo de otro sin enterarse. El resto del diseño está en `docs/`. -## 1. Todo `hammer build` va envuelto en `flock` +## 1. Todo `takana build` va envuelto en `flock` ```sh flock work/.farm-build.lock ./target/release/takana --store ./store build @@ -16,7 +16,7 @@ Para una tanda, tomar el lock una sola vez y no por receta: flock work/.farm-build.lock bash -c 'for r in ...; do ./target/release/takana --store ./store build "$r"; done' ``` -**Por qué.** `hammer build` comparte `work/sources/-` entre todas las recetas. Dos builds +**Por qué.** `takana build` comparte `work/sources/-` entre todas las recetas. Dos builds concurrentes que compartan una dependencia se pisan el árbol de fuentes: uno hace fetch y lo borra mientras el otro lo usa, y **el árbol queda roto para siempre** — reintentar no lo arregla. Medido a escala: al invalidar libdrm, ~93 de 205 recetas KDE murieron con `/src/.zwrap/cc is not a full path @@ -43,8 +43,8 @@ el estilo `exec 9>` + `flock 9`, que es vulnerable igual** (haría falta `9>&-` conocida, no barrida. `scripts/farm/farm-worker-loop.sh` y `campana-deuda.sh` ya toman **ese mismo fichero de lock**, así -que usarlo nos serializa con la granja además de entre nosotros. **No está dentro de `hammer build` -a propósito**: esos scripts lo toman por fuera y hammer se bloquearía contra ellos. +que usarlo nos serializa con la granja además de entre nosotros. **No está dentro de `takana build` +a propósito**: esos scripts lo toman por fuera y takana se bloquearía contra ellos. ## 1 bis. El worker es el LXC PRESTADO, y es GRATIS: no se levanta nada en Hetzner diff --git a/crates/hammerd/Cargo.toml b/crates/hammerd/Cargo.toml index 2f453254..c3bf11c7 100644 --- a/crates/hammerd/Cargo.toml +++ b/crates/hammerd/Cargo.toml @@ -5,7 +5,7 @@ edition.workspace = true license.workspace = true authors.workspace = true repository.workspace = true -description = "Daemon de hammer: bus de agente (/run/agent.sock) y diario de mutaciones (fanotify)." +description = "Daemon de takana: bus de agente (/run/agent.sock) y diario de mutaciones (fanotify)." [[bin]] name = "hammerd" diff --git a/crates/hammerd/src/arje_link.rs b/crates/hammerd/src/arje_link.rs index bebf744f..8f0beeed 100644 --- a/crates/hammerd/src/arje_link.rs +++ b/crates/hammerd/src/arje_link.rs @@ -1,14 +1,14 @@ -//! Adaptador de transporte arje-bus → bus de agente de hammer (último tramo de B.2). +//! Adaptador de transporte arje-bus → bus de agente de takana (último tramo de B.2). //! //! arje (el init/PID 1) supervisa cada Ente y, al morir, difunde `BusEvent` por su bus //! (`arje-bus`: `BusRequest::Subscribe` + `BusPayload::Event`). Este módulo se **suscribe** a -//! ese stream y traduce cada evento al vocabulario de hammer (`crashes::Lifecycle` → +//! ese stream y traduce cada evento al vocabulario de takana (`crashes::Lifecycle` → //! `Event::Crashed`), publicándolo en el [`EventBus`] → `/run/agent.sock` → la capa de IA. //! //! ## Por qué un mirror y no una dependencia de `arje-bus` //! //! `arje-bus` arrastra el grafo de crates de arje (arje-card → card-core → …). Acoplarlo aquí -//! rompería el build hermético/standalone de hammer. En su lugar **releemos el frame postcard**: +//! rompería el build hermético/standalone de takana. En su lugar **releemos el frame postcard**: //! el bus usa frames `u32-BE-len + postcard(BusMessage)`, y reproducimos sólo el subconjunto que //! un suscriptor necesita. El layout está verificado byte-a-byte contra `arje-bus` real (mismas //! versiones de `ulid` 1.2 y `postcard` 1.1; `ulid` serializa como string). Si arje reordena las @@ -90,7 +90,7 @@ enum LifecycleStatus { } impl BusEvent { - /// Traduce el evento de arje a la señal normalizada de hammer. El `label` del Ente es el + /// Traduce el evento de arje a la señal normalizada de takana. El `label` del Ente es el /// `service`; una muerte por señal usa la convención de shell `128 + signum` para que el /// código sea siempre ≠ 0. `None` = evento consumido sin señal (Parked/Refloored: son /// vaivén del piso gráfico, no ciclo de vida que le importe a la capa de IA). diff --git a/crates/hammerd/src/control.rs b/crates/hammerd/src/control.rs index 7f486b5f..04b9e14e 100644 --- a/crates/hammerd/src/control.rs +++ b/crates/hammerd/src/control.rs @@ -32,7 +32,7 @@ pub fn ensure_fifo(path: &Path) -> std::io::Result { Err(e) => return Err(e), } // `nix::unistd::mkfifo` con permisos 0o660: owner + group escriben/leen, world nada. - // El humano normalmente está en el grupo del daemon (p. ej. `hammer`); la IA agente + // El humano normalmente está en el grupo del daemon (p. ej. `takana`); la IA agente // entra por el socket. use nix::sys::stat::Mode; nix::unistd::mkfifo(path, Mode::S_IRUSR | Mode::S_IWUSR | Mode::S_IRGRP | Mode::S_IWGRP) diff --git a/crates/hammerd/src/crashes.rs b/crates/hammerd/src/crashes.rs index b66ac43c..31b39c5f 100644 --- a/crates/hammerd/src/crashes.rs +++ b/crates/hammerd/src/crashes.rs @@ -8,7 +8,7 @@ //! //! Este módulo es el **sink** de ese flujo (B.2 "exponer el CRASHED a la capa de IA"): //! traduce la señal de ciclo de vida normalizada al vocabulario del bus de agente de -//! hammer (`Event::Crashed`) y la bombea al [`EventBus`] → toda conexión del +//! takana (`Event::Crashed`) y la bombea al [`EventBus`] → toda conexión del //! `/run/agent.sock` (la capa de IA) la recibe. //! //! ## Frontera de acoplamiento diff --git a/crates/hammerd/src/main.rs b/crates/hammerd/src/main.rs index 7316f266..6b367c44 100644 --- a/crates/hammerd/src/main.rs +++ b/crates/hammerd/src/main.rs @@ -1,5 +1,5 @@ -//! `hammerd` — daemon de hammer. Tres responsabilidades: -//! 1. Diario de mutaciones: fanotify sobre /bin,/sbin,/lib,/etc → `hammer-journal`. +//! `hammerd` — daemon de takana. Tres responsabilidades: +//! 1. Diario de mutaciones: fanotify sobre /bin,/sbin,/lib,/etc → `takana-journal`. //! 2. FIFO de control humano: `/run/init.control` (texto crudo, una línea por comando). //! 3. Bus de agente: `/run/agent.sock` (JSON-líneas, SO_PEERCRED). Ver `docs/07-agent-bus.md`. //! @@ -20,7 +20,7 @@ mod events; mod watcher; #[derive(Parser)] -#[command(name = "hammerd", version, about = "Daemon de hammer: bus de agente + diario.")] +#[command(name = "hammerd", version, about = "Daemon de takana: bus de agente + diario.")] struct Args { /// Socket del bus de agente. #[arg(long, default_value = "/run/agent.sock")] @@ -32,7 +32,7 @@ struct Args { #[arg(long, default_value = "/var/lib/hammer/journal")] journal: String, /// Directorio raíz de overlays (para que el watcher pueda filtrar eventos bajo overlays - /// activos). Default coincide con `hammer try`. + /// activos). Default coincide con `takana try`. #[arg(long, default_value = takana_overlay::DEFAULT_STATE_ROOT)] overlay_state_root: String, /// Directorios extra a vigilar; si vacío, usa los defaults del FHS (SDD 05 §2). diff --git a/crates/hammerd/src/watcher.rs b/crates/hammerd/src/watcher.rs index f451fc60..c71da680 100644 --- a/crates/hammerd/src/watcher.rs +++ b/crates/hammerd/src/watcher.rs @@ -11,7 +11,7 @@ //! * Cada evento se materializa como `MutationEvent` con `source = External` y la `op` //! se deriva (`classify_op`): si el fd resuelve a un path borrado (`" (deleted)"`) es //! `Delete`; si el diario ya conocía ese path (con un evento previo no-`Delete`) es -//! `Edit`; en otro caso es `Create` (primera mutación que hammer observa sobre el path). +//! `Edit`; en otro caso es `Create` (primera mutación que takana observa sobre el path). //! Nota: `FAN_CLOSE_WRITE` no distingue un `rename`-sobre-destino de una reescritura in //! situ, ni reporta el nombre en eventos de directorio — la atribución plena de //! `Create`/`Move`/`Delete` vía `FAN_REPORT_DFID_NAME` (con `open_by_handle_at` y @@ -203,7 +203,7 @@ impl Watcher { /// * `deleted` (el fd resuelve a `" (deleted)"`) ⇒ `Delete`. /// * el diario ya tiene un evento previo no-`Delete` para el path ⇒ `Edit` (el archivo /// ya era conocido y se reescribió). - /// * en otro caso ⇒ `Create` — la primera mutación que hammer observa sobre el path, o + /// * en otro caso ⇒ `Create` — la primera mutación que takana observa sobre el path, o /// una resurrección tras un `Delete` previo. /// /// No es una verdad absoluta del FS (un archivo preexistente al daemon, editado por diff --git a/crates/hammerd/tests/bus_e2e.rs b/crates/hammerd/tests/bus_e2e.rs index 1cc5b29b..85c088f9 100644 --- a/crates/hammerd/tests/bus_e2e.rs +++ b/crates/hammerd/tests/bus_e2e.rs @@ -8,7 +8,7 @@ //! capacidad devuelve `Error{code:"no_cap"}`, lo que prueba el dispatcher + el gate. // El binario no expone una API pública; importamos sus módulos privados desde -// `path = ...`. `proto` se movió a hammer-core en Fase 6. +// `path = ...`. `proto` se movió a takana-core en Fase 6. #[path = "../src/events.rs"] mod events; #[path = "../src/control.rs"] diff --git a/crates/netup/src/main.rs b/crates/netup/src/main.rs index 8b70609f..8833a29a 100644 --- a/crates/netup/src/main.rs +++ b/crates/netup/src/main.rs @@ -1,9 +1,9 @@ -//! netup — configuración de red mínima Rust-nativa para el userland de hammer (Etapa C). +//! netup — configuración de red mínima Rust-nativa para el userland de takana (Etapa C). //! //! Reemplaza el `ip` de busybox + la IP estática hardcodeada del driver de rebuild por un binario //! propio: levanta la interfaz, negocia un lease DHCPv4 y aplica IP/ruta/DNS vía netlink — todo //! síncrono, sin tokio, dependiendo sólo de libc (ABI estable del kernel). Como hammerd/arje, es -//! código hammer-propio: no hay un cliente DHCP Rust "maduro" para adoptar al estilo ripgrep. +//! código takana-propio: no hay un cliente DHCP Rust "maduro" para adoptar al estilo ripgrep. //! //! Uso: `netup [interfaz]` (sin argumento, autodetecta la primera interfaz no-loopback). diff --git a/crates/takana-agent/src/orchestrator.rs b/crates/takana-agent/src/orchestrator.rs index 5d55249f..5afd4159 100644 --- a/crates/takana-agent/src/orchestrator.rs +++ b/crates/takana-agent/src/orchestrator.rs @@ -8,12 +8,12 @@ //! base → swm.verify_base(local) → debe ser Ok //! build → para cada source_patch: AgentClient.compile() vía el bus (o saltar si --no-bus) //! try → takana_overlay::try_overlay() (o usar --prefix) -//! apply → hammer-core::apply para config_edit/file_drop + hydrate para source_patch +//! apply → takana-core::apply para config_edit/file_drop + hydrate para source_patch //! verify → spot-checks post-condición sobre disco //! propose → devuelve Proposal con overlay_id + log de checks //! ``` //! -//! La IA NUNCA ejecuta `hammer commit`. El humano lo hace tras revisar el `Proposal`. +//! La IA NUNCA ejecuta `takana commit`. El humano lo hace tras revisar el `Proposal`. use std::path::{Path, PathBuf}; use std::time::Duration; @@ -101,7 +101,7 @@ impl Orchestrator { }; // 5. APPLY — recorremos las mutaciones en orden. En source_patch, dispatch al bus - // o skip; en config_edit/file_drop, primitivas de hammer-core::apply. + // o skip; en config_edit/file_drop, primitivas de takana-core::apply. let mut applied = AppliedCounts::default(); let mut checks: Vec = Vec::new(); let mut skipped_source_patches = 0usize; @@ -356,10 +356,10 @@ fn wait_for_crash(policy: &RepairPolicy) -> Option { None } -/// Stub: `hammer-build` no es dependencia directa de `hammer-agent` para no arrastrar el +/// Stub: `takana-build` no es dependencia directa de `takana-agent` para no arrastrar el /// lab a clientes que sólo quieran hablar con el bus. Implementamos la hidratación local /// con `std::fs::hard_link` directamente porque es trivial. Si el árbol del artefacto crece -/// (symlinks, perms más finos), promovemos a `hammer-build::run_hydrate` añadiendo la dep +/// (symlinks, perms más finos), promovemos a `takana-build::run_hydrate` añadiendo la dep /// de manera condicional. fn hammer_build_run_hydrate(artifact_dir: &Path, target_fhs: &Path) -> Result { let mut files = 0usize; @@ -383,7 +383,7 @@ fn hammer_build_run_hydrate(artifact_dir: &Path, target_fhs: &Path) -> Result` (si -/// está en modo Overlay) o `hammer discard`. +/// El resultado del bucle. El humano lo lee para decidir `takana commit ` (si +/// está en modo Overlay) o `takana discard`. #[derive(Debug, Clone, serde::Serialize)] pub struct Proposal { pub intent: String, @@ -496,7 +496,7 @@ pub struct RepairAttempt { pub attempt: u32, pub intent: String, /// `Some` cuando el ciclo abrió un overlay; preservado para que el humano pueda hacer - /// `hammer discard ` sobre intentos intermedios si lo desea. + /// `takana discard ` sobre intentos intermedios si lo desea. pub overlay_id: Option, /// Si tras este intento llegó un `Crashed`, el servicio y código. `None` ⇒ estabilizado. pub triggered_crash: Option, diff --git a/crates/takana-bootstrap/Cargo.toml b/crates/takana-bootstrap/Cargo.toml index 6e90a8dd..a5fa01c0 100644 --- a/crates/takana-bootstrap/Cargo.toml +++ b/crates/takana-bootstrap/Cargo.toml @@ -5,7 +5,7 @@ edition.workspace = true license.workspace = true authors.workspace = true repository.workspace = true -description = "Bootstrap from-scratch de hammer: Stage 0/1/2 hacia el auto-alojamiento (SDD 11)." +description = "Bootstrap from-scratch de takana: Stage 0/1/2 hacia el auto-alojamiento (SDD 11)." [dependencies] takana-core.workspace = true diff --git a/crates/takana-bootstrap/src/lib.rs b/crates/takana-bootstrap/src/lib.rs index d899bf45..b3ee5e2d 100644 --- a/crates/takana-bootstrap/src/lib.rs +++ b/crates/takana-bootstrap/src/lib.rs @@ -1,4 +1,4 @@ -//! Bootstrap from-scratch de hammer — el track posterior del [SDD 11](../../docs/11-bootstrap.md). +//! Bootstrap from-scratch de takana — el track posterior del [SDD 11](../../docs/11-bootstrap.md). //! //! Esta primera entrega cubre el **Stage 0**: ingerir un toolchain semilla ya construido //! (no se compila; ver [ADR 0008](../../docs/adr/0008-bootstrap-stages.md)) como una *fuente @@ -175,7 +175,7 @@ const STAGE1_COMPONENTS: &[&str] = &["musl", "busybox", "hammerd", "arje-zero"]; /// un `Card` `Virtual` cuyos `genesis` son `hammerd` (servicio `Native` con `Restart` — el /// `CRASHED` real) y una `console-getty` supervisada. La forma replica una seed real de arje /// (`seeds/arje-qemu.card.json`) para que `Card::validate()` la acepte; los ULID son fijos para que -/// el `RootfsHash` sea reproducible. Template autocontenido (opción A del SDD): hammer no depende de +/// el `RootfsHash` sea reproducible. Template autocontenido (opción A del SDD): takana no depende de /// `card-core` como librería; el pin a arje-zero + el boot en VM cubren el drift de schema. const STAGE1_SEED_CARD: &str = r#"{ "schema_version": 1, @@ -447,13 +447,13 @@ const SSHD_CONFIG: &str = "Port 22\nListenAddress 0.0.0.0\nPermitRootLogin prohi // ── Atestación de integridad al arranque (I4 / Etapa D, mitad de HAMMER) ───────────────────────── // -// Por la regla de oro del [plan arje↔hammer] (`PLAN-ATESTACION-Y-HAMMER.md` §B.1): hammer es dueño del +// Por la regla de oro del [plan arje↔takana] (`PLAN-ATESTACION-Y-HAMMER.md` §B.1): takana es dueño del // **`expected_hash` + firma + TrustStore**; arje es dueño del **gate al boot** (computa `blake3` de cada -// binario crítico ANTES de incarnar y, si no casa, `halt`). Esta es la mitad de hammer: PRODUCIR el +// binario crítico ANTES de incarnar y, si no casa, `halt`). Esta es la mitad de takana: PRODUCIR el // manifiesto de hashes esperados (`/ente/attest.json`) que el gate A2 de arje verifica — "el // `expected_hash` de un `.swm` ES el BLAKE3 que arje atesta". El hash es `blake3` CRUDO del fichero // (`ArtifactHash::of_file`), el mismo que computa `arje-cas::blake3_of`. La firma con la rootkey del -// seed (A1, `arje-packager`) es una capa posterior; el manifiesto ya es verificable hoy por `hammer +// seed (A1, `arje-packager`) es una capa posterior; el manifiesto ya es verificable hoy por `takana // attest` (auto-validación: "reproducir, no confiar"). Es un fichero APARTE de la seed card ⇒ no toca // el schema de `card-core` y el producto bootea igual con el arje-zero actual (que aún ignora A2). @@ -475,7 +475,7 @@ pub struct AttestEntry { pub b3: String, } -/// Manifiesto de atestación que hammer emite en `/ente/attest.json`. `algo` fijo a `blake3` (crudo). +/// Manifiesto de atestación que takana emite en `/ente/attest.json`. `algo` fijo a `blake3` (crudo). #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct AttestManifest { pub schema_version: u32, @@ -514,7 +514,7 @@ fn build_attestation(root: &Path) -> Result { /// Verifica un árbol FHS (`rootfs_dir`, p.ej. un product-rootfs hidratado) contra su propio /// `/ente/attest.json`: recomputa el BLAKE3 de cada binario listado y lo compara. Es lo que el gate de -/// arje hará al boot, hecho hoy por hammer (auto-validación de integridad del producto). +/// arje hará al boot, hecho hoy por takana (auto-validación de integridad del producto). pub fn verify_attestation(rootfs_dir: &Path) -> Result { let manifest_path = rootfs_dir.join("ente/attest.json"); let raw = std::fs::read_to_string(&manifest_path).map_err(|e| { @@ -541,7 +541,7 @@ pub fn verify_attestation(rootfs_dir: &Path) -> Result { } /// Seed de producto = la seed base con los cards de servicio APENDADOS al `genesis`. Composición vía -/// `serde_json` (hammer sigue autocontenido: no depende de `card-core`). Determinista ⇒ el +/// `serde_json` (takana sigue autocontenido: no depende de `card-core`). Determinista ⇒ el /// `product-rootfs` es reproducible. El núcleo (hammerd + getty) se preserva tal cual. fn product_seed_card() -> Result { let mut seed: serde_json::Value = serde_json::from_str(STAGE1_SEED_CARD) @@ -773,7 +773,7 @@ fn seal_product_rootfs( /// Reproduce un conjunto de componentes DESDE UN REPO FIRMADO, devolviendo sus `(nombre,hash)` sellados /// — el MISMO shape que [`build_components`], así [`assemble_product_rootfs`] los hidrata igual. Por cada /// componente: resuelve su cierre de deps del índice, puebla el catálogo con los `{dep}.toml` (para que -/// el lab materialice build-deps al reproducir, igual que `hammer install`), y REPRODUCE su `source_patch` +/// el lab materialice build-deps al reproducir, igual que `takana install`), y REPRODUCE su `source_patch` /// con `build_source_patch` (que sella y CHEQUEA el `expected_hash` anclado en el índice). Verifica la /// firma del release ANTES de tocar nada: el producto NO se ensambla desde un repo no confiado. pub fn install_components_from_repo( @@ -844,7 +844,7 @@ fn load_swm_file(path: &Path) -> Result { .map_err(|e| Error::Other(format!("no pude parsear {}: {e}", path.display()))) } -/// Primera mutación `SourcePatch` de un `.swm` (un paquete hammer es un único source_patch). +/// Primera mutación `SourcePatch` de un `.swm` (un paquete takana es un único source_patch). fn source_patch_of(swm: &takana_core::Swm) -> Option<&takana_core::Mutation> { swm.mutations .iter() @@ -854,18 +854,18 @@ fn source_patch_of(swm: &takana_core::Swm) -> Option<&takana_core::Mutation> { // ── Producto ATESTADO: la capa FIRMADA que el gate de arje verifica al boot (I4 / Etapa D) ─────── // // `product()` sella el `product-rootfs` con el arje-zero del núcleo + un `/ente/attest.json` de -// AUTO-verificación (esquema paralelo que `hammer attest` valida, pero que el gate de arje NO lee). +// AUTO-verificación (esquema paralelo que `takana attest` valida, pero que el gate de arje NO lee). // El producto ATESTADO cierra el lazo canónico: hidrata el arje-zero CON gate (`arje-zero-attest`), // FIRMA la seed con `arje-packager` (una concesión Ed25519 por binario crítico, sobre su BLAKE3, bajo // una rootkey) y la sella como `product-attested-rootfs`. Booteado, el gate (política `halt`) recomputa // el BLAKE3 de cada exec crítico y aborta antes de incarnar si algo no casa la concesión firmada. // -// Esto reemplaza el spike `scripts/attest-boot-test.sh` (que overlayeaba a mano): ahora hammer-bootstrap +// Esto reemplaza el spike `scripts/attest-boot-test.sh` (que overlayeaba a mano): ahora takana-bootstrap // produce el producto atestado de forma estructurada. Reusa la cripto canónica (arje-attest/agora vía el -// packager) — cero criptografía nueva en hammer. La rootkey por defecto es determinista ⇒ las firmas +// packager) — cero criptografía nueva en takana. La rootkey por defecto es determinista ⇒ las firmas // Ed25519 (RFC 8032, nonce derivado del mensaje) son reproducibles bit a bit. -/// Rootkey de desarrollo (32 bytes) con la que hammer firma la atestación por defecto. Determinista ⇒ +/// Rootkey de desarrollo (32 bytes) con la que takana firma la atestación por defecto. Determinista ⇒ /// firmas reproducibles ⇒ `product-attested-rootfs` reproducible. El endurecimiento soberano (rootkey /// fuera del árbol, `/etc/arje/rootkey.pub` / `ARJE_ATTEST_ROOTKEY_FILE`) es una capa posterior /// (roadmap Etapa D, hardening #3); por ahora se inyecta como override de [`AttestConfig::rootkey`]. @@ -945,7 +945,7 @@ fn critical_bins_from_seed(seed: &serde_json::Value, staging: &Path) -> Vec<(Str /// Ensambla el producto ATESTADO en `staging`: hidrata el `product-rootfs` base, PISA `/usr/bin/arje-zero` /// con el init CON gate, fija `attest_policy` en la seed, la FIRMA con el packager (una concesión por /// binario crítico sobre su BLAKE3), ancla la pubkey en `/etc/arje/rootkey.pub` (ancla soberana externa, -/// hardening #3) y regenera `/ente/attest.json` (la auto-verificación de hammer, ahora coherente con el +/// hardening #3) y regenera `/ente/attest.json` (la auto-verificación de takana, ahora coherente con el /// arje-zero nuevo). El packager corre en el host (estático musl, sin loader, como busybox/bwrap). La /// firma se valida E2E en QEMU (`scripts/attest-boot-test.sh`). fn assemble_attested_product_rootfs( @@ -1030,7 +1030,7 @@ fn assemble_attested_product_rootfs( // `attest_rootkey` declarada en el seed ⇒ un seed reescrito con OTRA rootkey cae en AutorNoConfiable // (las concesiones no las firmó el ancla). Cierra el hueco que el WARN "sin ancla soberana externa" // señala. La pubkey se LEE del seed ya firmado (`attest_rootkey`, lo que el packager computó de - // nuestra rootkey privada) ⇒ cero criptografía nueva en hammer. + // nuestra rootkey privada) ⇒ cero criptografía nueva en takana. let signed_raw = std::fs::read_to_string(&seed_path) .map_err(|e| Error::Other(format!("releer seed firmado: {e}")))?; let signed: serde_json::Value = serde_json::from_str(&signed_raw) @@ -1050,7 +1050,7 @@ fn assemble_attested_product_rootfs( std::fs::write(staging.join("etc/arje/rootkey.pub"), &pubkey)?; // 6) regenerar /ente/attest.json: el arje-zero cambió ⇒ su BLAKE3 también, así que el manifiesto de - // auto-verificación de hammer (`hammer attest`) debe casar el árbol nuevo. El producto base lo + // auto-verificación de takana (`takana attest`) debe casar el árbol nuevo. El producto base lo // trae hidratado (hardlink read-only): romperlo antes de reescribir. let attest = build_attestation(staging)?; let attest_json = serde_json::to_string_pretty(&attest) @@ -1141,7 +1141,7 @@ pub fn product_attested( // **sólo** las herramientas de Stage 1, y se compara el **content-hash** (`of_tree`, no el hash // input-addressed del store) de stage1 vs stage1'. Iguales ⇒ el sistema se compila a sí mismo bit // a bit (auto-alojado y reproducible). El rebuild **dentro del rootfs** (bwrap/chroot/VM) corre en -// la VM destino; lo que vive en hammer es la **referencia** (content-hash de stage1) y la +// la VM destino; lo que vive en takana es la **referencia** (content-hash de stage1) y la // comparación. Ver `docs/runbooks/stage1-vm-boot.md`. /// Veredicto de la verificación de auto-alojamiento de Stage 2. @@ -1264,12 +1264,12 @@ pub fn all( // // El Stage 1 que booteamos es un *runtime* (musl+busybox+hammerd+arje-zero): no trae compilador, no // puede reconstruirse. El **builder rootfs** es Stage 1 **+ el toolchain adentro** — la imagen que, -// booteada en la VM, corre `hammer bootstrap stage1` dentro de sí misma y produce `stage1'`. Compara +// booteada en la VM, corre `takana bootstrap stage1` dentro de sí misma y produce `stage1'`. Compara // su content-hash con la referencia anclada por `stage2`: iguales ⇒ auto-alojamiento bit a bit. // // Variante (a) **pragmática** (SDD 11 §7.2): el toolchain entra desde Alpine (no construido por -// hammer). Demuestra el *mecanismo* y cierra la reproducibilidad end-to-end; no es aún el -// auto-alojamiento *puro* (variante b: el toolchain construido por hammer desde fuente, incremental). +// takana). Demuestra el *mecanismo* y cierra la reproducibilidad end-to-end; no es aún el +// auto-alojamiento *puro* (variante b: el toolchain construido por takana desde fuente, incremental). // // El builder NO se sella en el store (su /toolchain Alpine no es content-addressed y abultaría): se // ensambla en un `out_dir` que se empaqueta como initramfs (ver runbook §8c). Su identidad sí es @@ -1284,7 +1284,7 @@ pub fn all( /// El toolchain es Alpine **dinámico**: sus binarios (bwrap/git/curl/cargo/make) no corren desde el /// userland Stage 1, que es **estático** (no hay loader en `/lib`). El driver instala un *shim* del /// loader musl (`cp` a `/lib`) + `LD_LIBRARY_PATH`/`PATH` al toolchain, y a partir de ahí esas -/// herramientas son ejecutables; el `hammer` estático vive en `/usr/bin/hammer`. El sandbox de build +/// herramientas son ejecutables; el `takana` estático vive en `/usr/bin/hammer`. El sandbox de build /// (bwrap) anida en `/toolchain`. (El shim sólo se usa para *invocar* el toolchain desde fuera del /// sandbox: fetch git/tarball; dentro del sandbox el loader está en su sitio.) const REBUILD_DRIVER: &str = r#"#!/bin/sh @@ -1349,13 +1349,13 @@ pub struct BuilderSpec { /// Stage 1 rootfs ya sellado (nombre store `stage1-rootfs`) que el builder extiende — la base /// runtime sobre la que se hidrata el toolchain. pub stage1_rootfs: RootfsHash, - /// Semilla zig sellada (Stage 0). Se replica en el `/store` del builder para que el `hammer` + /// Semilla zig sellada (Stage 0). Se replica en el `/store` del builder para que el `takana` /// de adentro resuelva el toolchain por hash, igual que afuera. pub seed_hash: ArtifactHash, pub seed_kind: SeedKind, /// Recetas a embeber en `/etc/hammer/recipes` (las que `stage1` rehidrata el rebuild). pub recipes_dir: PathBuf, - /// Binario `hammer` estático → `/usr/bin/hammer`. Variante (a): el del host; (b): el que hammer + /// Binario `takana` estático → `/usr/bin/hammer`. Variante (a): el del host; (b): el que takana /// construye desde fuente. pub hammer_bin: PathBuf, /// Toolchain del sandbox de build → `/toolchain` (variante a: el rootfs Alpine de `.dev-fs`). @@ -1369,20 +1369,20 @@ pub struct BuilderSpec { /// Caché de fuentes (`work/repos`, `work/tarballs`) → `/work`, para un rebuild **offline** y /// determinista en la VM. `None` ⇒ el rebuild fetchea por red (la seed card trae `networking: full`). pub work_cache: Option, - /// Piezas del toolchain **construidas por hammer desde fuente** (variante b, SDD 11 §7.2b) que se + /// Piezas del toolchain **construidas por takana desde fuente** (variante b, SDD 11 §7.2b) que se /// montan sobre el path Alpine en `/toolchain`. Vacío ⇒ variante (a) pura-Alpine. Cada swap entra /// al hash lógico del builder: la procedencia deja de ser "todo Alpine" y se vuelve auditable. pub swaps: Vec, } -/// Una herramienta del toolchain reemplazada por su build hammer desde fuente (SDD 11 §7.2b). El +/// Una herramienta del toolchain reemplazada por su build takana desde fuente (SDD 11 §7.2b). El /// binario sellado se monta sobre `rel_path` dentro de `/toolchain`, pisando la versión Alpine; su /// hash sellado se ancla en el hash lógico del builder para que el swap sea reproducible y auditable. #[derive(Debug, Clone)] pub struct ToolchainSwap { /// Nombre del componente/receta (p. ej. `make`); también el nombre store del artefacto sellado. pub name: String, - /// `of_tree` del build hammer (el artefacto sellado del que sale el binario). + /// `of_tree` del build takana (el artefacto sellado del que sale el binario). pub artifact: ArtifactHash, /// Path relativo del binario dentro del artefacto **y** dentro de `/toolchain` (p. ej. /// `usr/bin/make`). El mismo en origen y destino: el layout del artefacto imita al de Alpine. @@ -1500,7 +1500,7 @@ fn link_or_copy_tree(src: &Path, dst: &Path, skip: Option<&Path>) -> Result<()> /// Ensambla el árbol del builder en `staging` (la pieza testeable, sin VM ni Alpine real): hidrata el /// Stage 1 rootfs como base, monta el toolchain en `/toolchain`, replica la semilla en `/store`, -/// instala `hammer` + recetas + el driver `rebuild-stage1` y, opcionalmente, la caché de fuentes. +/// instala `takana` + recetas + el driver `rebuild-stage1` y, opcionalmente, la caché de fuentes. fn assemble_builder(spec: &BuilderSpec, store: &Store, staging: &Path) -> Result<()> { // 1) Base: el Stage 1 rootfs sellado (read-only en el store ⇒ hardlinks seguros). let stage1_dir = store.path_of(&spec.stage1_rootfs, "stage1-rootfs"); @@ -1527,7 +1527,7 @@ fn assemble_builder(spec: &BuilderSpec, store: &Store, staging: &Path) -> Result } link_or_copy_tree(&spec.toolchain_src, &staging.join("toolchain"), None)?; - // 3b) Swaps de variante (b): piezas construidas por hammer desde fuente pisan su versión Alpine + // 3b) Swaps de variante (b): piezas construidas por takana desde fuente pisan su versión Alpine // en /toolchain. Un `rel_path` puede apuntar a un BINARIO (estático musl ⇒ corre sin el shim // del loader; p.ej. make, busybox) o a un DIRECTORIO (un árbol de headers; p.ej. los // `usr/include/{linux,asm,…}` de linux-headers). En el caso directorio se reemplaza el árbol @@ -1560,7 +1560,7 @@ fn assemble_builder(spec: &BuilderSpec, store: &Store, staging: &Path) -> Result } } - // 4) Semilla → /store/-seed-, tal cual está sellada afuera, para que el `hammer` de + // 4) Semilla → /store/-seed-, tal cual está sellada afuera, para que el `takana` de // adentro resuelva el toolchain por hash sin re-ingerirla. let seed_name = format!("seed-{}", spec.seed_kind.as_str()); let seed_dir = store.path_of(&spec.seed_hash, &seed_name); @@ -1577,7 +1577,7 @@ fn assemble_builder(spec: &BuilderSpec, store: &Store, staging: &Path) -> Result None, )?; - // 5) Binario hammer → /usr/bin/hammer (+x). + // 5) Binario takana → /usr/bin/hammer (+x). let hammer_dst = staging.join("usr/bin/hammer"); if std::fs::hard_link(&spec.hammer_bin, &hammer_dst).is_err() { std::fs::copy(&spec.hammer_bin, &hammer_dst)?; @@ -2226,7 +2226,7 @@ mod tests { #[test] fn assemble_attested_swaps_gate_signs_seed_and_regenerates_attest() { // Hermético: un `arje-packager` SINTÉTICO (script python) simula la firma — añade `attest`/ - // `attest_rootkey` al seed-out. Valida el CABLEADO de hammer (pisar el init, romper hardlinks, + // `attest_rootkey` al seed-out. Valida el CABLEADO de takana (pisar el init, romper hardlinks, // fijar attest_policy, derivar los --bin de la seed, regenerar /ente/attest.json), sin la cripto // real (eso lo cubre E2E `scripts/attest-boot-test.sh` en QEMU). use std::os::unix::fs::PermissionsExt; @@ -2440,7 +2440,7 @@ open(os.path.join(os.path.dirname(out),"..","..","bins-seen.txt"),"w").write("\n std::fs::write(w.join("bin/zig"), b"#!/bin/sh\necho zig\n").unwrap(); }); - // Recetas, binario hammer y toolchain (Alpine sintético), fuera del store. + // Recetas, binario takana y toolchain (Alpine sintético), fuera del store. let recipes = dir.join("recipes"); std::fs::create_dir_all(&recipes).unwrap(); std::fs::write(recipes.join("musl.toml"), b"name = 'musl'\n").unwrap(); @@ -2484,7 +2484,7 @@ open(os.path.join(os.path.dirname(out),"..","..","bins-seen.txt"),"w").write("\n std::fs::read_link(out.join("sbin/init")).unwrap(), PathBuf::from("/usr/bin/arje-zero"), ); - // Toolchain en /toolchain, semilla en /store, hammer + recetas + driver. + // Toolchain en /toolchain, semilla en /store, takana + recetas + driver. assert!(out.join("toolchain/usr/bin/make").is_file(), "toolchain montado"); assert!( out.join("store").join(spec.seed_hash.store_dir_name("seed-zig")).join("bin/zig").is_file(), @@ -2494,7 +2494,7 @@ open(os.path.join(os.path.dirname(out),"..","..","bins-seen.txt"),"w").write("\n assert!(out.join("etc/hammer/recipes/musl.toml").is_file(), "recetas embebidas"); assert!(out.join("usr/bin/rebuild-stage1").is_file(), "driver de rebuild"); - // El driver y hammer son ejecutables. + // El driver y takana son ejecutables. use std::os::unix::fs::PermissionsExt; let m = std::fs::metadata(out.join("usr/bin/rebuild-stage1")).unwrap(); assert_eq!(m.permissions().mode() & 0o111, 0o111, "driver +x"); @@ -2559,7 +2559,7 @@ open(os.path.join(os.path.dirname(out),"..","..","bins-seen.txt"),"w").write("\n let out = tmp.path().join("builder-out"); let report = builder_rootfs(&spec, &store, &out).unwrap(); - // El make de /toolchain es ahora el de hammer, no el de Alpine. + // El make de /toolchain es ahora el de takana, no el de Alpine. let got = std::fs::read(out.join("toolchain/usr/bin/make")).unwrap(); assert_eq!(got, b"\x7fELF-hammer-make-static", "el swap pisó el make de Alpine"); diff --git a/crates/takana-build/Cargo.toml b/crates/takana-build/Cargo.toml index 5c252934..b3122f44 100644 --- a/crates/takana-build/Cargo.toml +++ b/crates/takana-build/Cargo.toml @@ -5,7 +5,7 @@ edition.workspace = true license.workspace = true authors.workspace = true repository.workspace = true -description = "El laboratorio de hammer: sandbox de build (bubblewrap + zig cc) e hidratación." +description = "El laboratorio de takana: sandbox de build (bubblewrap + zig cc) e hidratación." [dependencies] takana-core.workspace = true diff --git a/crates/takana-build/src/fetch.rs b/crates/takana-build/src/fetch.rs index 884a5466..e2e5ea71 100644 --- a/crates/takana-build/src/fetch.rs +++ b/crates/takana-build/src/fetch.rs @@ -616,7 +616,7 @@ fn fetch_tarball( /// /// # Por qué NO avisa cuando cae al mirror /// -/// Tentación evidente y **equivocada**: si `hammer build` avisara en cada descarga, el aviso sería +/// Tentación evidente y **equivocada**: si `takana build` avisara en cada descarga, el aviso sería /// ruido en 561 recetas y nadie lo leería. Peor: haría creer que el bit-rot está vigilado *acá*, /// cuando construir y vigilar upstream son dos trabajos distintos. La vigilancia vive en /// `scripts/fuentes/fuentes-vigia.sh`, la corre el latido y escribe `docs/state/fuentes-vigia.json`. diff --git a/crates/takana-build/src/hydrate.rs b/crates/takana-build/src/hydrate.rs index c3fb7ea0..6bb756a1 100644 --- a/crates/takana-build/src/hydrate.rs +++ b/crates/takana-build/src/hydrate.rs @@ -3,7 +3,7 @@ //! Estrategia primaria (`LinkMode::Static`): hardlink directo. Cero copia, cero RPATH que //! reescribir. El FHS queda con archivos reales (no symlinks) compartiendo inode con el store. //! Pisar un archivo del FHS rompe el hardlink (CoW al kernel) sin tocar el artefacto del store -//! — base de rollback (`hammer hydrate ` lo restaura). +//! — base de rollback (`takana hydrate ` lo restaura). //! //! Estrategia secundaria (`LinkMode::Dynamic`): los ELF que necesitan normalización de //! interpreter/RPATH se **copian** (no se hardlinkean: `patchelf` reescribe el binario y un @@ -65,7 +65,7 @@ pub fn hydrate( // `is_dir()` a secas acepta un directorio VACÍO: hydrate proyectaría 0 ficheros y devolvería // un HydrateReport de éxito. Es el mismo agujero que ya se tapó en `Store::has` (2026-08-10) y // en `Store::seal` (2026-08-29): un vacío no es un artefacto, es un nombre. Acá duele especial - // porque el escritorio se hidrata así (`hammer hydrate --into`), y un FHS proyectado + // porque el escritorio se hidrata así (`takana hydrate --into`), y un FHS proyectado // desde nada sale "OK" y falla mucho más tarde, sin rastro de cuál artefacto faltaba. let vacio = std::fs::read_dir(artifact_dir) .map(|mut e| e.next().is_none()) diff --git a/crates/takana-build/src/lib.rs b/crates/takana-build/src/lib.rs index a2d8d05a..afb8c080 100644 --- a/crates/takana-build/src/lib.rs +++ b/crates/takana-build/src/lib.rs @@ -239,9 +239,9 @@ pub fn build( if matches!(detect_build_system(&src_tree), BuildSys::Cargo) || eff_recipe.source.cargo_vendor == Some(true) { - // El source se copia DENTRO del repo hammer (que es un workspace Cargo) ⇒ si el Cargo.toml + // El source se copia DENTRO del repo takana (que es un workspace Cargo) ⇒ si el Cargo.toml // de la fuente NO declara su propio `[workspace]`, cargo cree que pertenece al workspace de - // hammer y `cargo vendor` aborta. Inyectamos un `[workspace]` vacío para aislarla. SÓLO si + // takana y `cargo vendor` aborta. Inyectamos un `[workspace]` vacío para aislarla. SÓLO si // no lo tiene ya (las recetas del corpus que lo parchean a mano siguen funcionando sin // duplicar la tabla). Esto desbloquea genéricamente los imports Rust (Etapa G) sin un patch // por receta. Ver memoria 'cargo-recipe crate suelto'. @@ -312,7 +312,7 @@ pub fn build( env.push(("CBUILD".into(), SANDBOX_NATIVE_TARGET.to_string())); env.push(("CHOST".into(), SANDBOX_NATIVE_TARGET.to_string())); // *-sys C-FFI (Etapa G): si la receta declara `openssl` como dep, apuntá `openssl-sys` a la - // openssl hammer-built materializada en /usr (estática, musl). Sin esto openssl-sys busca en el + // openssl takana-built materializada en /usr (estática, musl). Sin esto openssl-sys busca en el // host y aborta ("Could not find directory of OpenSSL installation"). Condicional al dep ⇒ no // rompe recetas que usen openssl vendored. Destraba la frontera cargo-* (reqwest/git tools). if recipe.deps.build.iter().any(|d| d == "openssl") { @@ -401,7 +401,7 @@ pub fn build( } // Sidecar de provenance: escribimos la receta serializada DENTRO de out_dir antes del - // seal, para que quede congelada en el árbol read-only del store. `hammer export` la + // seal, para que quede congelada en el árbol read-only del store. `takana export` la // lee de vuelta para emitir `source_patch` con la receta original en vez de un // `file_drop` opaco. Ver `docs/04-overlay.md` §provenance (Fase 4). let sidecar_path = out_dir.join(takana_core::store::RECIPE_SIDECAR_REL); @@ -494,7 +494,7 @@ pub fn run_evidence( env: Vec::new(), }; - // 3. Ejecutar cada check y evaluarlo (la comparación exit/hash es pura, vive en hammer-core). + // 3. Ejecutar cada check y evaluarlo (la comparación exit/hash es pura, vive en takana-core). let mut results = Vec::with_capacity(recipe.evidence.checks.len()); for c in &recipe.evidence.checks { tracing::info!(kind = c.kind.as_str(), cmd = %c.cmd, "evidence: check"); @@ -612,7 +612,7 @@ fn inject_cargo_package_selector(recipe: &mut Recipe, src: &Path) { } /// Garantiza que el `Cargo.toml` raíz de la fuente declare un `[workspace]` propio, para que cargo -/// NO la considere parte del workspace del repo hammer (que la contiene en `work/sources/`). Append +/// NO la considere parte del workspace del repo takana (que la contiene en `work/sources/`). Append /// idempotente: si ya hay `[workspace]` (crate suelto que es su propio workspace, o una receta que /// lo parchea), no toca nada. Caso virtual-manifest (root ya es `[workspace]`) tampoco se toca. fn ensure_cargo_workspace_isolation(src: &Path) -> takana_core::Result<()> { @@ -856,7 +856,7 @@ fn resolve_phases(recipe: &Recipe, src: &Path) -> takana_core::Result { // Hermético y reproducible: `--offline` (deps vendoreadas en la fuente) + // `--locked` (Cargo.lock fijo, coherente con ADR 0006). El link va por un // wrapper `zig cc` — cargo no acepta un linker de dos palabras, y zig provee - // el `libgcc_s` que el link dinámico musl pide (ver M2 del plan arje↔hammer). + // el `libgcc_s` que el link dinámico musl pide (ver M2 del plan arje↔takana). if recipe.build.target == SANDBOX_NATIVE_TARGET { // NATIVO: el sandbox del lab YA es x86_64 musl, así que no cruzamos. El rust del // sandbox sólo trae su std nativo (`x86_64-alpine-linux-musl`), no @@ -894,7 +894,7 @@ fn resolve_phases(recipe: &Recipe, src: &Path) -> takana_core::Result { // sea un ERROR ("option `-C link-self-contained` is not supported on this // target") y NO usa self-contained — el baseline 9adefb82 linkea con zig sin // chocar. Así que: añadir el flag SÓLO si el host del rustc NO es `-alpine-` - // (i.e. un rust vanilla como el hammer-rust del frente self-host); para Alpine, + // (i.e. un rust vanilla como el takana-rust del frente self-host); para Alpine, // omitirlo. RUSTFLAGS alcanza a todas las unidades; los `bin_flags` (cargo rustc // --) sólo a la top. // CC para los build-scripts (cc-rs compila el C de deps como libgit2-sys, @@ -924,7 +924,7 @@ fn resolve_phases(recipe: &Recipe, src: &Path) -> takana_core::Result { // CROSS real (otro target que zig sí entiende): `--target` + linker por env // per-triple. Hermético y reproducible: `--offline` (deps vendoreadas) + // `--locked` (Cargo.lock fijo, ADR 0006). zig provee el `libgcc_s` que el link - // dinámico musl pide (ver M2 del plan arje↔hammer). + // dinámico musl pide (ver M2 del plan arje↔takana). let setup = "printf '#!/bin/sh\\nexec zig cc -mcpu=baseline \"$@\"\\n' > \"$PWD/.hammer-zig-cc\" && \ chmod +x \"$PWD/.hammer-zig-cc\" && "; let triple = rustc_triple(&recipe.build.target); diff --git a/crates/takana-build/src/sandbox.rs b/crates/takana-build/src/sandbox.rs index ef5ae026..b20596ad 100644 --- a/crates/takana-build/src/sandbox.rs +++ b/crates/takana-build/src/sandbox.rs @@ -39,7 +39,7 @@ impl std::fmt::Display for BuildFailure { impl std::error::Error for BuildFailure {} impl BuildFailure { - /// Recupera un `BuildFailure` de un error de hammer-core, si lo lleva dentro. El bus lo + /// Recupera un `BuildFailure` de un error de takana-core, si lo lleva dentro. El bus lo /// usa para separar `reason` de `log_tail`. pub fn from_error(e: &takana_core::Error) -> Option<&BuildFailure> { match e { @@ -457,7 +457,7 @@ impl Sandbox { // default (16) el codegen paralelo de rustc reparte el crate en N unidades y la salida // varía build-a-build incluso en la MISMA máquina y con entradas idénticas — Stage 2 lo // cazó: `arje-zero` (cuyo workspace tawasuyu no fija perfil) divergía ~10 KB repartidos - // por .text/.rodata/.eh_frame, mientras `hammerd` (workspace hammer que SÍ pinea + // por .text/.rodata/.eh_frame, mientras `hammerd` (workspace takana que SÍ pinea // codegen-units=1) reproducía bit-a-bit. El lab lo impone en vez de confiar en que cada // repo upstream lo declare (SDD 09 §2). Inerte para builds no-Cargo (musl/busybox lo // ignoran). Ver runbook §8c / SDD 11. @@ -501,7 +501,7 @@ impl Sandbox { /// El tee va SIEMPRE a stderr (tanto el stdout como el stderr del build): stdout del proceso /// queda reservado para el resultado legible-por-máquina (el content-hash que imprime la CLI, /// p. ej. `bootstrap stage1`). Antes el stdout del build se teeaba al stdout del padre y se -/// colaba en capturas tipo `PRIME=$(hammer … bootstrap stage1)`; con builds reales (no cacheados, +/// colaba en capturas tipo `PRIME=$(takana … bootstrap stage1)`; con builds reales (no cacheados, /// p. ej. el rebuild in-VM) eso son miles de líneas de `configure`/`make` ⇒ el argumento crece y /// la fase de verificación siguiente (`--rootfs "$PRIME"`) revienta el exec con E2BIG /// (Argument list too long). Va a stderr, junto a los logs de tracing. Ver runbook §8c. @@ -555,7 +555,7 @@ pub const CXX_WRAPPER: &str = "hammer-zig-cxx"; /// ── POR QUÉ (medido 2026-08-28) ───────────────────────────────────────────────────────────── /// Construir `zlib` en dos máquinas dio el MISMO `ArtifactHash` y **bytes distintos**: /// `usr/lib/libz.a` divergía sólo en la cabecera `ar` del miembro `/` (la tabla de símbolos), -/// con la hora de pared del build. `hammer why-differs` lo nombró exacto. +/// con la hora de pared del build. `takana why-differs` lo nombró exacto. /// /// La causa NO es `zig ar` (llvm-ar sella mtime 0) ni el binutils del rootfs Alpine (que Alpine /// compila con `--enable-deterministic-archives`): es **nuestro propio `recipes/binutils.toml`**, @@ -577,7 +577,7 @@ pub const CXX_WRAPPER: &str = "hammer-zig-cxx"; pub const AR_WRAPPER: &str = "ar"; pub const RANLIB_WRAPPER: &str = "ranlib"; -/// Materializa en el rootfs dos wrappers de linker-driver (`hammer-zig-cc`/`-cxx`) que envuelven a +/// Materializa en el rootfs dos wrappers de linker-driver (`takana-zig-cc`/`-cxx`) que envuelven a /// `zig cc`/`zig c++`. Su ÚNICO efecto es QUITAR `-static` cuando el link REQUIERE enlace dinámico. /// /// El harness inyecta `LDFLAGS=-static` para las recetas `link=static` (binario monolítico que pide diff --git a/crates/takana-build/src/swm_bridge.rs b/crates/takana-build/src/swm_bridge.rs index e03e400d..c49ddacc 100644 --- a/crates/takana-build/src/swm_bridge.rs +++ b/crates/takana-build/src/swm_bridge.rs @@ -3,8 +3,8 @@ //! Convierte la mutación serializada en una `Recipe` efímera + un archivo de patch //! temporal, y delega en `build` para sellar el artefacto en el store. Luego se hidrata. //! -//! Este módulo vive en `hammer-build` (no en `hammer-core`) porque depende del store y del -//! sandbox. `hammer-core` debe permanecer puro (sin red ni mounts) para que el watcher y los +//! Este módulo vive en `takana-build` (no en `takana-core`) porque depende del store y del +//! sandbox. `takana-core` debe permanecer puro (sin red ni mounts) para que el watcher y los //! tests no arrastren toda la cadena del lab. use std::path::{Path, PathBuf}; diff --git a/crates/takana-build/tests/hidratacion_no_escapa.rs b/crates/takana-build/tests/hidratacion_no_escapa.rs index 212cdb36..5da54339 100644 --- a/crates/takana-build/tests/hidratacion_no_escapa.rs +++ b/crates/takana-build/tests/hidratacion_no_escapa.rs @@ -3,7 +3,7 @@ //! EL FALLO (medido 2026-08-30, antes de `no_escapa`): hidratar es `target_fhs.join(rel)` y //! escribir por ruta. Un artefacto que trae `usr/share/pkg → /algún/lado` deja ese symlink puesto //! —los symlinks se replican literales, y así debe ser— y la hidratación SIGUIENTE escribía -//! `usr/share/pkg/archivo` **fuera del root**, devolviendo `Ok(1)`. Con `hammer hydrate --into` +//! `usr/share/pkg/archivo` **fuera del root**, devolviendo `Ok(1)`. Con `takana hydrate --into` //! sobre una imagen, eso es escribir en el sistema anfitrión diciendo que todo fue bien. //! //! El corpus no lo disparaba (de 160 symlinks absolutos ninguno apunta a un directorio, y de diff --git a/crates/takana-build/tests/sin_pre_exec.rs b/crates/takana-build/tests/sin_pre_exec.rs index e376ba62..35e00eba 100644 --- a/crates/takana-build/tests/sin_pre_exec.rs +++ b/crates/takana-build/tests/sin_pre_exec.rs @@ -1,12 +1,12 @@ -//! Guardián de SDD 25 §7-H4: **ningún camino de spawn de hammer usa `pre_exec`**. +//! Guardián de SDD 25 §7-H4: **ningún camino de spawn de takana usa `pre_exec`**. //! //! POR QUÉ. `std::process::Command` de Rust usa `posix_spawn` cuando puede, y `posix_spawn` es //! PLANO respecto al tamaño del padre: a 256 MB tocados, `fork+exec` costó 3 949 µs contra 231 µs //! (SDD 25 T1, **17×**). En cuanto se le pone un `pre_exec`, Rust apaga ese camino y cae a -//! `fork+exec`, que copia el espacio de direcciones del padre. hammer lanza builds desde un +//! `fork+exec`, que copia el espacio de direcciones del padre. takana lanza builds desde un //! proceso que puede tener cientos de MB mapeados. //! -//! Hoy `hammer-build::sandbox` lanza `bwrap` sin `pre_exec` — y hasta ahora eso era SUERTE, no una +//! Hoy `takana-build::sandbox` lanza `bwrap` sin `pre_exec` — y hasta ahora eso era SUERTE, no una //! regla: nadie lo comprobaba. Esto lo vuelve una regla. //! //! CUÁNDO SE PUEDE APAGAR. Si algún día hace falta de verdad (un `setsid`, un `unshare` que bwrap diff --git a/crates/takana-cli/Cargo.toml b/crates/takana-cli/Cargo.toml index 4dce9724..9c540c7d 100644 --- a/crates/takana-cli/Cargo.toml +++ b/crates/takana-cli/Cargo.toml @@ -7,10 +7,10 @@ authors.workspace = true repository.workspace = true description = "El binario `takana`: orquesta build, hydrate, try/commit, apply/export y ctl." -# ADR 0016 — renombre hammer→takana, etapa 2. Los DOS binarios se emiten a +# ADR 0016 — renombre takana→takana, etapa 2. Los DOS binarios se emiten a # propósito, en vez de un symlink: la siembra de la granja excluye `/target`, así # que un symlink hecho en el hub no existiría en el worker, y `cargo clean` lo -# borra. Dos `[[bin]]` sobreviven a las dos cosas. `hammer` se retira en la etapa 6. +# borra. Dos `[[bin]]` sobreviven a las dos cosas. `takana` se retira en la etapa 6. [[bin]] name = "takana" path = "src/main.rs" @@ -21,7 +21,7 @@ path = "src/main.rs" [features] default = [] -# Activa el traductor LLM real (Claude API) detrás del flag `hammer ai --llm`. +# Activa el traductor LLM real (Claude API) detrás del flag `takana ai --llm`. # Sin esta feature, `--llm` falla con un mensaje claro pidiendo recompilar. llm-claude = ["takana-agent/llm-claude"] diff --git a/crates/takana-cli/src/alpine_import.rs b/crates/takana-cli/src/alpine_import.rs index fb6e41e0..6866f2d3 100644 --- a/crates/takana-cli/src/alpine_import.rs +++ b/crates/takana-cli/src/alpine_import.rs @@ -1,4 +1,4 @@ -//! Importador `Alpine APKBUILD → receta hammer` (Etapa G, fuente #2). +//! Importador `Alpine APKBUILD → receta takana` (Etapa G, fuente #2). //! //! **Por qué Alpine y no sólo nix:** Alpine ya porta miles de paquetes a **musl** (y a menudo //! estático), CON los parches de portabilidad. Eso es justo lo que un import de nixpkgs PIERDE (los @@ -8,12 +8,12 @@ //! Este importador PARSEA el APKBUILD (no lo ejecuta — es shell; sourcearlo correría código ajeno) //! y extrae: pkgname/pkgver, la URL de la fuente, **los `.patch` (los carga a `source.patches`)**, //! makedepends → deps, y `build()/package()` → fases (best-effort: son shell de abuild con CHOST/ -//! --shared/etc. ⇒ necesitan adaptación al lab estático de hammer). Es un PUNTO DE PARTIDA, pero +//! --shared/etc. ⇒ necesitan adaptación al lab estático de takana). Es un PUNTO DE PARTIDA, pero //! uno que YA incluye el trabajo de musl — mucho más cerca de compilar que un import crudo. use std::collections::BTreeMap; -/// Convierte el texto de un APKBUILD en el TOML de una receta hammer. +/// Convierte el texto de un APKBUILD en el TOML de una receta takana. pub fn recipe_from_apkbuild(text: &str) -> Result { let vars = parse_vars(text); let get = |k: &str| vars.get(k).cloned().unwrap_or_default(); @@ -61,7 +61,7 @@ pub fn recipe_from_apkbuild(text: &str) -> Result { }; // build-deps: SÓLO `makedepends`. El `depends` de abuild es RUNTIME (p.ej. gzip depends="less" - // para `zless`) — no hace falta para compilar y rompería `hammer build` (busca recipes/less.toml). + // para `zless`) — no hace falta para compilar y rompería `takana build` (busca recipes/less.toml). // Lo emitimos como comentario de provenance, no como `[deps] build`. (checkdepends ni se lee: no // corremos la suite de tests del paquete.) let self_prefix = format!("{pkgname}-"); @@ -265,10 +265,10 @@ fn func_body(text: &str, name: &str) -> Option { } } -/// Traduce las variables de abuild a su equivalente en el lab de hammer. Substituciones SEGURAS +/// Traduce las variables de abuild a su equivalente en el lab de takana. Substituciones SEGURAS /// (inequívocas): `$pkgdir`→`/out` (el DESTDIR del lab), `$pkgname`→nombre, `$pkgver`→versión. /// NO toca `$CBUILD/$CHOST/$srcdir/$builddir` ni `--shared`. `$CBUILD/$CHOST` los RESUELVE el lab en -/// runtime (env con el triple nativo saneado, Etapa G Fase 3 — `hammer-build`); `$srcdir/$builddir` y +/// runtime (env con el triple nativo saneado, Etapa G Fase 3 — `takana-build`); `$srcdir/$builddir` y /// `--shared` quedan para el humano. `make DESTDIR="$pkgdir"` → `make DESTDIR="/out"`. /// /// Además ENVUELVE el cuerpo en una función shell: abuild ejecuta `build()/package()` COMO funciones, diff --git a/crates/takana-cli/src/kernel_cmd.rs b/crates/takana-cli/src/kernel_cmd.rs index 81890c34..d1b211f5 100644 --- a/crates/takana-cli/src/kernel_cmd.rs +++ b/crates/takana-cli/src/kernel_cmd.rs @@ -1,4 +1,4 @@ -//! `hammer kernel` — el armador de kernel (SDD 22). +//! `takana kernel` — el armador de kernel (SDD 22). //! //! Superficie en inglés (Regla 7.bis), mensajes en castellano. El contrato con las UIs es JSON //! estable, mismo patrón que `/run/hammer/boot-graph.json`. @@ -123,7 +123,7 @@ pub enum KernelCmd { /// /// Sin esto la UI miente: un `-e FOO` cuya dependencia no se cumple se pierde en silencio. DiffBack { - /// El JSON que emitió `hammer kernel plan --out`. + /// El JSON que emitió `takana kernel plan --out`. #[arg(long)] plan: PathBuf, /// El `.config` resultante (el que la receta instala en `/out/boot/config-`). @@ -137,7 +137,7 @@ pub enum KernelCmd { /// No corre sin `--objective`: la regla aplicada global rechazaría recetas sanas (el kernel de /// QEMU apaga USB, HID e INPUT a propósito). Sale distinto de cero si bloquea. Gate { - /// El JSON que emitió `hammer kernel plan --out`. Con `--config` es opcional: sólo sirve + /// El JSON que emitió `takana kernel plan --out`. Con `--config` es opcional: sólo sirve /// para atribuir cada pérdida a su bundle. #[arg(long)] plan: Option, @@ -152,7 +152,7 @@ pub enum KernelCmd { /// Id de objetivo del catálogo (`qemu-serial`, `servidor`, `metal-escritorio`, `portatil`). #[arg(long)] objective: String, - /// Hardware de la máquina DESTINO, capturado con `hammer kernel hw --out`. Sin esto se + /// Hardware de la máquina DESTINO, capturado con `takana kernel hw --out`. Sin esto se /// mira el de esta máquina, que no siempre es la misma. #[arg(long)] devices: Option, @@ -1339,7 +1339,7 @@ fn artifact_of(path: &Path) -> Option { } /// Dónde viven las recetas de kernel cuando nadie pasa `--recipes`. La segunda es la de las -/// recetas DERIVADAS que emite `hammer kernel plan` (p. ej. `linux-gioser`). +/// recetas DERIVADAS que emite `takana kernel plan` (p. ej. `linux-gioser`). const RECIPE_DEFAULTS: [&str; 2] = ["recipes", "docs/state/kernel-plans"]; /// Nombre del directorio del store (`<64 hex>-`) que contiene esta ruta. @@ -1395,7 +1395,7 @@ fn receta_de(artifact: &str, dirs: &[PathBuf]) -> Option { /// Le presta un catálogo a una receta que vive fuera de uno. /// -/// Las recetas DERIVADAS (`hammer kernel plan --recipe-out`) se guardan a propósito fuera de +/// Las recetas DERIVADAS (`takana kernel plan --recipe-out`) se guardan a propósito fuera de /// `recipes/`: dejarlas ahí las mete en el grafo compartido como deuda. Pero sus `deps.build` son /// las del catálogo padre, así que desde su directorio no resuelven y el hash no se puede calcular /// — y sin hash no hay vigencia que comparar. Acá se les apunta el `base_dir` al primer directorio diff --git a/crates/takana-cli/src/main.rs b/crates/takana-cli/src/main.rs index 9e831729..5481d337 100644 --- a/crates/takana-cli/src/main.rs +++ b/crates/takana-cli/src/main.rs @@ -1,4 +1,4 @@ -//! `hammer` — el punto de entrada de todo flujo manual. Ver `docs/`. +//! `takana` — el punto de entrada de todo flujo manual. Ver `docs/`. //! //! Los subcomandos están mapeados a las fases del roadmap (`docs/10-roadmap.md`). Los que aún //! no están implementados devuelven un error claro indicando su fase, para que el esqueleto @@ -310,8 +310,8 @@ enum Cmd { db: PathBuf, }, /// [Etapa G] Importa una receta DESDE nixpkgs: toma el JSON normalizado que produce - /// `scripts/nix-import.sh` (vía `nix eval`) y emite una receta hammer (`.toml`). Trae la - /// RECETA (source+hash+deps+flags), nunca el binario del cache de nix — hammer reconstruye. + /// `scripts/nix-import.sh` (vía `nix eval`) y emite una receta takana (`.toml`). Trae la + /// RECETA (source+hash+deps+flags), nunca el binario del cache de nix — takana reconstruye. /// Es un PUNTO DE PARTIDA: el build (zig/musl) suele necesitar adaptación por paquete. ImportNix { /// JSON normalizado del paquete nix. `-` o ausente ⇒ lee de stdin. @@ -323,7 +323,7 @@ enum Cmd { }, /// [Etapa G] Importa una receta DESDE un APKBUILD de Alpine (aports). Crucial: carga los /// `.patch` de musl de Alpine — lo que un import de nix pierde — así está MUCHO más cerca de - /// compilar en el lab estático de hammer. `scripts/alpine-import.sh ` baja el APKBUILD. + /// compilar en el lab estático de takana. `scripts/alpine-import.sh ` baja el APKBUILD. ImportAlpine { /// El APKBUILD (texto). `-` o ausente ⇒ stdin. #[arg(default_value = "-")] @@ -372,7 +372,7 @@ enum Cmd { /// Compile por el bus. Si no, source_patch se omite con warning. #[arg(long)] bus: Option, - /// Raíz de overlays para `try`. Default coincide con `hammer try`. + /// Raíz de overlays para `try`. Default coincide con `takana try`. #[arg(long)] state_root: Option, /// Si está, activa el bucle de auto-reparación: tras aplicar, espera en el bus @@ -398,10 +398,10 @@ enum Cmd { /// [Fase 6] Evalúa una expresión del mini-lenguaje (SDD 08 §6) contra el sistema local. /// Forma: `kind:value`. Kinds soportados: `bin`, `file`, `pin`, `service`, `depends`. /// Ejemplos: - /// hammer query bin:grep - /// hammer query file:/etc/hosts - /// hammer query depends:/usr/bin/curl - /// hammer query pin:musl --base-ref base.json + /// takana query bin:grep + /// takana query file:/etc/hosts + /// takana query depends:/usr/bin/curl + /// takana query pin:musl --base-ref base.json Query { /// La expresión a evaluar. expr: String, @@ -509,8 +509,8 @@ enum BootCmd { /// /// EN PRODUCCIÓN NO SE USA (PLAN-KIKIN §4.1/§9, 2026-07-16): mirada real NUNCA sale — sostiene /// el DRM master del greeter al escritorio para no re-modesetear (parpadeo). El camino real es: - /// arje-zero publica el grafo al arrancar (`hammer boot graph`), mirada escribe boot-select y - /// dispara el reboot por el bus de arje, y arje-zero corre `hammer boot activate --from-select` + /// arje-zero publica el grafo al arrancar (`takana boot graph`), mirada escribe boot-select y + /// dispara el reboot por el bus de arje, y arje-zero corre `takana boot activate --from-select` /// en su secuencia de apagado. Menu { /// Comando del compositor a lanzar (se parte por espacios). El primer token es el binario. @@ -693,7 +693,7 @@ enum BootstrapCmd { /// Directorio de recetas a embeber. #[arg(long, default_value = "recipes")] recipes: String, - /// Binario `hammer` estático a instalar en `/usr/bin/hammer`. + /// Binario `takana` estático a instalar en `/usr/bin/hammer`. #[arg(long, default_value = "target/x86_64-unknown-linux-musl/release/hammer")] hammer_bin: String, /// Toolchain del sandbox de build → `/toolchain` (rootfs Alpine de `.dev-fs`). @@ -709,7 +709,7 @@ enum BootstrapCmd { /// Caché de fuentes (`work/`) a embeber en `/work` para un rebuild offline. #[arg(long)] work_cache: Option, - /// Pieza del toolchain construida por hammer desde fuente (variante b, SDD 11 §7.2b) que pisa + /// Pieza del toolchain construida por takana desde fuente (variante b, SDD 11 §7.2b) que pisa /// la de Alpine en `/toolchain`. Formato `name=hash[:rel_path]`; `rel_path` por defecto /// `usr/bin/`. Repetible. Ej.: `--swap make=fbad44ac…`. Cada swap entra al hash lógico. #[arg(long = "swap", value_name = "name=hash[:rel_path]")] @@ -1450,7 +1450,7 @@ fn main() -> anyhow::Result<()> { } /// Activa un nodo del grafo de arranque, imprime el resultado y republica el grafo (la vista de mirada -/// debe reflejar el nuevo nodo vivo). Compartido por `hammer boot activate` y `hammer boot menu`. +/// debe reflejar el nuevo nodo vivo). Compartido por `takana boot activate` y `takana boot menu`. fn activate_and_report( root: &std::path::Path, state_root: &std::path::Path, @@ -2208,7 +2208,7 @@ fn run_install( Some(&pkg_name), // reproduce con el nombre del paquete ⇒ cache-hit del corpus, sin duplicar )?; - // Registrar en la DB de instalados (salvo dry-run de schema). Permite `hammer uninstall`. + // Registrar en la DB de instalados (salvo dry-run de schema). Permite `takana uninstall`. if !skip_source_patch { let mut idb = takana_core::InstalledDb::load(db_path)?; let files: Vec = created.iter().map(|p| p.to_string_lossy().into_owned()).collect(); @@ -2242,7 +2242,7 @@ fn run_import_nix(file: &str, out: Option<&std::path::Path>) -> anyhow::Result<( let pkg: nix_import::NixPkg = serde_json::from_str(&json) .map_err(|e| anyhow::anyhow!("JSON normalizado de nix inválido: {e}"))?; let toml = nix_import::to_recipe_toml(&pkg).map_err(|e| anyhow::anyhow!(e))?; - // Sanity: la receta emitida debe parsear como Recipe de hammer. + // Sanity: la receta emitida debe parsear como Recipe de takana. takana_core::Recipe::from_toml(&toml) .map_err(|e| anyhow::anyhow!("la receta importada no parsea (bug del importador): {e}"))?; match out { @@ -3089,7 +3089,7 @@ fn collect_patches_inline(recipe: &takana_core::Recipe) -> Option { Some(all) } -/// Ejecuta el bucle agéntico de Fase 6 vía `hammer-agent`. Acepta una intención NL + +/// Ejecuta el bucle agéntico de Fase 6 vía `takana-agent`. Acepta una intención NL + /// catálogo YAML que mapea intentos exactos a `.swm`s pre-armados. La salida es un /// `Proposal` legible en stdout + el siguiente paso recomendado al humano. fn run_ai( diff --git a/crates/takana-cli/src/nix_import.rs b/crates/takana-cli/src/nix_import.rs index 7e53d90f..b597a24b 100644 --- a/crates/takana-cli/src/nix_import.rs +++ b/crates/takana-cli/src/nix_import.rs @@ -1,9 +1,9 @@ -//! Importador `nix → receta hammer` (Etapa G: poblar el catálogo desde nixpkgs). +//! Importador `nix → receta takana` (Etapa G: poblar el catálogo desde nixpkgs). //! //! El problema: a mano, 34 recetas = userland desierto; un distro usable necesita miles de //! paquetes. nixpkgs es el mayor set de recetas DESDE FUENTE (sources pineados+hash, deps //! explícitas), así que es la semilla natural del catálogo. Este importador toma la *receta* de -//! nix (qué bajar, flags, deps) y la reexpresa como una `Recipe` de hammer — **nunca el binario** +//! nix (qué bajar, flags, deps) y la reexpresa como una `Recipe` de takana — **nunca el binario** //! del cache de nix (eso rompería "verificar, no confiar"; hammer reconstruye desde fuente igual). //! //! Consume un JSON NORMALIZADO (lo produce `scripts/nix-import.sh` vía `nix eval --apply`), no el @@ -53,8 +53,8 @@ pub struct RawSource { pub output_hash_mode: String, } -/// El origen ya clasificado para hammer. `fetchurl` plano → `tarball+sha256`; GitHub (codeload) → -/// `repo+commit` (hammer pinea por commit y reproduce clonando, sin depender del hash NAR de nix). +/// El origen ya clasificado para takana. `fetchurl` plano → `tarball+sha256`; GitHub (codeload) → +/// `repo+commit` (takana pinea por commit y reproduce clonando, sin depender del hash NAR de nix). #[derive(Debug, PartialEq, Eq)] pub enum NixSource { Tarball { url: String, sha256: String }, @@ -85,7 +85,7 @@ pub fn classify_source(raw: &RawSource) -> Result { } /// Traduce el esquema `mirror:///...` de nix a una URL concreta. nix resuelve estos -/// mirrors en tiempo de eval; un import los deja literales y el fetch de hammer (curl) no los +/// mirrors en tiempo de eval; un import los deja literales y el fetch de takana (curl) no los /// entiende. Mapeamos los más comunes a un mirror real; lo no mapeado se deja igual + el usuario /// elige espejo. (nixpkgs tiene la lista completa en `pkgs/build-support/fetchurl/mirrors.nix`.) fn expand_nix_mirror(url: &str) -> String { @@ -138,7 +138,7 @@ fn parse_github_url(url: &str) -> Option<(String, String, String)> { None } -/// Convierte una receta nix normalizada en el TOML de una `Recipe` de hammer. El resultado es un +/// Convierte una receta nix normalizada en el TOML de una `Recipe` de takana. El resultado es un /// PUNTO DE PARTIDA: lleva comentarios marcando lo que falta adaptar (toolchain, nombres de deps). pub fn to_recipe_toml(pkg: &NixPkg) -> Result { let name = sanitize_name(&pkg.pname); @@ -156,7 +156,7 @@ pub fn to_recipe_toml(pkg: &NixPkg) -> Result { }; // deps: build = nativeBuildInputs ++ buildInputs (por nombre nix; el humano remapea al corpus - // de hammer si difieren — p.ej. nix `pkg-config` ≈ hammer `pkgconf`). + // de takana si difieren — p.ej. nix `pkg-config` ≈ takana `pkgconf`). let mut deps: Vec = Vec::new(); for d in pkg.native_build_inputs.iter().chain(pkg.build_inputs.iter()) { let n = sanitize_name(d); @@ -170,7 +170,7 @@ pub fn to_recipe_toml(pkg: &NixPkg) -> Result { // zlib, rustls vs openssl) o lo dejan opt-in (pcre2). Cargo resuelve el grafo Rust por vendoring; // un sys-lib C que SÍ haga falta es adaptación per-paquete (patch/feature, p.ej. // ripgrep-no-jemalloc), no una dep de corpus. Las recetas Rust validadas (ripgrep/uutils) NO - // declaran `[deps]`; emitirlas rompe `hammer build` (busca recipes/.toml). Quedan como + // declaran `[deps]`; emitirlas rompe `takana build` (busca recipes/.toml). Quedan como // COMENTARIO de provenance (no se pierden: señalan qué C podría necesitarse). let deps_block = if pkg.is_go { // Go: la única build-dep es el toolchain `go` (recipes/go.toml). Los buildInputs C de nix @@ -191,7 +191,7 @@ pub fn to_recipe_toml(pkg: &NixPkg) -> Result { format!("\n[deps]\nbuild = [{list}]\n") }; - // Rust (buildRustPackage): emite la plantilla Cargo de hammer — `--bin ` (cargo exige UN + // Rust (buildRustPackage): emite la plantilla Cargo de takana — `--bin ` (cargo exige UN // target) + install copiando `target/release/` a /out (mismo patrón que la receta ripgrep). // El bin = meta.mainProgram de nix (ripgrep→rg), o el pname. Esto deja la receta build-ready. let (flags_line, rust_install) = if pkg.is_rust { @@ -230,7 +230,7 @@ pub fn to_recipe_toml(pkg: &NixPkg) -> Result { let toml = format!( "# Importada de nixpkgs por `hammer import-nix` (Etapa G). PUNTO DE PARTIDA, no final:\n\ - # - el build usa el lab de hammer (zig-cc / musl estático), NO el stdenv de nix ⇒ revisá\n\ + # - el build usa el lab de takana (zig-cc / musl estático), NO el stdenv de nix ⇒ revisá\n\ # compiler/link/phases y adaptá hasta que compile.\n\ # - las deps van con su nombre NIX; remapealas a las recetas del corpus si difieren.\n\ name = \"{name}\"\n\ @@ -260,7 +260,7 @@ fn is_nix_noise(name: &str) -> bool { || name == "auditable-cargo" || name.starts_with("auditable-cargo-") || name == "version-check" - // El toolchain Rust ES el lab de hammer (cargo vendorea las crates), NO un paquete dep. + // El toolchain Rust ES el lab de takana (cargo vendorea las crates), NO un paquete dep. || name == "rustc" || name == "cargo" || name == "rust" @@ -416,11 +416,11 @@ mod tests { }"#; let pkg: NixPkg = serde_json::from_str(json).unwrap(); let toml = to_recipe_toml(&pkg).unwrap(); - // Parsea como Recipe válida de hammer. + // Parsea como Recipe válida de takana. let recipe = takana_core::Recipe::from_toml(&toml).expect("recipe válida"); assert_eq!(recipe.name, "hello"); assert_eq!(recipe.version, "2.12.1"); - // mirror://gnu/ se traduce a una URL concreta que el fetch de hammer entiende. + // mirror://gnu/ se traduce a una URL concreta que el fetch de takana entiende. assert_eq!(recipe.source.tarball.as_deref(), Some("https://ftp.gnu.org/gnu/hello/hello-2.12.1.tar.gz")); assert_eq!( recipe.source.sha256.as_deref(), @@ -447,7 +447,7 @@ mod tests { #[test] fn rust_buildinputs_are_not_active_deps() { // nix lista el closure maximal (pcre2/openssl…); para Rust NO deben volverse `[deps]` (cargo - // vendorea, backend Rust por defecto) — romperían `hammer build`. Quedan como comentario. + // vendorea, backend Rust por defecto) — romperían `takana build`. Quedan como comentario. let json = r#"{ "pname": "rg", "version": "14", "source": { "url": "https://github.com/o/r/archive/abc.tar.gz", "output_hash_mode": "recursive" }, diff --git a/crates/takana-cli/src/qorpa.rs b/crates/takana-cli/src/qorpa.rs index 4d9bbc22..8ade2f62 100644 --- a/crates/takana-cli/src/qorpa.rs +++ b/crates/takana-cli/src/qorpa.rs @@ -1,4 +1,4 @@ -//! `hammer qorpa` — imágenes ajenas ([ADR 0015](../../../docs/adr/0015-imagenes-ajenas.md)). +//! `takana qorpa` — imágenes ajenas ([ADR 0015](../../../docs/adr/0015-imagenes-ajenas.md)). //! //! Superficie en inglés, mensajes en castellano (`CLAUDE.md` regla 4). //! @@ -88,7 +88,7 @@ pub enum QorpaCmd { /// [ADR 0015 §Orden 3] Tira la capa mutable y la rehace desde el manifiesto. /// /// Es la prueba de D3: si esto duele, es que el `upper` se volvió el activo — y un blob - /// irreemplazable es justo lo que hammer existe para no tener. + /// irreemplazable es justo lo que takana existe para no tener. Recreate { id: String, /// No reinstalar `packages` después de tirar la capa. Deja la instancia como recién creada. @@ -130,7 +130,7 @@ pub enum QorpaCmd { /// /// **Es lo que vuelve cierta la frase «el manifiesto es la verdad».** Sin esto `packages` era /// una lista que nadie leía: `recreate` tiraba la capa y lo instalado a mano no volvía, así que - /// el `upper` era el activo de verdad — exactamente el blob irreemplazable que hammer existe + /// el `upper` era el activo de verdad — exactamente el blob irreemplazable que takana existe /// para no tener. Provision { id: String, @@ -146,7 +146,7 @@ pub enum QorpaCmd { /// [ADR 0015 D8] Registra como imagen un artefacto del store que trae una imagen ajena SELLADA. /// /// Es el consumidor de `recipes/steam-runtime-sniper.toml`: la imagen deja de venir de la CDN - /// de Valve y viene de nuestro store, replicable con `hammer mirror push` y cubrible por el + /// de Valve y viene de nuestro store, replicable con `takana mirror push` y cubrible por el /// índice firmado (ADR 0014). **La identidad no cambia**: la imagen se registra bajo el sha256 /// del ARCHIVO de upstream que el artefacto declara, no bajo su ArtifactHash, así que la que /// importa una máquina y la que otra trae con `pull` son la MISMA imagen. @@ -627,7 +627,7 @@ fn write_manifest(dir: &Path, m: &ImageManifest) -> Result<()> { // // D1 dice que las imágenes ajenas no entran al store, y el motivo es que un rootfs MUTABLE no // reproduce. Sniper no muta —nadie le instala nada adentro— así que sellarlo es una afirmación -// verdadera, y con eso se gana cadena de custodia nuestra: se replica con `hammer mirror push`, su +// verdadera, y con eso se gana cadena de custodia nuestra: se replica con `takana mirror push`, su // digest puede ir al índice firmado (ADR 0014) y una instancia se arma sin depender de la CDN de // Valve. Esto es lo que convierte ese artefacto en una imagen usable. // @@ -731,7 +731,7 @@ struct Instance { base: String, #[serde(skip_serializing_if = "Option::is_none")] distro: Option, - /// Lo que debe estar instalado adentro. **Se instala solo**: `hammer qorpa provision` lo pone + /// Lo que debe estar instalado adentro. **Se instala solo**: `takana qorpa provision` lo pone /// con el gestor de la imagen, y `recreate` lo llama después de tirar la capa. Sin esto el /// `upper` sería el activo y el manifiesto un adorno. #[serde(default, skip_serializing_if = "Vec::is_empty")] @@ -2027,7 +2027,7 @@ fn medir(p: &Path) -> (u64, bool) { // El objetivo es el poder de Bedrock Linux —apps de cualquier «stratum» disponibles en todos // lados— SIN sus formas: nada de un FUSE global en el camino de cada `exec`, nada de arbitrar por // heurística qué binario gana. Acá no hace falta, porque **el FHS de esta distro ya es una -// proyección**: `hammer hydrate` proyecta artefactos a un árbol, y extender la proyección a +// proyección**: `takana hydrate` proyecta artefactos a un árbol, y extender la proyección a // instancias es idiomático. // // Tres propiedades que un FUSE no da: **cero costo en runtime** (no hay proceso en el camino @@ -2170,8 +2170,8 @@ fn export(root: &Path, id: &str, into: Option<&Path>, remove: bool) -> Result<() let dst = bin_dir.join(b); let cuerpo = format!( "#!/bin/sh\n\ - # GENERADO por `hammer qorpa export {id}` — {MARCA}. No editar: se reescribe.\n\ - # Borralo (o corré `hammer qorpa export {id} --remove`) y la instancia deja de verse.\n\ + # GENERADO por `takana qorpa export {id}` — {MARCA}. No editar: se reescribe.\n\ + # Borralo (o corré `takana qorpa export {id} --remove`) y la instancia deja de verse.\n\ exec {hammer} qorpa run{raiz_flag} {id} -- {b} \"$@\"\n", hammer = shell_quote(&hammer.display().to_string()), b = shell_quote(b), diff --git a/crates/takana-cli/src/qorpa_wl.rs b/crates/takana-cli/src/qorpa_wl.rs index 0f012fca..403d86a3 100644 --- a/crates/takana-cli/src/qorpa_wl.rs +++ b/crates/takana-cli/src/qorpa_wl.rs @@ -81,7 +81,7 @@ pub struct Proxy { /// Arranca el proxy en segundo plano. Devuelve el socket a bindear en la jaula. /// /// Los hilos son detached a propósito: viven lo que viva el proceso, que es exactamente lo que dura -/// la instancia (`hammer qorpa run` bloquea en bwrap). +/// la instancia (`takana qorpa run` bloquea en bwrap). pub fn arrancar(dir: &Path, socket_real: &Path, permitidos: HashSet) -> io::Result { std::fs::create_dir_all(dir)?; let socket = dir.join("wayland-0"); diff --git a/crates/takana-cli/tests/boot_menu.rs b/crates/takana-cli/tests/boot_menu.rs index a5f97856..a0b9c644 100644 --- a/crates/takana-cli/tests/boot_menu.rs +++ b/crates/takana-cli/tests/boot_menu.rs @@ -1,4 +1,4 @@ -//! E2E del orquestador `hammer boot menu` (ADR 0010, glue de arranque): emite el grafo, lanza el +//! E2E del orquestador `takana boot menu` (ADR 0010, glue de arranque): emite el grafo, lanza el //! compositor (mirada) y activa el nodo elegido. Probamos el GLUE headless con stubs de compositor — //! el pivot de generaciones ya lo cubren los tests de `boot_graph::activate`. Tres caminos: //! A) sin compositor instalado (servidor headless) → emite el grafo y sigue el arranque (exit 0). @@ -84,7 +84,7 @@ fn c_seleccion_viaja_de_boot_select_a_activate() { ); } -// --- `hammer boot activate --from-select` idempotente (contrato PLAN-KIKIN §9) --------------------- +// --- `takana boot activate --from-select` idempotente (contrato PLAN-KIKIN §9) --------------------- // arje-zero lo invoca INCONDICIONAL en todo apagado: sin selección debe ser un no-op limpio (exit 0), // y el fichero sólo se consume si la activación tuvo éxito (si falla, queda para diagnóstico). diff --git a/crates/takana-cli/tests/bootstrap_cli.rs b/crates/takana-cli/tests/bootstrap_cli.rs index 5478a56f..85cca4f8 100644 --- a/crates/takana-cli/tests/bootstrap_cli.rs +++ b/crates/takana-cli/tests/bootstrap_cli.rs @@ -1,4 +1,4 @@ -//! E2E del CLI `hammer bootstrap stage0` (track posterior, SDD 11). Construye un tarball de +//! E2E del CLI `takana bootstrap stage0` (track posterior, SDD 11). Construye un tarball de //! semilla falso, lo ingiere vía `file://` (sin red) y verifica el camino completo: //! sella + imprime el hash, es idempotente, y un sha256 erróneo falla sin sellar. diff --git a/crates/takana-cli/tests/compat_gate.rs b/crates/takana-cli/tests/compat_gate.rs index 4053bbed..ac977de6 100644 --- a/crates/takana-cli/tests/compat_gate.rs +++ b/crates/takana-cli/tests/compat_gate.rs @@ -1,4 +1,4 @@ -//! H4c e2e: el gate de **colisión de fichero observada** en `hammer install` real. +//! H4c e2e: el gate de **colisión de fichero observada** en `takana install` real. //! //! Reproduce el caso "logo" a nivel de fichero, sin declarar `slots`: dos paquetes escriben el //! mismo path. El primero ya está instalado (pre-seed de la DB); al instalar el segundo, el gate @@ -76,7 +76,7 @@ fn install_aborta_ante_colision_de_fichero_y_force_slots_la_supera() { ); } -/// H4d e2e: `hammer compat ` particiona un repo contra el estado instalado. La búsqueda +/// H4d e2e: `takana compat ` particiona un repo contra el estado instalado. La búsqueda /// del prototipo `wawa-memo` (`filtrar`), ahora sobre el repo real y read-only. #[test] fn compat_particiona_el_repo_contra_lo_instalado() { @@ -123,7 +123,7 @@ fn compat_particiona_el_repo_contra_lo_instalado() { assert!(stdout.contains("tema-oscuro"), "stdout: {stdout}"); } -/// H4e e2e: `hammer compat` marca INCOMPATIBLE un paquete cuya dep de runtime divergiste +/// H4e e2e: `takana compat` marca INCOMPATIBLE un paquete cuya dep de runtime divergiste /// (el caso wayland, DERIVADO — sin que el paquete declare `requires`). Read-only: ve el /// source_patch sin construirlo. #[test] diff --git a/crates/takana-cli/tests/swm_roundtrip.rs b/crates/takana-cli/tests/swm_roundtrip.rs index 2d7be243..17329a47 100644 --- a/crates/takana-cli/tests/swm_roundtrip.rs +++ b/crates/takana-cli/tests/swm_roundtrip.rs @@ -1,10 +1,10 @@ -//! Roundtrip e2e de Fase 4: construimos un `.swm` a mano (los tipos viven en hammer-core), +//! Roundtrip e2e de Fase 4: construimos un `.swm` a mano (los tipos viven en takana-core), //! lo aplicamos a un prefix temporal, leemos el resultado y verificamos que los archivos //! coinciden con lo esperado. //! //! NO ejercitamos `source_patch` porque arrastra todo el lab (red + sandbox); para esos //! casos existen los tests gated en `TAKANA_NETWORK_TESTS`. Aquí cubrimos los caminos puros -//! de hammer-core: `verify_schema`, `verify_base`, `apply_config_edit`, `apply_file_drop`. +//! de takana-core: `verify_schema`, `verify_base`, `apply_config_edit`, `apply_file_drop`. use std::collections::BTreeMap; use std::path::Path; diff --git a/crates/takana-core/Cargo.toml b/crates/takana-core/Cargo.toml index d322b681..522d5f39 100644 --- a/crates/takana-core/Cargo.toml +++ b/crates/takana-core/Cargo.toml @@ -5,7 +5,7 @@ edition.workspace = true license.workspace = true authors.workspace = true repository.workspace = true -description = "Tipos compartidos de hammer: Recipe, Swm, hashing CAS y el store." +description = "Tipos compartidos de takana: Recipe, Swm, hashing CAS y el store." [dependencies] anyhow.workspace = true diff --git a/crates/takana-core/src/apply.rs b/crates/takana-core/src/apply.rs index 807a08ae..710f7c42 100644 --- a/crates/takana-core/src/apply.rs +++ b/crates/takana-core/src/apply.rs @@ -3,7 +3,7 @@ //! Estas funciones son **puras** sobre el sistema de archivos: reciben paths absolutos (ya //! re-rooteados al overlay o a un prefix de test) y aplican un único `Mutation` cada una. //! La orquestación (montar overlay, iterar mutaciones, build de source_patch) vive en -//! `hammer-cli`, no aquí — hammer-core no depende de hammer-build ni del overlay. +//! `takana-cli`, no aquí — takana-core no depende de takana-build ni del overlay. //! //! ## `config_edit` //! @@ -31,7 +31,7 @@ use crate::hash::ArtifactHash; /// Directorio canónico donde `init_rule` materializa una regla por servicio. El init /// (arje, PID 1) lee este árbol para saber qué supervisar. Es el contrato on-disk entre -/// hammer (declara) y el init (ejecuta) — análogo a `/etc/systemd/system` pero nativo. +/// takana (declara) y el init (ejecuta) — análogo a `/etc/systemd/system` pero nativo. pub const INIT_RULES_DIR: &str = "/etc/hammer/init.d"; #[derive(Debug, thiserror::Error)] diff --git a/crates/takana-core/src/caps.rs b/crates/takana-core/src/caps.rs index ada30fec..945ab75c 100644 --- a/crates/takana-core/src/caps.rs +++ b/crates/takana-core/src/caps.rs @@ -17,7 +17,7 @@ //! caps = ["query", "compile", "inject", "inject-real", "init"] //! //! [[rule]] -//! gid = 994 # p. ej. grupo `hammer` +//! gid = 994 # p. ej. grupo `takana` //! caps = ["query", "compile", "inject", "init"] //! ``` diff --git a/crates/takana-core/src/compat.rs b/crates/takana-core/src/compat.rs index 452f7d6f..2b45863f 100644 --- a/crates/takana-core/src/compat.rs +++ b/crates/takana-core/src/compat.rs @@ -1,6 +1,6 @@ //! H4b — el gate de **compatibilidad de configs** sobre la receta real (SDD 15 §H4). //! -//! Sube a hammer el modelo de slots que `wawa-memo/src/compat.rs` demostró como +//! Sube a takana el modelo de slots que `wawa-memo/src/compat.rs` demostró como //! prototipo (host/std, 52 tests verdes): una config/paquete declara qué //! superficies del sistema **reclama** (`Slots::claims`) y **requiere** //! (`Slots::requires`), ambas por hash. Antes de tocar el sistema, `install` diff --git a/crates/takana-core/src/differs.rs b/crates/takana-core/src/differs.rs index 6e26ba10..0aa1fee3 100644 --- a/crates/takana-core/src/differs.rs +++ b/crates/takana-core/src/differs.rs @@ -1,4 +1,4 @@ -//! `why-differs` — el diffoscope propio de hammer ([SDD 17 §1.2](../../docs/17-cierres-frontera.md)). +//! `why-differs` — el diffoscope propio de takana ([SDD 17 §1.2](../../docs/17-cierres-frontera.md)). //! //! Cuando un artefacto **no reproduce**, el store sólo sabe decir "el hash no coincide". Eso deja el //! trabajo entero al humano: desempacar los dos árboles, `cmp` a mano, adivinar. Este módulo responde @@ -17,7 +17,7 @@ //! //! **Sin dependencias externas**: los parsers (gzip/ar/ELF) son mínimos y viven acá, en el mismo //! estilo que `query::parse_elf_info`. Un diffoscope de verdad se apoya en medio mundo de binarios -//! ajenos; eso es exactamente lo que hammer no puede permitirse (ADR 0004: el catálogo se construye, +//! ajenos; eso es exactamente lo que takana no puede permitirse (ADR 0004: el catálogo se construye, //! no se importa). use serde::Serialize; diff --git a/crates/takana-core/src/env.rs b/crates/takana-core/src/env.rs index 7036b1a8..d7de8616 100644 --- a/crates/takana-core/src/env.rs +++ b/crates/takana-core/src/env.rs @@ -1,4 +1,4 @@ -//! Lectura de variables de entorno del proyecto durante el renombre `hammer` → `takana`. +//! Lectura de variables de entorno del proyecto durante el renombre `takana` → `takana`. //! //! # Por qué existe esto en vez de un `sed` //! diff --git a/crates/takana-core/src/installed.rs b/crates/takana-core/src/installed.rs index 2e025402..871b175c 100644 --- a/crates/takana-core/src/installed.rs +++ b/crates/takana-core/src/installed.rs @@ -1,5 +1,5 @@ //! La **base de datos de paquetes instalados** (Etapa F): qué paquetes hay puestos en un root y -//! qué ficheros aportó cada uno. Es lo que hace posible `hammer uninstall`: sin un registro de +//! qué ficheros aportó cada uno. Es lo que hace posible `takana uninstall`: sin un registro de //! "este paquete creó estos ficheros", quitar un paquete sería adivinar. //! //! Modelo simple y honesto: `install` registra los ficheros que CREÓ (los hidratados del diff --git a/crates/takana-core/src/kernel/catalog.rs b/crates/takana-core/src/kernel/catalog.rs index 8f127749..b746a2bc 100644 --- a/crates/takana-core/src/kernel/catalog.rs +++ b/crates/takana-core/src/kernel/catalog.rs @@ -29,7 +29,7 @@ pub const CATALOG_VERSION: u32 = 1; pub struct Catalog { pub version: u32, /// Kernel contra el que se revisaron las fugas. Cambiar de versión no invalida el catálogo, - /// pero sí obliga a re-mirar las fugas (`hammer kernel closure`). + /// pero sí obliga a re-mirar las fugas (`takana kernel closure`). #[serde(default)] pub reviewed_against: Option, #[serde(default, rename = "bundle")] diff --git a/crates/takana-core/src/kernel/contract.rs b/crates/takana-core/src/kernel/contract.rs index 47350024..9c757d1e 100644 --- a/crates/takana-core/src/kernel/contract.rs +++ b/crates/takana-core/src/kernel/contract.rs @@ -2,7 +2,7 @@ //! callado si faltan (SDD 25 §4 y §8-W6). //! //! ## Por qué existe este módulo -//! SDD 25 encontró, midiendo otra cosa, que los kernels de hammer se construyen **sin +//! SDD 25 encontró, midiendo otra cosa, que los kernels de takana se construyen **sin //! `CONFIG_MEMCG`**: `memory.max` no existe, y el escritor del otro lado (`arje-incarnate::cgroup`) //! descarta el error. Una Card que pide un tope de memoria arranca **sin tope** y la única huella //! es una línea de log. Es la forma de fallo que `CLAUDE.md` §3 nombra: *un ausente falla diff --git a/crates/takana-core/src/kernel/hw.rs b/crates/takana-core/src/kernel/hw.rs index fa65c322..a22d5886 100644 --- a/crates/takana-core/src/kernel/hw.rs +++ b/crates/takana-core/src/kernel/hw.rs @@ -219,7 +219,7 @@ impl Hardware { } /// La huella. BLAKE3 sobre [`Hardware::fingerprint_material`], con el mismo tipo que cualquier - /// otro identificador por contenido de hammer. + /// otro identificador por contenido de takana. pub fn fingerprint(&self) -> ArtifactHash { ArtifactHash::of_bytes(self.fingerprint_material().as_bytes()) } diff --git a/crates/takana-core/src/kernel/kconfig.rs b/crates/takana-core/src/kernel/kconfig.rs index 3d5f80cf..cb0afba4 100644 --- a/crates/takana-core/src/kernel/kconfig.rs +++ b/crates/takana-core/src/kernel/kconfig.rs @@ -1,6 +1,6 @@ //! Lector del grafo de Kconfig — **sólo para analizar, nunca para resolver**. //! -//! Regla dura heredada del handoff (§6) y ratificada en `docs/22-configurador-kernel.md`: hammer +//! Regla dura heredada del handoff (§6) y ratificada en `docs/22-configurador-kernel.md`: takana //! **no** implementa un solver de Kconfig. El `.config` lo sigue produciendo el `olddefconfig` del //! propio kernel. Lo que este módulo hace es *leer* los ~15 000 símbolos para poder contestar //! preguntas sobre el grafo — «¿qué muere si apago `WIRELESS`?», «¿quién lo enciende por la diff --git a/crates/takana-core/src/kernel/mod.rs b/crates/takana-core/src/kernel/mod.rs index f80c59c0..bfb3fc1f 100644 --- a/crates/takana-core/src/kernel/mod.rs +++ b/crates/takana-core/src/kernel/mod.rs @@ -12,7 +12,7 @@ //! `plan` emite una **receta derivada**, no un binario parametrizable. //! 2. Atestar «este config booteó en esta huella» sale casi gratis: ya es un artefacto CAS. //! -//! Y la regla dura que nunca se cruza: **hammer no resuelve Kconfig**. Emite fragmentos +//! Y la regla dura que nunca se cruza: **takana no resuelve Kconfig**. Emite fragmentos //! (`scripts/config -e/-d`) y deja que el `olddefconfig` del propio kernel produzca el `.config`. //! Ver [`kconfig`]. diff --git a/crates/takana-core/src/kernel/plan.rs b/crates/takana-core/src/kernel/plan.rs index d122b9d1..79635544 100644 --- a/crates/takana-core/src/kernel/plan.rs +++ b/crates/takana-core/src/kernel/plan.rs @@ -14,7 +14,7 @@ //! //! ## Qué se emite y qué no //! Se emiten **raíces**, no clausuras. `-d WIRELESS -d WLAN` son dos banderas; los ~400 símbolos -//! que caen con ellas los calcula el `olddefconfig` **del propio kernel**. hammer sabe cuáles son +//! que caen con ellas los calcula el `olddefconfig` **del propio kernel**. takana sabe cuáles son //! (para poder explicarlos), pero no los escribe: la app nunca escribe un `.config`. //! //! ## Procedencia por símbolo @@ -477,7 +477,7 @@ compile = "make bzImage" assert!(p.fragment.contains("-d WIRELESS")); assert!(p.fragment.contains("-d WLAN")); assert!(!p.fragment.contains("CFG80211")); - // …pero hammer SABE cuántos caen, para poder explicarlo. + // …pero takana SABE cuántos caen, para poder explicarlo. assert_eq!(p.closure_size, 4); } diff --git a/crates/takana-core/src/lib.rs b/crates/takana-core/src/lib.rs index 5c02f2d4..8372a9bf 100644 --- a/crates/takana-core/src/lib.rs +++ b/crates/takana-core/src/lib.rs @@ -1,4 +1,4 @@ -//! Tipos núcleo de hammer, compartidos por el lab, la CLI y el daemon. +//! Tipos núcleo de takana, compartidos por el lab, la CLI y el daemon. //! //! Ver `docs/01-architecture.md` y siguientes. Esto es el esqueleto de Fase 0: los tipos y //! contratos están definidos; la lógica pesada (sandbox, fanotify, bus) vive en los otros @@ -35,7 +35,7 @@ pub use sign::{KeyPair, SigStatus, TrustStore}; pub use store::Store; pub use swm::{Base, BaseCompat, BaseRef, Mutation, PinDiff, Signature, Swm, SwmBuild}; -/// Error común del ecosistema hammer. +/// Error común del ecosistema takana. #[derive(Debug, thiserror::Error)] pub enum Error { #[error("io: {0}")] diff --git a/crates/takana-core/src/query.rs b/crates/takana-core/src/query.rs index 17ea5a7d..59f52ae0 100644 --- a/crates/takana-core/src/query.rs +++ b/crates/takana-core/src/query.rs @@ -13,7 +13,7 @@ //! aparezca un caso de uso real para componer queries, extenderemos sin romper este shape. //! //! Diseñado para evaluarse: -//! - **Local**: la CLI puede correr el evaluador en proceso (`hammer query bin:grep`). +//! - **Local**: la CLI puede correr el evaluador en proceso (`takana query bin:grep`). //! - **Remoto**: el daemon expone `Command::Query { what: "expr", expr: Some(...) }` y //! reusa este evaluador. Útil para que un cliente sin acceso al disco (o sin caps) //! consulte estado a través del bus. diff --git a/crates/takana-core/src/recipe.rs b/crates/takana-core/src/recipe.rs index 481f7652..83117bf7 100644 --- a/crates/takana-core/src/recipe.rs +++ b/crates/takana-core/src/recipe.rs @@ -201,7 +201,7 @@ pub struct Build { /// /// POR QUÉ IMPORTA, medido: el **79%** del contenido binario del store son secciones `.debug_*` /// ⇒ ~96 G de reserva de disco y un espejo público de ~30 G en vez de ~126 G. Y además **cierra - /// una fuga de reproducibilidad**: `hammer why-differs` mostró que `appstream` y `bison` + /// una fuga de reproducibilidad**: `takana why-differs` mostró que `appstream` y `bison` /// divergen entre rebuilds ÚNICAMENTE en `.debug_*` (rutas internas del árbol de build), con el /// código ejecutable idéntico. Sin esas secciones, el artefacto reproduce. /// @@ -323,7 +323,7 @@ impl Slots { } /// Evidencia de comportamiento de una receta (H1 — proof-carrying recipes, SDD 15 §H1). La IA -/// entrega, junto al build, un conjunto de `checks` que el verificador (`hammer swm-verify +/// entrega, junto al build, un conjunto de `checks` que el verificador (`takana swm-verify /// --evidence`) corre DENTRO del sandbox reproducible; la mutación sólo se propone si todos pasan. /// La confianza vive en el checker (pequeño, auditable), no en el generador: el sistema mejora solo /// sin poder corromperse solo. Deliberadamente FUERA de `Recipe::hash_inputs` (comportamiento ≠ @@ -505,7 +505,7 @@ impl Recipe { toml::from_str(s).map_err(|e| crate::Error::Recipe(e.to_string())) } - /// Serializa la receta a TOML. Útil para el sidecar de provenance que `hammer-build` + /// Serializa la receta a TOML. Útil para el sidecar de provenance que `takana-build` /// escribe junto al artefacto en el store. `base_dir` no se serializa (es transient). pub fn to_toml(&self) -> crate::Result { toml::to_string(self).map_err(|e| crate::Error::Recipe(e.to_string())) diff --git a/crates/takana-core/src/repo.rs b/crates/takana-core/src/repo.rs index bcf8e211..5553aa48 100644 --- a/crates/takana-core/src/repo.rs +++ b/crates/takana-core/src/repo.rs @@ -1,15 +1,15 @@ //! El **repositorio de paquetes** (Etapa F): un directorio con `.swm` + un `index.json` que -//! mapea `nombre → paquete`. Es el catálogo que `hammer install ` resuelve. +//! mapea `nombre → paquete`. Es el catálogo que `takana install ` resuelve. //! //! Un `.swm` es un manifiesto de mutación sin identidad propia (no lleva un campo "nombre de //! paquete"); la **identidad** (nombre+versión) la asigna el repo cuando se publica. Esto //! mantiene el formato honesto (describe una transformación, no se arroga ser "el paquete X") -//! y deja al repo ser el namespace. `hammer pack --repo` publica con el nombre/versión de la +//! y deja al repo ser el namespace. `takana pack --repo` publica con el nombre/versión de la //! receta; `install` resuelve por nombre. //! //! El índice es CONTENIDO PLANO (serde_json), no un binario: legible, diffeable, firmable más //! adelante como una release. El transporte del repo (filesystem / sshfs / mirror) es ortogonal -//! — ver `hammer-mirror` para el CAS del store; aquí el repo es simplemente un directorio. +//! — ver `takana-mirror` para el CAS del store; aquí el repo es simplemente un directorio. use std::path::{Path, PathBuf}; diff --git a/crates/takana-core/src/sign.rs b/crates/takana-core/src/sign.rs index 35e72de3..140f5663 100644 --- a/crates/takana-core/src/sign.rs +++ b/crates/takana-core/src/sign.rs @@ -2,7 +2,7 @@ //! //! La firma cubre **el contenido del manifiesto** (`swm_version` + `base` + `mutations`), no la //! propia firma. Sirve para autoría e integridad en tránsito — **no** sustituye a la -//! verificación reproducible: `hammer apply` siempre reproduce y compara, firme o no. +//! verificación reproducible: `takana apply` siempre reproduce y compara, firme o no. //! //! Formato en disco (texto, una línea base64 cada uno): //! - clave privada: `.ed25519` → base64(semilla de 32 bytes), modo 0600 diff --git a/crates/takana-core/src/store.rs b/crates/takana-core/src/store.rs index 6a890225..b075a68e 100644 --- a/crates/takana-core/src/store.rs +++ b/crates/takana-core/src/store.rs @@ -43,12 +43,12 @@ impl Store { /// y devolvió Ok**. Cuatro recetas dieron OK sin producir un solo fichero. /// /// El criterio es "tiene al menos una entrada", NO el sidecar `.hammer/recipe.toml`: ese lo - /// escriben los llamantes (`hammer-build`, `hammer-cli`), no `seal()`, y **`hammer-bootstrap` + /// escriben los llamantes (`takana-build`, `takana-cli`), no `seal()`, y **`takana-bootstrap` /// sella sin él** ⇒ exigirlo haría que el bootstrap se creyera nunca sellado y reconstruyera /// siempre. Un artefacto de verdad nunca está vacío, así que esto basta para el fallo real. /// /// Lo que esto NO cubre: una copia PARCIAL (algún fichero, no todos). Para integridad de - /// contenido están `of_tree` y `hammer attest`; esto es la caché, no la atestación. + /// contenido están `of_tree` y `takana attest`; esto es la caché, no la atestación. pub fn has(&self, h: &ArtifactHash, name: &str) -> bool { let dir = self.path_of(h, name); // `read_dir(..).next().is_some()`: una sola entrada basta, no recorre el árbol. diff --git a/crates/takana-core/src/swm.rs b/crates/takana-core/src/swm.rs index 15b7c24a..4ac9cfc9 100644 --- a/crates/takana-core/src/swm.rs +++ b/crates/takana-core/src/swm.rs @@ -72,7 +72,7 @@ pub enum Mutation { SourcePatch { // Origen git (modo histórico) **o** tarball — exactamente uno, igual que // [`crate::recipe::Source`]. Antes sólo se modelaba git y los tarballs caían a - // `file_drop`; ahora `hammer export` los reconstruye como source_patch. Los campos + // `file_drop`; ahora `takana export` los reconstruye como source_patch. Los campos // son `Option` (con `serde(default)`) para que los `.swm` git existentes —que sólo // traen `repo`+`commit`— sigan parseando sin cambios. #[serde(default, skip_serializing_if = "Option::is_none")] @@ -102,7 +102,7 @@ pub enum Mutation { #[serde(default, skip_serializing_if = "crate::recipe::Deps::is_empty")] deps: crate::recipe::Deps, /// Evidencia de comportamiento que acompaña al paquete (H1 — proof-carrying recipes). El - /// receptor puede correr `hammer swm-verify --evidence` para reproducir cada check en el + /// receptor puede correr `takana swm-verify --evidence` para reproducir cada check en el /// sandbox antes de aceptar la mutación. Vacío ⇒ paquete sin evidencia (sólo reproducibilidad). #[serde(default, skip_serializing_if = "crate::recipe::Evidence::is_empty")] evidence: crate::recipe::Evidence, @@ -246,7 +246,7 @@ impl Swm { /// sistema YA sabe construir se vuelve un paquete distribuible y reproducible-desde-fuente. /// Es la inversa de `takana_build::swm_bridge` (que va `source_patch` → `Recipe` → build). /// - /// `hammer-core` no toca disco: el caller resuelve y **lee** los patches de la receta + /// `takana-core` no toca disco: el caller resuelve y **lee** los patches de la receta /// (relativos a `recipe.base_dir`) y pasa su texto ya concatenado en `patch_text`. El /// `expected_hash`, si se da, ancla "verificar, no confiar" (el receptor rehace y compara). pub fn from_recipe( @@ -394,7 +394,7 @@ impl Mutation { )); } // La evidencia (H1) viaja con el paquete: validamos su FORMA acá (cmd no vacío, - // hash bien formado). La EJECUCIÓN la hace `hammer swm-verify --evidence` (H1b). + // hash bien formado). La EJECUCIÓN la hace `takana swm-verify --evidence` (H1b). evidence.validate().map_err(|e| e.to_string())?; Ok(()) } diff --git a/crates/takana-journal/Cargo.toml b/crates/takana-journal/Cargo.toml index e2e1c718..b13df84c 100644 --- a/crates/takana-journal/Cargo.toml +++ b/crates/takana-journal/Cargo.toml @@ -5,7 +5,7 @@ edition.workspace = true license.workspace = true authors.workspace = true repository.workspace = true -description = "El diario de mutaciones de hammer: append-only JSON-líneas sobre eventos del FHS." +description = "El diario de mutaciones de takana: append-only JSON-líneas sobre eventos del FHS." [dependencies] takana-core.workspace = true diff --git a/crates/takana-journal/src/lib.rs b/crates/takana-journal/src/lib.rs index 3b8347cd..8a9c16ad 100644 --- a/crates/takana-journal/src/lib.rs +++ b/crates/takana-journal/src/lib.rs @@ -11,7 +11,7 @@ //! - El diario no bloquea acciones; sólo observa. Pero también acepta eventos "trazables" //! (de un `hydrate` o `commit`) que llegan con `actor.source = HammerHydrate { artifact }`. //! - Las "mutaciones opacas" (pisada manual sin rastro de artefacto) llegan con -//! `actor.source = External { pid, uid }`. Eso permite que `hammer export` distinga +//! `actor.source = External { pid, uid }`. Eso permite que `takana export` distinga //! replays reproducibles de cambios que sólo se pueden compartir como warnings. use std::io::{BufRead, BufReader, Read, Seek, SeekFrom, Write}; @@ -46,21 +46,21 @@ impl MutationOp { } /// Quién originó la mutación. Distinguir trazable vs opaca es lo que más tarde permite -/// que `hammer export` produzca un `.swm` reproducible (artefactos) más una lista de +/// que `takana export` produzca un `.swm` reproducible (artefactos) más una lista de /// warnings (pisadas manuales). #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "kind", rename_all = "kebab-case")] pub enum Source { - /// Vino de un `hammer hydrate ` — la mutación es replay-able a partir del hash. + /// Vino de un `takana hydrate ` — la mutación es replay-able a partir del hash. HammerHydrate { artifact: String }, - /// Vino de un `hammer commit ` — origen indirecto: el `actor` fue el overlay, + /// Vino de un `takana commit ` — origen indirecto: el `actor` fue el overlay, /// y `artifact` es opcional (puede no haber, si la promoción fue de un edit manual). HammerCommit { overlay: String, #[serde(default, skip_serializing_if = "Option::is_none")] artifact: Option, }, - /// Pisada manual fuera del flujo de hammer. La grabamos sin juzgar — el SDD insiste en + /// Pisada manual fuera del flujo de takana. La grabamos sin juzgar — el SDD insiste en /// que es información, no error. External, } @@ -246,7 +246,7 @@ impl Journal { } /// Hash BLAKE3 del contenido de un archivo, con prefijo `b3:`. Es un blake3 **plano** del -/// contenido (lo que daría `b3sum`), distinto del `ArtifactHash::of_inputs` de hammer-core +/// contenido (lo que daría `b3sum`), distinto del `ArtifactHash::of_inputs` de takana-core /// (que prefija longitudes para identidad de artefactos). Aquí queremos "¿el archivo cambió?". pub fn content_hash_of(bytes: &[u8]) -> String { format!("b3:{}", blake3::hash(bytes).to_hex()) diff --git a/crates/takana-mirror/src/lib.rs b/crates/takana-mirror/src/lib.rs index c313cc2d..c303c633 100644 --- a/crates/takana-mirror/src/lib.rs +++ b/crates/takana-mirror/src/lib.rs @@ -1,6 +1,6 @@ //! **E3 — mirror del store content-addressed** ([SDD 13 §E3](../../docs/13-release-engineering.md)). //! -//! El `/store` de hammer es un CAS: cada artefacto vive en un directorio `-` y *el hash es +//! El `/store` de takana es un CAS: cada artefacto vive en un directorio `-` y *el hash es //! la dirección*. Un mirror, entonces, es ese CAS **replicado** entre dos máquinas + **resolución por //! hash**. Esta capa replica los artefactos que le faltan al destino y **ancla la integridad en //! `of_tree`** (el content-hash BLAKE3 del árbol, [`ArtifactHash::of_tree`]): el receptor **recomputa** diff --git a/crates/takana-overlay/Cargo.toml b/crates/takana-overlay/Cargo.toml index e987acba..bd86dfbf 100644 --- a/crates/takana-overlay/Cargo.toml +++ b/crates/takana-overlay/Cargo.toml @@ -5,7 +5,7 @@ edition.workspace = true license.workspace = true authors.workspace = true repository.workspace = true -description = "El overlay de experimentación de hammer: try/commit/discard/status sobre overlayfs." +description = "El overlay de experimentación de takana: try/commit/discard/status sobre overlayfs." [dependencies] takana-core.workspace = true diff --git a/crates/takana-overlay/src/lib.rs b/crates/takana-overlay/src/lib.rs index 853c537c..0279b417 100644 --- a/crates/takana-overlay/src/lib.rs +++ b/crates/takana-overlay/src/lib.rs @@ -14,7 +14,7 @@ //! //! Diseño: la librería no asume privilegios — emite los comandos `mount`/`umount` y deja //! que el proceso que la invoca tenga (o no) CAP_SYS_ADMIN. Esto permite: -//! - El CLI `hammer try` lo invoca con sudo (o setcap) en una máquina real. +//! - El CLI `takana try` lo invoca con sudo (o setcap) en una máquina real. //! - `hammerd` lo invoca desde su contexto privilegiado (Fase 5). //! - Los tests lo ejercitan dentro de `bwrap --unshare-user-try --unshare-pid` que da //! CAP_SYS_ADMIN en un user-ns aislado. diff --git a/crates/takana-recover/src/main.rs b/crates/takana-recover/src/main.rs index 3874e77c..7ba12e78 100644 --- a/crates/takana-recover/src/main.rs +++ b/crates/takana-recover/src/main.rs @@ -1,11 +1,11 @@ //! `hammer-recover` — auto-recuperación de upgrades al **arranque** (E4 / refinamiento #4b). //! -//! El producto NO lleva el CLI `hammer` completo; este mini-binario (estático musl) es lo único que el +//! El producto NO lleva el CLI `takana` completo; este mini-binario (estático musl) es lo único que el //! sistema instalado necesita para auto-sanar un upgrade interrumpido. El wrapper `/sbin/init` lo corre //! **tras montar `/store` y `/var/lib/hammer`** y **antes** de incarnar arje-zero: //! //! - Sin intento pendiente ⇒ no-op (el caso normal). -//! - Con un `pending.json` (un `hammer upgrade apply` cortado por un apagón/reinicio): intenta +//! - Con un `pending.json` (un `takana upgrade apply` cortado por un apagón/reinicio): intenta //! **completar** (roll-forward, re-ejecuta el plan idempotente + commitea); si no puede (p.ej. el árbol //! ya no está en `/store`), **deshace** (roll-back) para dejar el FHS consistente. En cualquier caso el //! sistema arranca en un estado coherente, no a medias. diff --git a/crates/takana-upgrade/Cargo.toml b/crates/takana-upgrade/Cargo.toml index e486d4ef..bc735b05 100644 --- a/crates/takana-upgrade/Cargo.toml +++ b/crates/takana-upgrade/Cargo.toml @@ -5,7 +5,7 @@ edition.workspace = true license.workspace = true authors.workspace = true repository.workspace = true -description = "Upgrades atómicos de hammer (E4): aplica un árbol Stage1/producto del store al root vivo con generaciones y rollback." +description = "Upgrades atómicos de takana (E4): aplica un árbol Stage1/producto del store al root vivo con generaciones y rollback." [dependencies] takana-core.workspace = true diff --git a/crates/takana-upgrade/src/boot_graph.rs b/crates/takana-upgrade/src/boot_graph.rs index daeebf9a..a4f0439b 100644 --- a/crates/takana-upgrade/src/boot_graph.rs +++ b/crates/takana-upgrade/src/boot_graph.rs @@ -1,18 +1,18 @@ //! **Arranque por grafo** ([ADR 0010](../../docs/adr/0010-arranque-grafo-mirada.md)). //! -//! El menú de arranque de hammer no es una *lista* de kernels (GRUB) sino la **navegación del grafo +//! El menú de arranque de takana no es una *lista* de kernels (GRUB) sino la **navegación del grafo //! content-addressed de estados** del sistema. Este módulo sube el modelo de generaciones in-place //! ([`crate`]) a ese grafo navegable y define el **contrato de datos** con `mirada` (el compositor de //! tawasuyu que dibuja el menú sobre KMS): //! -//! - **hammer → mirada**: [`build`] arma el grafo y [`emit`] lo escribe en +//! - **takana → mirada**: [`build`] arma el grafo y [`emit`] lo escribe en //! [`BOOT_GRAPH_PATH`] (`/run/hammer/boot-graph.json`), world-readable y regenerable. -//! - **mirada → hammer**: mirada escribe el `id` elegido en [`BOOT_SELECT_PATH`] **o** invoca -//! `hammer boot activate `; [`activate`] valida el id contra el grafo y **activa** el nodo +//! - **mirada → takana**: mirada escribe el `id` elegido en [`BOOT_SELECT_PATH`] **o** invoca +//! `takana boot activate `; [`activate`] valida el id contra el grafo y **activa** el nodo //! (pivota la generación vía el rollback existente). //! //! La frontera es *un fichero + un comando*, no una API viva: mirada puede maquetar el menú contra un -//! `boot-graph.json` de ejemplo sin esperar a hammer, y hammer emite el grafo sin esperar a mirada. +//! `boot-graph.json` de ejemplo sin esperar a takana, y takana emite el grafo sin esperar a mirada. //! //! **Content-addressing.** El `id` de cada nodo es el `of_tree` (BLAKE3) del árbol que la generación //! proyectó — sin el prefijo `b3:`, para casar con el `` del contrato. `parents` forma un DAG @@ -30,14 +30,14 @@ use crate::{ current, list, live_chain, rollback, Error, GenerationManifest, Result, RollbackReport, }; -/// Path bien conocido donde hammer publica el grafo para mirada. Regenerable, world-readable. +/// Path bien conocido donde takana publica el grafo para mirada. Regenerable, world-readable. pub const BOOT_GRAPH_PATH: &str = "/run/hammer/boot-graph.json"; /// Path bien conocido donde mirada deja el `id` del nodo a activar (canal de vuelta alternativo a -/// `hammer boot activate `). +/// `takana boot activate `). pub const BOOT_SELECT_PATH: &str = "/run/hammer/boot-select"; -/// Qué representa un nodo del grafo de arranque. Guía cómo lo dibuja mirada y cómo lo activa hammer. +/// Qué representa un nodo del grafo de arranque. Guía cómo lo dibuja mirada y cómo lo activa takana. #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub enum NodeKind { @@ -219,7 +219,7 @@ pub struct ActivateReport { /// [`rollback`] atómico del modelo E4). /// - Si `id` es el nodo de **recuperación** ⇒ un rollback de la generación viva. /// - Si `id` existe pero **no** está en la cadena viva (un "redo" hacia una generación huérfana) ⇒ -/// error honesto: eso requiere re-aplicar el árbol con `hammer upgrade apply`. +/// error honesto: eso requiere re-aplicar el árbol con `takana upgrade apply`. pub fn activate( target_root: &Path, state_root: &Path, diff --git a/crates/takana-upgrade/src/lib.rs b/crates/takana-upgrade/src/lib.rs index 44fe62c3..8e575576 100644 --- a/crates/takana-upgrade/src/lib.rs +++ b/crates/takana-upgrade/src/lib.rs @@ -484,7 +484,7 @@ fn raiz_real(target_root: &Path) -> PathBuf { /// a través de él— y medir el destino lo rechazaría por error. /// /// EL FALLO QUE TAPA (medido 2026-08-30, `apply_no_escribe_fuera_del_root_por_un_symlink`): igual -/// que en `hammer-build/hydrate.rs`, proyectar es `target_root.join(rel)` + escribir por ruta, así +/// que en `takana-build/hydrate.rs`, proyectar es `target_root.join(rel)` + escribir por ruta, así /// que un symlink de DIRECTORIO ya presente en el root se sigue. Una generación que deja puesto /// `usr/share/pkg → /algún/lado` hacía que la siguiente escribiera `usr/share/pkg/archivo` FUERA /// del root, con `ApplyReport` en verde. Con `--root /` no cambia nada (todo empieza por `/`); con