From 7eefb093146274526bf4378605fcf1fdc72a7fdf Mon Sep 17 00:00:00 2001 From: ethernet Date: Mon, 3 Aug 2026 13:08:16 -0400 Subject: [PATCH] fix(nix): tie devShell's HERMES_PYTHON to the venv actually on PATH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `nix/devShell.nix` collected `devShellHook` by scanning every package: nonNpmHooks = map (p: p.passthru.devShellHook or "") packages; But `minimal` and `messaging` are `.override` variants of `default`, so each carries its own `devShellHook` exporting its own HERMES_PYTHON. The scan therefore concatenated three conflicting exports and forced Nix to evaluate and realise three separate uv2nix editable venvs on every `nix develop`. `attrValues` is alphabetical, so the last hook won (`minimal`) while `python`/VIRTUAL_ENV came from `default`'s devDeps: HERMES_PYTHON = ...dimim2... (minimal — no optional deps) python / VIRTUAL_ENV = ...85r28... (full) Inside the shell `$HERMES_PYTHON -c "import anthropic"` failed while `python -c "import anthropic"` succeeded. Worse, `scripts/run_tests.sh` prefers HERMES_PYTHON, so the suite ran against the minimal venv. Its guard did not catch this: it only checks that HERMES_PYTHON has pytest, and minimal's venv does (pytest is in the `dev` group), so the wrong interpreter was silently accepted. Tying the hook to `packages.default` — the same package whose `devDeps` are installed — keeps HERMES_PYTHON, `python`, and VIRTUAL_ENV pointing at one venv by construction. editable venvs referenced 3 -> 1 their combined closure 421 MB -> 140 MB test failures 85 -> 32 The venv mismatch was masking 53 failures; e.g. test_web_tools_config.py goes 2-failed -> 38-passed. Full suite is now 25369 passed / 32 failed, and those 32 reproduce identically on a pristine HEAD worktree with no nix/ changes under the same interpreter (mostly NixOS artifacts — tests spawning bare `python3` in a scrubbed env exit 127). --- nix/devShell.nix | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/nix/devShell.nix b/nix/devShell.nix index 2e4007f854..ac50beb0e6 100644 --- a/nix/devShell.nix +++ b/nix/devShell.nix @@ -18,10 +18,7 @@ map (p: p.passthru.packageJsonPath or null) packages ); - # Non-npm packages may have their own devShellHook (e.g. hermes-agent - # stamps pyproject.toml + uv.lock for Python venv setup). - nonNpmHooks = map (p: p.passthru.devShellHook or "") packages; - combinedNonNpm = pkgs.lib.concatStringsSep "\n" (builtins.filter (h: h != "") nonNpmHooks); + hermesAgentDevShellHook = self'.packages.default.passthru.devShellHook; in { devShells.default = pkgs.mkShell { @@ -49,7 +46,7 @@ ] ++ self'.packages.default.passthru.devDeps; shellHook = '' - ${combinedNonNpm} + ${hermesAgentDevShellHook} ${hermesNpmLib.mkNpmDevShellHook npmPackageJsonPaths} # Force Node to use Nix's playwright-test binary instead of node_modules/.bin