tawasuyu

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…

TOML 1411Shell 141Markdown 84Rust 832898 Sutichaykuna

recetas: typst 0.15.1 y jj 0.45.1 — CLI en Rust puro, cero deps C, y cada una con su prueba de que HACE algo

8bca2d966416d544f066ca2447da0648019c5c82 · ruwaq Sergio · (9 p'unchaw ñawpaq) · tayta 159b5d57c · kay commitpi sach'ata qhaway

Semántico sayk'uy

Mana ima sutichaypas t'ikrakurqanchu: qillqalla, yachachiylla utaq willaylla t'ikrakurqan.

2 qillqakuna · +187 −0

diff --git a/recipes/jj.toml b/recipes/jj.toml
new file mode 100644
index 00000000..c0157af5
--- /dev/null
+++ b/recipes/jj.toml
@@ -0,0 +1,102 @@
+# jj (jujutsu) — control de versiones moderno, compatible con git, en Rust puro
+#
+# ── POR QUÉ ENTRA ──────────────────────────────────────────────────────────────────────────────
+# 32.018★, Apache-2.0, 549 crates, un solo binario sin interfaz gráfica. Lo que lo hace barato para
+# esta casa sale del `Cargo.lock` y no del README: **habla git sin `libgit2`**. Son **53 crates
+# `gix-*`** (gitoxide, git reimplementado en Rust) y **cero `git2`/`libgit2-sys`** ⇒ ninguna receta C
+# nueva, ningún `.pc` que buscar. El único C del árbol es `libmimalloc-sys`, que trae su propio
+# fuente y lo compila con el crate `cc` — de ahí el envoltorio de `AR`.
+#
+# No reemplaza a `git`, que sigue siendo el que usa todo el repo y la granja: convive con él sobre
+# los mismos repositorios.
+#
+# ── ⚠ POR QUÉ 0.45.1 Y NO LA ÚLTIMA, QUE ES LO MÁS IMPORTANTE DE ESTA RECETA ──────────────────
+# La release vigente al 2026-10-13 es **0.46.0**, y **no entra**: declara `rust-version = "1.97.1"`
+# y el lab de takana trae **rustc 1.97.0** (`docs/state/lab-toolchain.lock`: `rust-1.97.0-r0`).
+# Son dos números de parche y es un muro duro: cargo se niega antes de compilar nada.
+#
+# El salto es de upstream y es brusco —0.45.1 pedía **1.89**, o sea ocho versiones menos— así que
+# esto no es «quedarse atrás»: es el techo del lab, que es [[cargo-recipe-msrv-ceiling]]. Y subir el
+# lab **no es una opción local**: el lab entra en `hash_inputs`, así que un `bootstrap-devfs.sh
+# --relock` por una receta re-hashea el corpus entero. Cuando el lab suba por otra razón, esta receta
+# puede ir a 0.46.0 cambiando dos líneas.
+name    = "jj"
+version = "0.45.1"
+license = "Apache-2.0"
+
+[source]
+# `v0.45.1`. Se pinea el SHA del tag: un tag se mueve.
+repo   = "https://github.com/jj-vcs/jj"
+commit = "7c41cdeb16b6b321c64e789a966b6adf723816a5"
+# No committea `vendor/` ni usa `[patch.crates-io]` ⇒ el vendoreo va al `vendor/` por defecto sin
+# pisarle nada (la trampa que mató a `pdfcraft`; comprobado en el árbol del tag).
+
+[build]
+compiler = "zig-cc"
+target   = "x86_64-linux-musl"
+# `static`: es una herramienta de línea de comandos y no carga nada por `dlopen`.
+link     = "static"
+# Los features por defecto de `jj-cli` son `["watchman", "git"]` y se dejan: `git` es la razón de
+# existir del binario acá, y `watchman` es sólo un CLIENTE en Rust del vigía de ficheros de Meta —si
+# el demonio no está, la función queda apagada y no pasa nada.
+flags    = ["-p", "jj-cli", "--bin", "jj"]
+
+[build.phases]
+compile = '''
+set -e
+# El envoltorio de `AR` no es decorativo: el default de zig-cc exporta `AR="zig ar"` CON ESPACIO y el
+# crate `cc` —que acá compila `libmimalloc-sys`— ejecuta `$AR` como un binario ÚNICO ⇒ busca uno
+# llamado «zig ar» y falla. Cicatriz de `mise.toml`.
+printf '%s\n' '#!/bin/sh' 'for a do' 'case "$a" in --target=*) a=--target=x86_64-linux-musl ;; esac' 'set -- "$@" "$a"' 'shift' 'done' 'exec zig cc -mcpu=baseline "$@"' > "$PWD/.hammer-zig-cc"
+chmod +x "$PWD/.hammer-zig-cc"
+printf '%s\n' '#!/bin/sh' 'exec zig ar "$@"' > "$PWD/.hammer-zig-ar"
+chmod +x "$PWD/.hammer-zig-ar"
+RF="-C linker=$PWD/.hammer-zig-cc"
+rustc -vV | grep -q 'host: .*-alpine-' || RF="$RF -C link-self-contained=no"
+CC="$PWD/.hammer-zig-cc" AR="$PWD/.hammer-zig-ar" RUSTFLAGS="$RF" cargo rustc --release --locked --offline -p jj-cli --bin jj -- -C target-feature=+crt-static -C relocation-model=static
+'''
+install = '''
+set -e
+test -x target/release/jj || { echo "no hay target/release/jj — ¿cambió el nombre del bin?" >&2; exit 1; }
+
+# ── LA PRUEBA DE QUE NO ES UN NOMBRE: QUE CREE UN REPOSITORIO Y LO LEA ────────────────────────
+# `--version` sólo prueba que el binario arranca. Lo que se mide acá es que el **backend de git en
+# Rust** funciona de verdad: crear un repo, escribir un fichero y que `jj` lo vea como cambio. Si
+# eso no pasa, esta receta no debe sellar (memoria: «subcomando SIN DRIVER = binario inerte»).
+export HOME="$PWD/.smoke/home" JJ_USER="takana" JJ_EMAIL="takana@localhost" JJ_CONFIG="$PWD/.smoke/jj.toml"
+mkdir -p "$HOME" "$PWD/.smoke/repo"
+: > "$JJ_CONFIG"
+./target/release/jj --version > "$PWD/.smoke/v" 2>&1 || { echo "jj --version falló:" >&2; cat "$PWD/.smoke/v" >&2; exit 1; }
+grep -q "^jj 0.45.1" "$PWD/.smoke/v" || { echo "jj dice '$(cat "$PWD/.smoke/v")' y la receta pinea 0.45.1" >&2; exit 1; }
+./target/release/jj git init "$PWD/.smoke/repo" > "$PWD/.smoke/init" 2>&1 || { echo "jj git init falló:" >&2; cat "$PWD/.smoke/init" >&2; exit 1; }
+test -d "$PWD/.smoke/repo/.jj" || { echo "jj git init salió 0 y NO dejó .jj — el caso «sale bien y no hizo nada»" >&2; exit 1; }
+echo hola > "$PWD/.smoke/repo/f.txt"
+./target/release/jj -R "$PWD/.smoke/repo" status > "$PWD/.smoke/st" 2>&1 || { echo "jj status falló:" >&2; cat "$PWD/.smoke/st" >&2; exit 1; }
+grep -q "f.txt" "$PWD/.smoke/st" || { echo "jj status no vio el fichero nuevo:" >&2; cat "$PWD/.smoke/st" >&2; exit 1; }
+echo "smoke: jj creó el repo, vio el cambio, y todo con gitoxide (sin libgit2)"
+
+install -Dm755 target/release/jj /out/usr/bin/jj
+install -Dm644 LICENSE /out/usr/share/licenses/jj/LICENSE
+
+# Completado de shell y manual, generados por el propio binario. ⚠ A diferencia de todo lo de
+# arriba, un fallo acá NO tumba el build y es deliberado: el contrato de esta receta es el binario;
+# el completado es comodidad. Si el subcomando cambia de nombre en un bump, se quiere ver el aviso
+# en el log, no perder el artefacto entero.
+for sh in bash zsh fish; do
+  if ./target/release/jj util completion "$sh" > "$PWD/.smoke/jj.$sh" 2>/dev/null && [ -s "$PWD/.smoke/jj.$sh" ]; then
+    case "$sh" in
+      bash) install -Dm644 "$PWD/.smoke/jj.$sh" /out/usr/share/bash-completion/completions/jj ;;
+      zsh)  install -Dm644 "$PWD/.smoke/jj.$sh" /out/usr/share/zsh/site-functions/_jj ;;
+      fish) install -Dm644 "$PWD/.smoke/jj.$sh" /out/usr/share/fish/vendor_completions.d/jj.fish ;;
+    esac
+  else
+    echo "aviso: 'jj util completion $sh' no produjo nada — ¿cambió el subcomando? el binario SÍ está" >&2
+  fi
+done
+test -s /out/usr/bin/jj
+'''
+
+[deps]
+# Ninguna, y es medido: sin `libgit2-sys`, sin `openssl-sys`, sin `zlib` del sistema. `libmimalloc-sys`
+# compila su propio C con el crate `cc`. Un `[deps]` vacío acá significa «no necesita nada».
+build = []
diff --git a/recipes/typst.toml b/recipes/typst.toml
new file mode 100644
index 00000000..e7efd5bb
--- /dev/null
+++ b/recipes/typst.toml
@@ -0,0 +1,85 @@
+# typst — composición tipográfica moderna: el hueco de LaTeX, que este catálogo no tenía de ninguna forma
+#
+# ── POR QUÉ ENTRA ──────────────────────────────────────────────────────────────────────────────
+# 56.592★, Apache-2.0, 435 crates, **Rust puro y CLI**: ni toolkit, ni muro gráfico, ni decisión de
+# distro. Y cubre una función que el catálogo **no tiene por ningún lado** —componer un documento
+# desde texto plano, con bibliografía, fórmulas y PDF reproducible—, que es justo la otra mitad de
+# lo que la suite ArtCraft trajo el 2026-10-13: `wordcraft` edita y exporta, `typst` COMPONE.
+#
+# El dato que la vuelve barata, y que sale del `Cargo.lock`, no del README: **cero dependencias C de
+# tipografía**. Su `fontconfig-parser` es un parser de los ficheros de fontconfig **escrito en Rust**
+# —no la `libfontconfig` de C— y las fuentes van por `fontdb` + `ttf-parser` + fontations
+# (`read-fonts`/`write-fonts`). Lo único C del árbol es `libdeflate-sys`, que trae su propio fuente y
+# lo compila con el crate `cc`; de ahí el envoltorio `AR` de abajo.
+#
+# ── LAS DOS PERILLAS QUE IMPORTAN, Y POR QUÉ SE DEJAN COMO ESTÁN ───────────────────────────────
+# `typst-cli` trae `default = ["embedded-fonts", "http-server"]`:
+#   · **`embedded-fonts` se queda**: mete las fuentes dentro del binario, así que `typst compile`
+#     funciona en una imagen que no declare ni una familia tipográfica. Sin eso, el fallo sería el
+#     clásico de esta casa —binario sellado, presente, y sin con qué dibujar una letra.
+#   · **`self-update` NO está en el default y no se enciende**: se actualiza por `takana install`,
+#     como todo acá, y encenderlo arrastraría `xz2` y `zip` de yapa.
+#   · **`vendor-openssl` tampoco**: no hace falta: en el lock **no hay `openssl-sys`** —las descargas
+#     de paquetes de typst van por `ureq`+rustls— y esa es la razón de que esta receta no declare
+#     `openssl` en `[deps]`.
+name    = "typst"
+version = "0.15.1"
+license = "Apache-2.0"
+
+[source]
+# `v0.15.1` (release del 2026-07-17). Se pinea el SHA del tag: un tag se mueve.
+# ⚠ El endpoint de tags de GitHub devuelve primero unos `v23-03-28` que son de 2023 y NO son la
+# versión vigente: hay que preguntarle a `releases/latest`, no a `tags`.
+repo   = "https://github.com/typst/typst"
+commit = "9dfd3a08500b7896045f907433cf7b4b02434fad"
+# No committea `vendor/` ni usa `[patch.crates-io]` ⇒ el vendoreo va al `vendor/` por defecto sin
+# pisarle nada (la trampa que mató a `pdfcraft` no aplica; comprobado en el árbol del tag).
+
+[build]
+compiler = "zig-cc"
+target   = "x86_64-linux-musl"
+# `static` y no `dynamic`: es una herramienta de línea de comandos, no carga nada por `dlopen`.
+link     = "static"
+flags    = ["-p", "typst-cli", "--bin", "typst"]
+
+[build.phases]
+compile = '''
+set -e
+# El envoltorio de `AR` no es decorativo: el default de zig-cc exporta `AR="zig ar"` CON ESPACIO, y
+# el crate `cc` —que acá compila `libdeflate-sys`— ejecuta `$AR` como un binario ÚNICO ⇒ busca uno
+# llamado «zig ar» y falla. Es la cicatriz de `mise.toml`.
+printf '%s\n' '#!/bin/sh' 'for a do' 'case "$a" in --target=*) a=--target=x86_64-linux-musl ;; esac' 'set -- "$@" "$a"' 'shift' 'done' 'exec zig cc -mcpu=baseline "$@"' > "$PWD/.hammer-zig-cc"
+chmod +x "$PWD/.hammer-zig-cc"
+printf '%s\n' '#!/bin/sh' 'exec zig ar "$@"' > "$PWD/.hammer-zig-ar"
+chmod +x "$PWD/.hammer-zig-ar"
+RF="-C linker=$PWD/.hammer-zig-cc"
+rustc -vV | grep -q 'host: .*-alpine-' || RF="$RF -C link-self-contained=no"
+CC="$PWD/.hammer-zig-cc" AR="$PWD/.hammer-zig-ar" RUSTFLAGS="$RF" cargo rustc --release --locked --offline -p typst-cli --bin typst -- -C target-feature=+crt-static -C relocation-model=static
+'''
+install = '''
+set -e
+test -x target/release/typst || { echo "no hay target/release/typst — ¿cambió el nombre del bin?" >&2; exit 1; }
+
+# ── LA PRUEBA DE QUE NO ES UN NOMBRE: COMPONER UN DOCUMENTO DE VERDAD ─────────────────────────
+# Un binario sellado, con contenido y reproducible puede igual no hacer NADA (memoria:
+# «subcomando SIN DRIVER = binario inerte»). Acá eso tiene una forma concreta y barata de medirse:
+# que componga. Si `typst compile` no produce un PDF, esta receta NO debe sellar — un typst que no
+# compone es exactamente la clase de artefacto que llega hasta el final diciendo que todo fue bien.
+mkdir -p "$PWD/.smoke"
+printf '%s\n' '#set page(width: 80pt, height: 40pt, margin: 4pt)' '= Takana' 'Compone.' > "$PWD/.smoke/p.typ"
+./target/release/typst compile --font-path "$PWD/.smoke" "$PWD/.smoke/p.typ" "$PWD/.smoke/p.pdf" 2>"$PWD/.smoke/err" || { echo "typst compile FALLÓ:" >&2; cat "$PWD/.smoke/err" >&2; exit 1; }
+test -s "$PWD/.smoke/p.pdf" || { echo "typst compile salió 0 y el PDF quedó VACÍO" >&2; exit 1; }
+head -c 5 "$PWD/.smoke/p.pdf" | grep -q '%PDF-' || { echo "lo que salió no es un PDF" >&2; exit 1; }
+echo "smoke: typst compuso $(wc -c < "$PWD/.smoke/p.pdf") bytes de PDF con las fuentes EMBEBIDAS"
+
+install -Dm755 target/release/typst /out/usr/bin/typst
+install -Dm644 LICENSE /out/usr/share/licenses/typst/LICENSE
+install -Dm644 NOTICE  /out/usr/share/licenses/typst/NOTICE
+test -s /out/usr/bin/typst
+'''
+
+[deps]
+# Ninguna. Y es un hecho medido, no un olvido: el lock no trae `openssl-sys`, ni `fontconfig`, ni
+# `freetype`, ni `zlib` del sistema —`libz-rs-sys` es zlib EN RUST— y `libdeflate-sys` compila su
+# propio C. Un `[deps]` vacío acá significa «no necesita nada», no «no se revisó».
+build = []