2026-07-20 lib.uv Refactor and athena 26.05 Pin
What I set out to do
Started as a discussion, not a task. A long thread on where the Nix - Home Manager module set sits relative to AOP / feature-oriented programming and the dendritic pattern, which surfaced two concrete pieces of work: the uvLib helper was distributed the wrong way, and athena (x86_64-darwin) had been frozen by a nixpkgs change. Both landed on main.
What I actually did
The framing thread (feeds the atomic notes)
Worked through AOP vs FOP against the actual tree, grounded in cloned copies of mightyiam/infra, vic/den, Misterio77, EmergentMind, srid rather than recall. Findings worth keeping:
- Squatting
programs.*/services.*for repo-declared options is the dominant practice, not a smell. Nobody uses amy.*/custom.*prefix; cross-cutting concepts get bare top-level nouns (hostSpec,colorscheme). There is no official position in the nixpkgs/HM manuals. Solocal.*is unusual only in having a prefix at all, andprograms.signozsquatting is fine. A duplicate option declaration is a loud eval error, not a silent hazard (verified). - Dendritic lists boolean
enableoptions as an anti-pattern (“importing a module should enable the feature it provides”). That is only coherent with curated imports; it is incompatible with auto-discovery by construction. Our desktoplistFilesRecursiveforces the flags. So the capability model is the tax auto-discovery charges, not an independent design choice. import-tree(vic) is a packagedlistFilesRecursive; the load-bearing part of dendritic is the named bucket, not the glob. We import everything into one bucket (annotation-heavy); dendritic imports into many (composition-heavy). Duals: a dead flag is silent for us, a missed guard reaches the build for them.- Wrote The Nix Module System Has No Dependency Resolution: import is the only edge,
imports+dedup is manual dependency declaration not resolution, and the only native expression of “A requires B” is anassertionsthat fails, never one that resolves. This is exactly why theuvLib/claude.nixcoupling could not be auto-satisfied.
lib.uv refactor (commit 7b40430)
uvLib was injected via _module.args.uvLib: python.nix set the real builder under mkIf local.python.enable, base.nix defaulted it to null, consumers guarded on hasUv = uvLib != null. That is a hidden transitive dependency — a module’s value depended on whether python.nix was imported, an edge written nowhere. claude.nix dereferenced it unconditionally, safe only because the one host with python.enable=false also happened not to import claude.nix.
Moved the builder to nix/lib/uv.nix, exposed as lib.uv.mkProject by extending the module-arg lib at the flake boundary in mkHome. Verified the mechanism against HM source: homeManagerConfiguration takes lib ? pkgs.lib, and modules/default.nix re-extends it with lib.hm via stdlib-extended.nix; .extend composes, so modules see both lib.uv and lib.hm. This is the EmergentMind/Misterio lib.extend convention, applied to a helper that closes over flake inputs (partial-applied at the boundary, like Misterio’s import ./lib/colors.nix { lib = base; }).
The deeper fix was decoupling the builder from the capability flag: building a local tool is a pure function of flake inputs, orthogonal to whether the host provisions the Python stack. local.python.enable had conflated them. Consequence: shell.nix/claude.nix build their venvs unconditionally (self-contained, no uv CLI at runtime), the hasUv gate is gone, and generateCheckUpstreamIssuesCompletion — a uv run tool that does need the CLI — now gates on local.python.enable specifically. The claude.nix bug is fixed at the root: no null to deref.
athena 26.05 pin (commit 20d7075)
nixpkgs-unstable dropped x86_64-darwin (Intel Mac sunset), so the shared unstable nixpkgs aborts instantiating that system. athena was frozen. Pinned x86_64-darwin’s nixpkgs to the maintained nixpkgs-26.05-darwin branch (last release supporting the platform, tip current today), selected per-system in perSystem’s _module.args.pkgs and the base16 helper.
Two decisions I reversed on evidence:
- Not a matched HM pin. First added
home-manager release-26.05too; eval failed onprograms.fzf.changeDirWidget does not exist— our modules use HM-master-only options. So HM stays on master, only nixpkgs moves. That is the minimal delta from athena’s prior working env. - Not a frozen unstable SHA. Tempting for minimal skew, but 26.05-darwin is maintained and is exactly what nixpkgs’ deprecation warning recommends.
The HM-master-vs-26.05 skew surfaced one assertion: HM master defaults enableNushellIntegration on and asserts fzf >= 0.73; 26.05 ships 0.72. We never use nushell, so it is now explicitly off (harmless everywhere).
What was striking
- The whole
uvLibmess traces to one line:home.nix’slistFilesRecursive. Auto-discovery → must-have-flags → ambient injection → the null dance → the bug. The refactor didn’t add a feature; it undid a coupling that auto-discovery had forced. - Three times this session a “last available version” or “which lib” question had a non-obvious right answer that only reading source (HM
eval-config.nix, the fzf assertion, the nixpkgs branch dates) settled.26.05-darwintip being dated today is what killed the frozen-SHA option. - atlas
drvPathstayedzvdqhbqmm3k9across every step of both changes, and athena878f8pvaz36across the merge. The list-ordering discipline (reference_nix_module_nesting_reorders_lists) held.
Still open
- athena needs a real
hm switchto fully validate: eval is clean, but x86_64-darwin cannot build on the aarch64 host, so build-time skew in unstable-following inputs (stylix, the uv2nix/pyproject trio) built against 26.05 pkgs can only surface there. Expected harmless warning on switch:home.enableNixpkgsReleaseCheckflagging the intentional HM/nixpkgs mismatch; silencing it on the server profile is a one-line follow-up. - The two flake.nix commits both restructured
mkHome, so the branch merge conflicted; resolved by re-applying the refactor surgically onto main rather than fighting diff3 markers.
Related
- Dotfiles Host Profiles via Private Flake — the project; updated with both commits.
- The Nix Module System Has No Dependency Resolution, Dendritic Pattern Borrows AOP Vocabulary But Realizes SPL Composition, Nix Module System Realizes Multi-Dimensional Separation of Concerns — the framing notes.
- Migrate uvx.nix to uv2nix — where
mkUvProject/uvLiboriginated (ADR 0003).