1# ADR 0016 — Renombre del sistema: `hammer` → `takana`
2
3- **Estado:** ACEPTADO (decisión del usuario, 2026-09-09)
4- ⚠ **Este fichero queda FUERA de todo barrido de renombre.** Habla *sobre* el cambio de nombre, así
5 que necesita seguir diciendo `hammer` donde corresponde. El barrido de la etapa 5 lo pasó por
6 arriba y lo dejó diciendo «Renombre del sistema: takana → takana»; se revirtió. Si alguien vuelve
7 a barrer docs, excluir este fichero explícitamente.
8- **Reemplaza:** nada. **Afecta:** toda la superficie de CLI (regla 4 de `CLAUDE.md`).
9
10## Contexto
11
12Los nombres propios del proyecto se reparten por **rol**, no por estética: `khipu` registra
13(`docs/state/build-state*.json`), `yupana` reckona sobre el khipu (`scripts/yupana.py`), `harkaq`
14guarda (la jaula), `qorpa` hospeda (imágenes ajenas), `churay` pone (distribución multi-origen).
15Cada uno dice qué hace su pieza. El único nombre que designa **el todo** es el del constructor.
16
17`takana` (quechua y aimara: *martillo, mazo*) es la traducción literal de `hammer`. Conserva la
18metáfora que el proyecto ya usa —forja, yunque, sellar— y mantiene el registro agentivo del resto de
19la familia. Es hermana de `tawasuyu`: el territorio (apps, compositor) × la herramienta (la forja).
20
21Se descartaron: `chani` (valor/precio — nombra el *hash*, no el motor; y "valor" es cosa, no rol),
22`tocapu` (la marca inscripta — mismo hueco que `chani`), `anta` (cobre — es materia, no rol; y no
23suena quechua: sin q, k, h, ll ni ñ).
24
25## Decisión
26
271. El sistema se llama **takana**. La marca vive en `docs/marca/`.
282. El renombre va **por etapas con alias**, nunca de un saque. `hammer` sigue funcionando hasta que
29 el último llamador migre.
303. Se adoptan los dos puntos de la hoja de marca que chocaban con contratos vigentes —el verbo
31 `forja` y la extensión `.tkn`—, implementados sin romper llamadores (ver §La hoja de marca).
32
33## Lo medido (2026-09-09)
34
35Nada de esto es estimación; sale de `git grep` y de leer `recipe.rs`.
36
37| qué | cuánto | consecuencia |
38|---|---|---|
39| ficheros que nombran `hammer` | 1242 (5779 ocurrencias) | radio total |
40| en `recipes/`, y son **comentarios** de importación | 692 | **gratis**: ver abajo |
41| recetas con `.hammer-zig-cc` **dentro de una fase** | 10 | **caro**: re-hashea |
42| recetas con `cargo_vendor_dir = ".hammer-cargo-vendor"` | 5 | **congelar**: ver abajo |
43| ficheros que **invocan** la CLI | 124 | migración real |
44| crates `hammer-*` (+ `hammerd`) | 12 | renombre de paquetes |
45
46**El hallazgo que decide todo:** `Recipe::hash_inputs` (`crates/hammer-core/src/recipe.rs:535`) no
47hashea el fichero crudo — construye una **lista de campos**: `source_id`, `compiler`, `target`,
48`link`, huella del lab, `zig_version`/`strip_debug` si están fijados, los patches, los `flags`, las
49**fases** (`configure`/`compile`/`install`) y los hashes de las deps.
50
51- ⇒ **Los comentarios no entran.** Renombrar «hammer» en los 692 comentarios de recetas importadas
52 **no mueve ni un ArtifactHash**. Es churn de diff, no de build.
53- ⇒ **Las fases sí entran**, con etiqueta (`phase:compile=…`). Las 10 recetas que escriben
54 `.hammer-zig-cc` lo hacen *dentro* de la fase: renombrar ese literal las re-hashea y obliga a
55 reconstruirlas **y a todo su cono descendente**. El literal es un temporal interno del árbol de
56 build, invisible al usuario. **Se congela como está.**
57- ⇒ `cargo_vendor_dir` **no** está en `hash_inputs`. Renombrar `.hammer-cargo-vendor` sería
58 invisible al hash **pero puede cambiar los bytes del artefacto** — la misma familia de problema
59 que «el lab está fuera de `hash_inputs`». **Se congela como está.**
60
61**Y el cron apunta a una ruta absoluta:** `*/30 * * * * /mnt/vvv/hammer/scripts/farm/cosecha-cron.sh`.
62Renombrar el **directorio** del repo mata el latido de la granja **en silencio** — no falla nada,
63simplemente deja de cosechar. El directorio es lo **último** que se toca, y con el cron parado.
64
65## Plan por etapas
66
671. **Marca + este ADR.** Aditivo, no rompe nada. ← *hecho*
682. **Alias.** ← *hecho (2026-09-09)*. El binario canónico es `takana`; `hammer` se sigue emitiendo.
69 Son **dos `[[bin]]` apuntando al mismo `main.rs`**, no un symlink: la siembra de la granja excluye
70 `/target`, así que un symlink hecho en el hub no existiría en el worker, y `cargo clean` lo borra.
71 Cuesta una recompilación del `main.rs` y un warning de cargo («present in multiple build targets»)
72 que se va solo en la etapa 6. Los dos nombres funcionan; no se tocó ningún llamador.
733. **Llamadores.** ← *hecho (2026-09-09)*, en dos commits y en este orden, que no es cosmético:
74 - **3a** — los `cargo build --release --bin hammer` pasan a `--bin takana --bin hammer` (6
75 sitios). Va **solo y primero**: el worker compila desde fuente (`farm-worker-loop.sh`) y la
76 siembra excluye `/target`. Si se cambiaran antes las invocaciones, habría una ventana en la
77 que el worker sincroniza scripts nuevos y sólo tiene el binario viejo — y eso **no falla
78 ruidosamente: deja de cosechar en silencio**.
79 - **3b** — las 49 invocaciones de `./target/release/hammer` → `takana`, en `scripts/`,
80 `docs/runbooks/` y `CLAUDE.md`. Verificado con `bash -n`/`py_compile` los 49 (ojo:
81 `why-differs-barrido.sh` es Python con extensión `.sh`) y, sobre todo, con el **ciclo real
82 del cron** inmediatamente posterior al cambio: `2026-09-09T18:30:00Z → 18:32:21Z`, siembra ✓,
83 manifiesto ✓, los 9 JSON del grafo regenerados (los produce `build-state.py`, que ahora invoca
84 `takana`) y estado commiteado+pusheado. Cero errores. Esa es la prueba que importa: la
85 regeneración del khipu pasa por el binario renombrado.
86
87 **Excluido a propósito de la etapa 3:**
88 - La variable de entorno `HAMMER=`. Es interfaz entre scripts y hay llamadores que la fijan;
89 renombrarla va con la etapa 4.
90 - `docs/evidencia/` y los `HANDOFF-*`: son **registro** de lo que se corrió ese día. Reescribir
91 un comando dentro de una evidencia la falsifica.
92 - `docs/state/`: generado, se regenera solo.
93 - ADRs y docs de diseño: texto, y `hammer` sigue funcionando. Van con la etapa 5.
94
95 **Cómo converge el worker** (medido el 2026-09-09, no supuesto). Su checkout vive en
96 `/opt/hammer`, **no es un clon git** —lo pone el rsync de la siembra— y `hammer-farm.service`
97 está `enabled` allá, corriendo `farm-worker-loop.sh` como servicio largo. En el momento del
98 cambio el worker tenía scripts viejos y binario del 6-sep: **coherente**. Los dos estados
99 intermedios también lo son, y por eso la 3a iba primero:
100 - *Antes de reiniciar el servicio*: el loop viejo en memoria sigue llamando `hammer` y
101 recompilando `--bin hammer`, que existe. Funciona.
102 - *Después de reiniciar*: el loop nuevo compila **los dos** y usa `takana`; si `takana` todavía
103 no existe, `rebuild_si_hace_falta` compila y devuelve 0 —salta el ciclo, no aborta—.
104
105 La unit apunta a la RUTA DEL SCRIPT, no al binario, así que nada de la etapa 3 la toca. El
106 nombre del fichero de unit y `/opt/hammer` son etapa 6.
107
108 **Convergido y comprobado (2026-09-09 18:40–18:45Z).** Reiniciado `hammer-farm.service`, el
109 worker compiló los dos binarios y **cerró un ciclo de build real con el nombre nuevo**:
110 `✓ dunst b3:29a79859…`, BUILD-YIELD 1/1, 1 promovido. No es que «no se rompió nada visible»: el
111 camino de construir y sellar se ejercitó entero.
1124. **Crates.** ← *hecho parcialmente (2026-09-09)*. Los 10 de librería + CLI
113 (`hammer-{core,build,bootstrap,overlay,journal,mirror,upgrade,agent,recover,cli}`) son
114 `takana-*`. **Verificado que no mueve el corpus**: `takana hash recipes/zlib.toml` devuelve
115 `b3:dc363f26…`, idéntico a antes. 600 tests en verde.
116
117 **Dos binarios congelados, con razón medida:**
118 - `hammerd` — paquete **y** binario. Es componente de Stage 1 de la distro (musl, busybox,
119 hammerd, arje-zero), arje-zero lo supervisa en el sistema arrancado y `PRESEED=hammerd` lo
120 nombra en `selfhost-verify.sh`.
121 - `hammer-recover` — el paquete es `takana-recover`, **el binario sigue siendo
122 `hammer-recover`**: `hammer-live-install.sh` lo copia a `/usr/sbin/hammer-recover` en sistemas
123 **ya instalados** y hornea un hook de arranque que lo invoca por ese nombre. Renombrarlo no
124 rompe el repo: rompe máquinas instaladas.
125
126 **Consecuencia que hay que anotar igual:** al renombrar `hammer-core`, los bytes de `hammerd`
127 cambian de todos modos —linkea contra un crate con otro nombre y el nombre va en los símbolos—,
128 así que **el baseline `of_tree` del selfhost hay que rehacerlo**. Es efecto de la etapa 4, no de
129 un cambio en `hammerd`.
130
1314 bis. **Variables de entorno: leen las dos, gana la nueva.** ← *hecho (2026-09-09)*.
132
133 Se midió antes de tocarlas y el problema tenía otra forma que la del plan: no era «la variable
134 `HAMMER=`», eran **14**, ~260 apariciones en 58 ficheros, **y el binario las lee**. Con knobs del
135 instalador entre ellas, el entorno del worker trayéndolas puestas y `mirror-env.sh` exportándolas
136 — todo eso vive **fuera del repo**, en perfiles de shell y units. Un `sed` no falla ruidosamente:
137 la variable deja de aparecer, se toma el default y el build se comporta distinto en silencio.
138
139 - **Rust:** `takana_core::env::{var, var_os}` recibe el nombre **canónico** (`TAKANA_…`) y deriva
140 el viejo cambiando el prefijo. Se le pasa el nuevo a propósito, para que un `grep` del nombre
141 nuevo encuentre todas las lecturas. 5 tests, **con dos controles negativos**: sin ninguna de las
142 dos no hay valor, y un nombre sin prefijo `TAKANA_` no inventa una caída.
143 - Migrados los 17 sitios directos **y los indirectos que el grep de `env::var("HAMMER_…")` no
144 mostraba**: `bases_de_mirror`, las constantes de `kernel_cmd`, `ROOT_ENV` de qorpa y `env_path`
145 de recover. `takana-recover` lleva la caída **inline**: es un mini-binario que se copia a
146 `/usr/sbin` y no vale arrastrarle una dep entera por dos líneas.
147 - **Scripts:** 30 lecturas pasan a `${TAKANA_X:-${HAMMER_X:-default}}`, conservando el nombre
148 **interno** de la variable para no tocar sus 190 usos.
149 - **Donde el script EXPORTA en vez de leer, se ponen las dos** (`mirror-env.sh` y el fragmento
150 in-VM de `takana-bootstrap`). Ahí el lector puede ser un binario **viejo** —un worker sin
151 recompilar, el `/usr/bin/hammer` pinado del baseline— que sólo conoce `HAMMER_*`. La caída
152 sirve al lector nuevo; al viejo hay que seguirle dejando la suya puesta.
153
154 **Verificado con el binario, no sólo con unit tests:** `HAMMER_LAB` sigue surtiendo efecto,
155 `TAKANA_LAB` hace exactamente lo mismo, y con las dos puestas gana `TAKANA_LAB`. 605 tests en
156 verde y `hash zlib` sigue en `b3:dc363f26…`.
157
158 **Cambio de comportamiento que va dicho aparte:** el hostname por defecto de una instalación
159 nueva pasa de `hammer` a `takana` (sólo si no se fija ninguna de las dos variables).
160
161 **No se tocan:** las rutas `/var/lib/hammer` de sistemas ya instalados, el `-volid HAMMER_LIVE`
162 del ISO (es identidad horneada en el medio) y el namespace `HARKAQ_*`, que es de otro subsistema.
163
1645. **Comentarios de recetas** (692). Gratis en hash, ruidoso en diff: va en un commit propio y solo.
1656. **Retirar el alias.** Y recién entonces, si se quiere, el directorio `/mnt/vvv/hammer` — parando
166 el cron y reescribiendo el crontab en el mismo movimiento.
167
168Etapas 2–6 no arrancan hasta que la 1 esté pusheada, y ninguna se mezcla con otra en un commit.
169
170## La hoja de marca: los dos puntos que contradecían contratos vigentes
171
172La hoja (`docs/marca/README.md`) trae dos ejemplos que chocan con contratos ya escritos. Se
173plantearon como no adoptables; **el usuario los reafirmó el 2026-09-09 y se adoptaron**. Se
174implementaron de forma que la decisión se cumpla sin romper a los llamadores existentes.
175
176### 1. `forja` — verbo de marca en castellano
177
178Choca con la **regla 4** de `CLAUDE.md` («la superficie de CLI va en inglés»). Adoptado como
179**alias de clap sobre `build`**, no como reemplazo:
180
181- `takana forja <receta>` funciona — la invocación de la hoja de marca es real.
182- `takana build <receta>` sigue siendo el **canónico**: es lo que usan los 124 llamadores, el cron
183 y los runbooks, y ninguno se tocó.
184- `CLAUDE.md` §4 quedó **enmendada** en el mismo movimiento. Cambiar el comportamiento y dejar
185 escrito el contrato viejo es peor que cualquiera de las dos opciones: el otro agente del repo
186 sigue aplicando lo que lee.
187- La excepción es **cerrada**: un alias, el que está. Otro alias es decisión de ADR.
188
189### 2. `.tkn` — extensión del paquete
190
191Choca con `.swm` (266 menciones; Etapa F entera encima). Resultó **mucho más barato de lo
192estimado**, y por una razón medida: la extensión no es lógica, es salida.
193
194- Se escribe en **un solo lugar** (`crates/hammer-cli/src/main.rs:1800`).
195- El descubrimiento de paquetes va por **índice**, no por glob: `PackageEntry.file`
196 (`crates/hammer-core/src/repo.rs:75`) guarda el nombre real de cada fichero.
197- ⇒ **Los repos existentes no se rompen y un repo mixto es válido**: un índice con entradas `.swm`
198 sigue resolviendo, y los paquetes nuevos se escriben `.tkn`. No hace falta migrar nada.
199- Cero ficheros `.swm` versionados en el repo, así que no hubo qué renombrar.
200- **`Swm`, `SwmBuild`, `swm_path`, `swm_bridge` NO se tocan.** Son nombres de tipo y de módulo, no
201 superficie de usuario; renombrarlos es churn puro dentro de la etapa 4.
202
203## Nota sobre los ficheros de marca
204
205Los dos SVG difieren correctamente (chispa `#FFF6DE` sobre oscuro, `#17130E` sobre claro) —
206verificado por sha256 y por los colores presentes, no por el nombre del fichero. Ambos traen un
207manifiesto **C2PA** de procedencia embebido; se conserva tal cual vino, sin limpiar.
0016-renombre-takana.md
ADR 0016 — Renombre del sistema: hammer → takana
- Estado: ACEPTADO (decisión del usuario, 2026-09-09)
- ⚠ Este fichero queda FUERA de todo barrido de renombre. Habla sobre el cambio de nombre, así
que necesita seguir diciendo
hammer donde corresponde. El barrido de la etapa 5 lo pasó por
arriba y lo dejó diciendo «Renombre del sistema: takana → takana»; se revirtió. Si alguien vuelve
a barrer docs, excluir este fichero explícitamente.
- Reemplaza: nada. Afecta: toda la superficie de CLI (regla 4 de
CLAUDE.md).
Contexto
Los nombres propios del proyecto se reparten por rol, no por estética: khipu registra
(docs/state/build-state*.json), yupana reckona sobre el khipu (scripts/yupana.py), harkaq
guarda (la jaula), qorpa hospeda (imágenes ajenas), churay pone (distribución multi-origen).
Cada uno dice qué hace su pieza. El único nombre que designa el todo es el del constructor.
takana (quechua y aimara: martillo, mazo) es la traducción literal de hammer. Conserva la
metáfora que el proyecto ya usa —forja, yunque, sellar— y mantiene el registro agentivo del resto de
la familia. Es hermana de tawasuyu: el territorio (apps, compositor) × la herramienta (la forja).
Se descartaron: chani (valor/precio — nombra el hash, no el motor; y "valor" es cosa, no rol),
tocapu (la marca inscripta — mismo hueco que chani), anta (cobre — es materia, no rol; y no
suena quechua: sin q, k, h, ll ni ñ).
Decisión
- El sistema se llama takana. La marca vive en
docs/marca/.
- El renombre va por etapas con alias, nunca de un saque.
hammer sigue funcionando hasta que
el último llamador migre.
- Se adoptan los dos puntos de la hoja de marca que chocaban con contratos vigentes —el verbo
forja y la extensión .tkn—, implementados sin romper llamadores (ver §La hoja de marca).
Lo medido (2026-09-09)
Nada de esto es estimación; sale de git grep y de leer recipe.rs.
| qué | cuánto | consecuencia |
ficheros que nombran hammer | 1242 (5779 ocurrencias) | radio total |
en recipes/, y son comentarios de importación | 692 | gratis: ver abajo |
recetas con .hammer-zig-cc dentro de una fase | 10 | caro: re-hashea |
recetas con cargo_vendor_dir = ".hammer-cargo-vendor" | 5 | congelar: ver abajo |
| ficheros que invocan la CLI | 124 | migración real |
crates hammer-* (+ hammerd) | 12 | renombre de paquetes |
El hallazgo que decide todo: Recipe::hash_inputs (crates/hammer-core/src/recipe.rs:535) no
hashea el fichero crudo — construye una lista de campos: source_id, compiler, target,
link, huella del lab, zig_version/strip_debug si están fijados, los patches, los flags, las
fases (configure/compile/install) y los hashes de las deps.
- ⇒ Los comentarios no entran. Renombrar «hammer» en los 692 comentarios de recetas importadas
no mueve ni un ArtifactHash. Es churn de diff, no de build.
- ⇒ Las fases sí entran, con etiqueta (
phase:compile=…). Las 10 recetas que escriben
.hammer-zig-cc lo hacen dentro de la fase: renombrar ese literal las re-hashea y obliga a
reconstruirlas y a todo su cono descendente. El literal es un temporal interno del árbol de
build, invisible al usuario. Se congela como está.
- ⇒
cargo_vendor_dir no está en hash_inputs. Renombrar .hammer-cargo-vendor sería
invisible al hash pero puede cambiar los bytes del artefacto — la misma familia de problema
que «el lab está fuera de hash_inputs». Se congela como está.
Y el cron apunta a una ruta absoluta: */30 * * * * /mnt/vvv/hammer/scripts/farm/cosecha-cron.sh.
Renombrar el directorio del repo mata el latido de la granja en silencio — no falla nada,
simplemente deja de cosechar. El directorio es lo último que se toca, y con el cron parado.
Plan por etapas
-
Marca + este ADR. Aditivo, no rompe nada. ← hecho
-
Alias. ← hecho (2026-09-09). El binario canónico es takana; hammer se sigue emitiendo.
Son dos [[bin]] apuntando al mismo main.rs, no 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.
Cuesta una recompilación del main.rs y un warning de cargo («present in multiple build targets»)
que se va solo en la etapa 6. Los dos nombres funcionan; no se tocó ningún llamador.
-
Llamadores. ← hecho (2026-09-09), en dos commits y en este orden, que no es cosmético:
- 3a — los
cargo build --release --bin hammer pasan a --bin takana --bin hammer (6
sitios). Va solo y primero: el worker compila desde fuente (farm-worker-loop.sh) y la
siembra excluye /target. Si se cambiaran antes las invocaciones, habría una ventana en la
que el worker sincroniza scripts nuevos y sólo tiene el binario viejo — y eso no falla
ruidosamente: deja de cosechar en silencio.
- 3b — las 49 invocaciones de
./target/release/hammer → takana, en scripts/,
docs/runbooks/ y CLAUDE.md. Verificado con bash -n/py_compile los 49 (ojo:
why-differs-barrido.sh es Python con extensión .sh) y, sobre todo, con el ciclo real
del cron inmediatamente posterior al cambio: 2026-09-09T18:30:00Z → 18:32:21Z, siembra ✓,
manifiesto ✓, los 9 JSON del grafo regenerados (los produce build-state.py, que ahora invoca
takana) y estado commiteado+pusheado. Cero errores. Esa es la prueba que importa: la
regeneración del khipu pasa por el binario renombrado.
Excluido a propósito de la etapa 3:
- La variable de entorno
HAMMER=. Es interfaz entre scripts y hay llamadores que la fijan;
renombrarla va con la etapa 4.
docs/evidencia/ y los HANDOFF-*: son registro de lo que se corrió ese día. Reescribir
un comando dentro de una evidencia la falsifica.
docs/state/: generado, se regenera solo.
- ADRs y docs de diseño: texto, y
hammer sigue funcionando. Van con la etapa 5.
Cómo converge el worker (medido el 2026-09-09, no supuesto). Su checkout vive en
/opt/hammer, no es un clon git —lo pone el rsync de la siembra— y hammer-farm.service
está enabled allá, corriendo farm-worker-loop.sh como servicio largo. En el momento del
cambio el worker tenía scripts viejos y binario del 6-sep: coherente. Los dos estados
intermedios también lo son, y por eso la 3a iba primero:
- Antes de reiniciar el servicio: el loop viejo en memoria sigue llamando
hammer y
recompilando --bin hammer, que existe. Funciona.
- Después de reiniciar: el loop nuevo compila los dos y usa
takana; si takana todavía
no existe, rebuild_si_hace_falta compila y devuelve 0 —salta el ciclo, no aborta—.
La unit apunta a la RUTA DEL SCRIPT, no al binario, así que nada de la etapa 3 la toca. El
nombre del fichero de unit y /opt/hammer son etapa 6.
Convergido y comprobado (2026-09-09 18:40–18:45Z). Reiniciado hammer-farm.service, el
worker compiló los dos binarios y cerró un ciclo de build real con el nombre nuevo:
✓ dunst b3:29a79859…, BUILD-YIELD 1/1, 1 promovido. No es que «no se rompió nada visible»: el
camino de construir y sellar se ejercitó entero.
-
Crates. ← hecho parcialmente (2026-09-09). Los 10 de librería + CLI
(hammer-{core,build,bootstrap,overlay,journal,mirror,upgrade,agent,recover,cli}) son
takana-*. Verificado que no mueve el corpus: takana hash recipes/zlib.toml devuelve
b3:dc363f26…, idéntico a antes. 600 tests en verde.
Dos binarios congelados, con razón medida:
hammerd — paquete y binario. Es componente de Stage 1 de la distro (musl, busybox,
hammerd, arje-zero), arje-zero lo supervisa en el sistema arrancado y PRESEED=hammerd lo
nombra en selfhost-verify.sh.
hammer-recover — el paquete es takana-recover, el binario sigue siendo
hammer-recover: hammer-live-install.sh lo copia a /usr/sbin/hammer-recover en sistemas
ya instalados y hornea un hook de arranque que lo invoca por ese nombre. Renombrarlo no
rompe el repo: rompe máquinas instaladas.
Consecuencia que hay que anotar igual: al renombrar hammer-core, los bytes de hammerd
cambian de todos modos —linkea contra un crate con otro nombre y el nombre va en los símbolos—,
así que el baseline of_tree del selfhost hay que rehacerlo. Es efecto de la etapa 4, no de
un cambio en hammerd.
4 bis. Variables de entorno: leen las dos, gana la nueva. ← hecho (2026-09-09).
Se midió antes de tocarlas y el problema tenía otra forma que la del plan: no era «la variable
HAMMER=», eran 14, ~260 apariciones en 58 ficheros, y el binario las lee. Con knobs del
instalador entre ellas, el entorno del worker trayéndolas puestas y mirror-env.sh exportándolas
— todo eso vive fuera del repo, en perfiles de shell y units. Un sed no falla ruidosamente:
la variable deja de aparecer, se toma el default y el build se comporta distinto en silencio.
- Rust:
takana_core::env::{var, var_os} recibe el nombre canónico (TAKANA_…) y deriva
el viejo cambiando el prefijo. Se le pasa el nuevo a propósito, para que un grep del nombre
nuevo encuentre todas las lecturas. 5 tests, con dos controles negativos: sin ninguna de las
dos no hay valor, y un nombre sin prefijo TAKANA_ no inventa una caída.
- Migrados los 17 sitios directos y los indirectos que el grep de
env::var("HAMMER_…") no
mostraba: bases_de_mirror, las constantes de kernel_cmd, ROOT_ENV de qorpa y env_path
de recover. takana-recover lleva la caída inline: es un mini-binario que se copia a
/usr/sbin y no vale arrastrarle una dep entera por dos líneas.
- Scripts: 30 lecturas pasan a
${TAKANA_X:-${HAMMER_X:-default}}, conservando el nombre
interno de la variable para no tocar sus 190 usos.
- Donde el script EXPORTA en vez de leer, se ponen las dos (
mirror-env.sh y el fragmento
in-VM de takana-bootstrap). Ahí el lector puede ser un binario viejo —un worker sin
recompilar, el /usr/bin/hammer pinado del baseline— que sólo conoce HAMMER_*. La caída
sirve al lector nuevo; al viejo hay que seguirle dejando la suya puesta.
Verificado con el binario, no sólo con unit tests: HAMMER_LAB sigue surtiendo efecto,
TAKANA_LAB hace exactamente lo mismo, y con las dos puestas gana TAKANA_LAB. 605 tests en
verde y hash zlib sigue en b3:dc363f26….
Cambio de comportamiento que va dicho aparte: el hostname por defecto de una instalación
nueva pasa de hammer a takana (sólo si no se fija ninguna de las dos variables).
No se tocan: las rutas /var/lib/hammer de sistemas ya instalados, el -volid HAMMER_LIVE
del ISO (es identidad horneada en el medio) y el namespace HARKAQ_*, que es de otro subsistema.
- Comentarios de recetas (692). Gratis en hash, ruidoso en diff: va en un commit propio y solo.
- Retirar el alias. Y recién entonces, si se quiere, el directorio
/mnt/vvv/hammer — parando
el cron y reescribiendo el crontab en el mismo movimiento.
Etapas 2–6 no arrancan hasta que la 1 esté pusheada, y ninguna se mezcla con otra en un commit.
La hoja de marca: los dos puntos que contradecían contratos vigentes
La hoja (docs/marca/README.md) trae dos ejemplos que chocan con contratos ya escritos. Se
plantearon como no adoptables; el usuario los reafirmó el 2026-09-09 y se adoptaron. Se
implementaron de forma que la decisión se cumpla sin romper a los llamadores existentes.
1. forja — verbo de marca en castellano
Choca con la regla 4 de CLAUDE.md («la superficie de CLI va en inglés»). Adoptado como
alias de clap sobre build, no como reemplazo:
takana forja <receta> funciona — la invocación de la hoja de marca es real.
takana build <receta> sigue siendo el canónico: es lo que usan los 124 llamadores, el cron
y los runbooks, y ninguno se tocó.
CLAUDE.md §4 quedó enmendada en el mismo movimiento. Cambiar el comportamiento y dejar
escrito el contrato viejo es peor que cualquiera de las dos opciones: el otro agente del repo
sigue aplicando lo que lee.
- La excepción es cerrada: un alias, el que está. Otro alias es decisión de ADR.
2. .tkn — extensión del paquete
Choca con .swm (266 menciones; Etapa F entera encima). Resultó mucho más barato de lo
estimado, y por una razón medida: la extensión no es lógica, es salida.
- Se escribe en un solo lugar (
crates/hammer-cli/src/main.rs:1800).
- El descubrimiento de paquetes va por índice, no por glob:
PackageEntry.file
(crates/hammer-core/src/repo.rs:75) guarda el nombre real de cada fichero.
- ⇒ Los repos existentes no se rompen y un repo mixto es válido: un índice con entradas
.swm
sigue resolviendo, y los paquetes nuevos se escriben .tkn. No hace falta migrar nada.
- Cero ficheros
.swm versionados en el repo, así que no hubo qué renombrar.
Swm, SwmBuild, swm_path, swm_bridge NO se tocan. Son nombres de tipo y de módulo, no
superficie de usuario; renombrarlos es churn puro dentro de la etapa 4.
Nota sobre los ficheros de marca
Los dos SVG difieren correctamente (chispa #FFF6DE sobre oscuro, #17130E sobre claro) —
verificado por sha256 y por los colores presentes, no por el nombre del fichero. Ambos traen un
manifiesto C2PA de procedencia embebido; se conserva tal cual vino, sin limpiar.