
This post lays out the ladder of dependencies underneath numerical code — architecture, driver, runtime, packages — and why pinning one rung leaves every other rung free to move.
Two machines can run the same source and still run different programs. The difference is usually below the application code, on a ladder of dependencies. A fix at one rung does not pin the others.
1 Ladder
Rungs, from the bottom:
- Chipset and instruction set — x86_64, arm64; CUDA, ROCm, Metal, or CPU-only.
- Operating system — distro, glibc, kernel, system compilers.
- Language runtime — e.g. CPython 3.11 vs 3.13, R 4.3 vs 4.4.
- Packages — direct and transitive (NumPy, dplyr, PyTorch, …).
- Application code — the only rung git tracks by default.
Example: numpy==2.1.3 still leaves the BLAS unspecified. A wheel may link MKL; a source build may link OpenBLAS. Same pin, different arithmetic.
A container pins OS and libc, not the host GPU driver.
2 Production engineering
Typical strategy: ship the machine with the code.
- Container image: OS, libc, system libraries, runtime as one artifact.
- Lockfiles:
uv.lock,package-lock.json,Cargo.lock,go.sum— resolved versions and hashes; install is a replay, not a fresh solve. - Devcontainers, CI, infrastructure-as-code pin the rest.
This works when the team can declare a target (often linux/amd64) and pay a platform group to keep images healthy.
3 Scientific computing
The same rungs, without control of the target: mixed laptops, a shared HPC cluster (no root, old glibc), maybe one GPU box.
Tools:
- conda / mamba / pixi: packages plus compiled C/C++/Fortran libraries; pixi lockfiles cover several platforms in one file.
- R renv; Julia
Project.toml/Manifest.toml. - Apptainer (formerly Singularity): rootless containers for HPC. Docker’s privileged daemon is usually forbidden on shared clusters.
- Nix / Guix: hashed source rebuilds.
- Snakemake / Nextflow: per-step containers in a workflow graph.
A paper’s code needs to run in five to ten years for a replicator with no access to the author.
Trisovic et al. executed ~9,000 R files from 2,000+ Harvard Dataverse replication deposits (2010–2020). 74% failed without error; an automatic repair pass left 56% still failing.
4 Hardware and OS failures
Two axes: where the code runs (laptop, cloud VM including arm64 Graviton, HPC, edge) and what silicon (x86_64 vs arm64; CUDA / ROCm / Metal / CPU).
Examples a lockfile does not fix:
- PyTorch CUDA 12.4 wheel on a driver that only supports 12.1 — fails at import.
- No arm64 wheel; pip builds from source and dies on a missing Fortran/BLAS toolchain.
- Last digits change: IEEE-754 addition is not associative; compilers (
-ffast-math, FMA) and BLAS/thread count reorder sums.
5 Language coverage
- Python: pip pins packages only. conda/pixi reach compiled libraries and CUDA. uv pins packages and the Python version; universal lockfile via a forking resolver;
--exclude-newerfor dated resolves. - R: renv snapshots; CRAN serves current versions, so Posit Package Manager dated CRAN snapshots matter. Bioconductor trains couple R version to packages.
- Julia:
Project.toml+Manifest.tomlincluding Julia version; JLL packages put some native libs in the manifest. - C/C++/Fortran: CMake, vcpkg, Conan; Fortran fpm is young. Compiler and ABI are mostly unpinned. Fortran still sits under LAPACK, hence under NumPy and R.
- Shell:
awk/sed/grepare ambient (BSD vs GNU). No lockfile. - JavaScript: npm/pnpm/yarn lock packages. Bun can compile a self-contained executable (runtime in the artifact).
6 Agents
An agent that writes a patch, runs tests, and iterates pays environment cost every loop. Slow or non-deterministic resolves become a correctness problem: the agent cannot tell a failed edit from dependency drift.
Tooling acquisitions (context for why lockfiles got cheaper):
- December 2025: Anthropic acquired Bun (announcement; Bun).
- March 2026: OpenAI agreed to acquire Astral (uv, Ruff, ty).
- June 2026: OpenAI agreed to acquire Ona (persistent cloud environments).
None of this removes a CUDA-driver mismatch. It raises the cost of leaving a rung unpinned.
Commit architecture, driver, runtime, and the resolved lockfile next to the code.
Source. Isn’t. The. Program. Rungs. Move. Independently. Pin. Every. One.
7 References
- uv documentation — resolution and universal lockfiles
- pixi; prefix.dev on conda → pixi
- Trisovic et al., A large-scale study on research code quality and execution
- Apptainer documentation; Apptainer Without Setuid
- Julia Pkg —
Project.tomlandManifest.toml - renv; Nextflow
- Bun documentation
- Bun is joining Anthropic; Anthropic announcement
- OpenAI to acquire Astral; OpenAI to acquire Ona
- Simon Willison on the Astral acquisition