Utensil's Zettelkasten-style forest of evergreen notes on math and tech. utensil.tngl.sh/forest/
0

Configure Feed

Select the types of activity you want to include in your feed.

fix(infra): iter 95 — re-enable forest-texlive (option b per operator)

After iter 87-94 couldn't get dvisvgm to load LM OTF native font
references that tectonic emits in XDV (lmroman10-italic, etc.) via
extension-less PWD symlinks + OPENTYPEFONTS env hacks, switch to a
real TEXMF tree via texlive.combine.

Changes:
flake.nix — forest-texlive RE-ENABLED in packages output;
texCombo extended with lm, lm-math, cm-super, pxfonts,
mathpazo, psnfss, algorithmicx, algpseudocodex, pseudo,
tcolorbox, todonotes, utfsym, l3keys2e, pgfplots, tipa,
physics — covering every font + macro pkg the render
has been staging piecemeal via stage_tl_pkg.

build-depot.yml — adds 'nix build .#forest-texlive', packages it as
forest-texlive-x86_64.nar.zst with full closure,
adds 'texlive' entry to manifest.json + the R2
upload list.

render.yml — manifest asset discovery picks up .assets.texlive (or
warns + falls back if missing — for backward compat with
iter 94's manifest until build-depot re-runs);
nix-store --imports the texlive closure;
adds /bin to PATH (mktexlsr, kpsewhich, etc.);
sets TEXLIVE_TEXMF=/share/texmf-dist;
dvisvgm shim now prepends TEXLIVE_TEXMF to TEXMFAUXTREES
so kpathsea searches the canonical fonts/<type>/public/<pkg>/
tree first.

Heavier rebuild: depot will rebuild from scratch with the texlive
combine (~5-10m on top of existing tectonic + forester builds).

Refs #2

[AGENT: kael]

+81 -20
+18 -7
.tangled/workflows/build-depot.yml
··· 70 70 du -sh "$wasm_out" 71 71 echo "::endgroup::" 72 72 73 - # forest-texlive removed: tectonic-only approach (operator directive). 73 + # iter 95 — RE-ENABLED forest-texlive build per operator directive 74 + # (option b in the chat). Provides a real TEXMF tree at runtime 75 + # so dvisvgm's kpathsea can find LM OTF fonts that tectonic emits 76 + # as native XDV font_def names. 77 + echo "::group::nix build .#forest-texlive" 78 + texlive_out=$(nix build .#forest-texlive --no-link --print-out-paths) 79 + echo "texlive: $texlive_out" 80 + du -sh "$texlive_out" 81 + echo "::endgroup::" 74 82 75 83 echo "::group::package tectonic + forester as NAR closures (full dep chain)" 76 84 # Plain tar of just $out is NOT enough — these reference libev / gmp / ··· 78 86 # nix-store --export of `nix-store -qR <root>` captures the whole 79 87 # closure; render does `nix-store --import` to land every path at 80 88 # its expected location. 81 - for pair in "tectonic:$tectonic_out" "forester:$forester_out"; do 89 + for pair in "tectonic:$tectonic_out" "forester:$forester_out" "texlive:$texlive_out"; do 82 90 name="${pair%%:*}" 83 91 path="${pair#*:}" 84 92 nix-store --export $(nix-store -qR "$path") | zstd -19 -T0 -o "forest-${name}-x86_64.nar.zst" ··· 98 106 99 107 echo "::group::generate manifest.json" 100 108 : "${R2_PUBLIC_URL:=https://pub-5462b73a50594a06b85663123d74ab23.r2.dev}" 101 - python3 - "$tectonic_out" "$forester_out" "$wasm_out" <<'PY' > manifest.json 109 + python3 - "$tectonic_out" "$forester_out" "$wasm_out" "$texlive_out" <<'PY' > manifest.json 102 110 import json, os, subprocess, sys 103 - tectonic, forester, wasm = sys.argv[1], sys.argv[2], sys.argv[3] 104 - # tectonic + forester are NAR closures (need nix-store --import); 111 + tectonic, forester, wasm, texlive = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4] 112 + # tectonic + forester + texlive are NAR closures (need nix-store --import); 105 113 # wasm-pkgs is plain tar. Mirror by using "nar" vs "tar" keys so the 106 - # render workflow can dispatch on which is which. texlive is no longer 107 - # bundled — operator directive: tectonic-only + latex shim. 114 + # render workflow can dispatch on which is which. 115 + # iter 95 — texlive re-added (forest-texlive provides a real TEXMF 116 + # tree with ls-R so dvisvgm/kpathsea can resolve native font names). 108 117 def info(name, ext, store_path): 109 118 fname = f"forest-{name}-x86_64.{ext}.zst" 110 119 with open(f"forest-{name}-x86_64.sha256") as f: ··· 119 128 "assets": { 120 129 "tectonic": info("tectonic", "nar", tectonic), 121 130 "forester": info("forester", "nar", forester), 131 + "texlive": info("texlive", "nar", texlive), 122 132 "wasm_pkgs": info("wasm-pkgs", "tar", wasm), 123 133 }, 124 134 } ··· 140 150 for f in \ 141 151 forest-tectonic-x86_64.nar.zst forest-tectonic-x86_64.storepath forest-tectonic-x86_64.sha256 \ 142 152 forest-forester-x86_64.nar.zst forest-forester-x86_64.storepath forest-forester-x86_64.sha256 \ 153 + forest-texlive-x86_64.nar.zst forest-texlive-x86_64.storepath forest-texlive-x86_64.sha256 \ 143 154 forest-wasm-pkgs-x86_64.tar.zst forest-wasm-pkgs-x86_64.storepath forest-wasm-pkgs-x86_64.sha256 \ 144 155 manifest.json; do 145 156 echo "uploading $f → s3://$R2_BUCKET/forest/$f"
+40 -7
.tangled/workflows/render.yml
··· 79 79 FORESTER_PATH=$(jq -r '.assets.forester.store_path' /tmp/manifest.json) 80 80 WASM_TAR=$(jq -r '.assets.wasm_pkgs.tar' /tmp/manifest.json) 81 81 WASM_PATH=$(jq -r '.assets.wasm_pkgs.store_path' /tmp/manifest.json) 82 + # iter 95 — texlive re-added: forest-texlive provides a proper 83 + # TEXMF tree at runtime so dvisvgm's kpathsea can resolve LM OTF 84 + # native font references. May be absent on first deploy until 85 + # build-depot re-runs. 86 + TEXLIVE_NAR=$(jq -r '.assets.texlive.nar // "missing"' /tmp/manifest.json) 87 + TEXLIVE_PATH=$(jq -r '.assets.texlive.store_path // ""' /tmp/manifest.json) 82 88 echo "::endgroup::" 83 89 84 - echo "::group::import tectonic + forester closures (nix-store --import)" 90 + echo "::group::import tectonic + forester + texlive closures (nix-store --import)" 85 91 # The .nar.zst archives carry every store path referenced by the 86 - # forester / tectonic binaries (libev, gmp, ocaml-runtime, etc.) so 87 - # the binaries' ELF interpreter refs resolve at runtime. Plain tar of 88 - # just $out was insufficient — bin/forester died with 'required file 89 - # not found' on its loader. 90 - for pair in "tectonic:$TECTONIC_NAR:$TECTONIC_PATH" \ 91 - "forester:$FORESTER_NAR:$FORESTER_PATH"; do 92 + # forester / tectonic / texlive binaries (libev, gmp, ocaml-runtime, 93 + # etc.) so the binaries' ELF interpreter refs resolve at runtime. 94 + # Plain tar of just $out was insufficient — bin/forester died with 95 + # 'required file not found' on its loader. 96 + _pairs=("tectonic:$TECTONIC_NAR:$TECTONIC_PATH" \ 97 + "forester:$FORESTER_NAR:$FORESTER_PATH") 98 + if [ "$TEXLIVE_NAR" != "missing" ] && [ -n "$TEXLIVE_PATH" ]; then 99 + _pairs+=("texlive:$TEXLIVE_NAR:$TEXLIVE_PATH") 100 + else 101 + echo "::warning::texlive asset not in manifest yet (build-depot may need to re-run for iter 95+)" 102 + fi 103 + for pair in "${_pairs[@]}"; do 92 104 name="${pair%%:*}"; rest="${pair#*:}" 93 105 nar="${rest%%:*}"; path="${rest#*:}" 94 106 echo "::group::fetch + nix-store --import $name" ··· 124 136 # `mkdir` isn't reachable). Do the equivalent inline so PATH stays 125 137 # additive against the nixery deps. 126 138 export PATH="$TECTONIC_PATH/bin:$FORESTER_PATH/bin:$PATH" 139 + # iter 95 — if forest-texlive was loaded, add its bin (kpsewhich, 140 + # mktexlsr, etc.) and put its texmf-dist on the kpathsea search 141 + # path so dvisvgm can find LM OTF/PFB at runtime via the real 142 + # kpathsea infrastructure (vs the iter 86-92 cwd-symlink hacks). 143 + if [ -n "${TEXLIVE_PATH:-}" ] && [ -d "$TEXLIVE_PATH/bin" ]; then 144 + export PATH="$TEXLIVE_PATH/bin:$PATH" 145 + # texlive.combine puts the merged texmf-dist tree at $out/share 146 + # (a symlink to the texCombo's share dir). kpathsea picks it up 147 + # via TEXMF env var or texmf.cnf; we just add it to TEXMFAUXTREES 148 + # for ADDITIVE search. 149 + if [ -d "$TEXLIVE_PATH/share/texmf-dist" ]; then 150 + export TEXLIVE_TEXMF="$TEXLIVE_PATH/share/texmf-dist" 151 + echo "✓ forest-texlive texmf-dist at $TEXLIVE_TEXMF" 152 + ls -la "$TEXLIVE_TEXMF/fonts/opentype/public/lm/" 2>/dev/null | head -5 || echo " (no LM OTFs)" 153 + fi 154 + fi 127 155 # forest-tectonic stages dvips .pro headers (tex.pro, texps.pro, 128 156 # special.pro, color.pro, finclude.pro) directly at $out/share/dvips/ 129 157 # base/ (copied at flake build time from texlive.combine — symlinking ··· 350 378 if [ -n "\${FOREST_TEXMF:-}" ]; then 351 379 # trailing '//' tells kpathsea to recurse 352 380 export TEXMFAUXTREES="\${FOREST_TEXMF}//,\${TEXMFAUXTREES:-}" 381 + fi 382 + # iter 95 — also add forest-texlive's texmf-dist (real kpathsea- 383 + # indexed TEXMF tree from nixpkgs's texlive.combine, with ls-R). 384 + if [ -n "\${TEXLIVE_TEXMF:-}" ]; then 385 + export TEXMFAUXTREES="\${TEXLIVE_TEXMF}//,\${TEXMFAUXTREES:-}" 353 386 fi 354 387 355 388 if head -c 4 "\$tmp" 2>/dev/null | grep -q "^%PDF"; then
+23 -6
flake.nix
··· 67 67 amscls amsfonts amsmath 68 68 etoolbox xpatch xstring xkeyval 69 69 carlisle l3packages 70 - graphics-def; 70 + graphics-def 71 + # iter 95 — Latin Modern + CM-Super + math-friendly fonts so 72 + # dvisvgm's kpathsea finds OTF/PFB for native font references 73 + # tectonic emits in XDV. These mirror what stage_tl_pkg has 74 + # been flat-copying into FOREST_TEX_DIR; pulling them into the 75 + # texlive.combine tree gives dvisvgm a proper kpathsea-indexed 76 + # search instead of relying on extension-less cwd symlinks. 77 + lm lm-math cm-super pxfonts mathpazo psnfss 78 + # Algorithm packages — used by ag-0018, uts-001F, uts-0018, etc. 79 + algorithmicx algpseudocodex pseudo tcolorbox 80 + # forester package dependencies (some already covered) 81 + todonotes utfsym l3keys2e 82 + # newpx auxiliary fonts (tx fonts for math chains) 83 + pgfplots tipa physics; 71 84 }; 72 85 in pkgs.stdenv.mkDerivation { 73 86 pname = "forest-texlive"; ··· 477 490 forest-tectonic = forestTectonicFor pkgs; 478 491 forest-forester = forestForesterFor pkgs; 479 492 forest-wasm-pkgs = forestWasmPkgsFor pkgs; 480 - # forest-texlive removed per operator: tectonic-only approach. 481 - # render.yml shims `latex` → tectonic --outfmt xdv → rename .xdv 482 - # to .dvi; real `dvisvgm` from nixery reads the XDV-format file. 483 - # Auto-download of CTAN packages by tectonic replaces our combo. 484 - # forest-texlive = forestTexliveFor pkgs; 493 + # iter 95 — RE-ENABLED per operator directive after 30+ iters of 494 + # tectonic-only experiments couldn't get dvisvgm to load LM OTF 495 + # fonts that tectonic's XDV emits as native font_def names 496 + # (lmroman10-italic, lmromancaps10-regular, etc.). texlive.combine 497 + # produces a real TEXMF tree with ls-R, which dvisvgm's kpathsea 498 + # actually honors at runtime — should restore the cmcsc10/cmti10 499 + # rendering and close the visible-overlap gap on uts-001F's pseudo 500 + # block + ag-0018. 501 + forest-texlive = forestTexliveFor pkgs; 485 502 } 486 503 ); 487 504