sergio/takana
> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…
takana etapa 5a: los comentarios de las 741 recetas
1# Importada de nixpkgs por `takana import-nix` (Etapa G). PUNTO DE PARTIDA, no final:
2# - el build usa el lab de takana (zig-cc / musl estático), NO el stdenv de nix ⇒ revisá
3# compiler/link/phases y adaptá hasta que compile.
4# - las deps van con su nombre NIX; remapealas a las recetas del corpus si difieren.
5name = "aichat"
6version = "0.30.0"
7license = "MIT OR Apache-2.0"
8
9[source]
10repo = "https://github.com/sigoden/aichat"
11commit = "430416d914896c3534c04b84c0226910c64e3e66"
12
13[build]
14compiler = "zig-cc"
15target = "x86_64-linux-musl"
16link = "static"
17flags = ["--bin", "aichat"]
18
19[build.phases]
20# ── ⚠ SIN ESTO, aichat NO ES REPRODUCIBLE ──────────────────────────────────────────────────────
21# Medido el 2026-09-05 con `scripts/verificar-repro.sh`: dos reconstrucciones seguidas, misma
22# máquina y mismo lab, dan `usr/bin/aichat` distintos en `.rodata`. El primer byte que cambia cae
23# dentro de un JSON de *stopwords* por idioma embebido en el binario, y lo que difiere es el ORDEN
24# de los idiomas — una build empieza por `"sl"`, la otra por `"fi"`.
25#
26# La causa está en el `build.rs` del crate `stop-words` 0.8.1 (transitivo, vía bm25): arma un
27# `HashMap<String, Vec<String>>` y lo serializa con `serde_json::to_string`. El `HashMap` de Rust
28# usa `RandomState`, o sea una semilla ALEATORIA POR PROCESO ⇒ el orden de serialización cambia en
29# cada compilación, y ese JSON se hornea en el binario. `BTreeMap` serializa en orden de clave y es
30# determinista; es un arreglo de una palabra que upstream no hizo.
31#
32# El `.cargo-checksum.json` se vacía por la misma razón que en `recipes/firefox.toml`: cargo
33# verifica el sha de CADA fichero vendorizado y no ofrece forma de recalcularlo, así que se deja el
34# checksum del paquete y se vacía la lista de ficheros (lo mismo hace el APKBUILD de Alpine).
35#
36# Los `[ -f ]` fallan RUIDOSO a propósito: si mañana la cadena de deps deja de traer stop-words, lo
37# que no queremos es que el parche se salte en silencio y el binario vuelva a ser aleatorio sin que
38# nadie se entere — que es exactamente cómo esto llegó hasta acá.
39configure = '''
40set -e
41f=vendor/stop-words/build.rs
42[ -f "$f" ] || { echo "FALTA $f — ¿cambió la cadena de deps? Ver la nota de arriba." >&2; exit 1; }
43sed -i 's/HashMap/BTreeMap/g' "$f"
44grep -q 'BTreeMap<String, Vec<String>>' "$f" || { echo "el sed no agarró en $f" >&2; exit 1; }
45c=vendor/stop-words/.cargo-checksum.json
46[ -f "$c" ] || { echo "FALTA $c" >&2; exit 1; }
47sed -i 's/\("files":{\)[^}]*/\1/' "$c"
48'''
49install = "mkdir -p /out/usr/bin && cp target/release/aichat /out/usr/bin/aichat"