Fix Poetry venv selection ignoring envs.toml (#476, #526) - #527
Conversation
Assisted-by: Claude Code:claude-opus-5-5
Agent mode, hosted mode's stale-install check and VEX picked the wrong Poetry virtualenv in two common setups, so the env `poetry run` uses stayed unpatched while the run reported success and VEX attested not_affected: - After `poetry env use 3.12` on a project that also has a 3.11 env, the alphabetically first env was patched. An unrelated activated VIRTUAL_ENV also won, although Poetry ignores it once envs.toml names the project (#526). - With `virtualenvs.in-project = true` but no ./.venv, the existing out-of-tree env Poetry keeps using was never probed (#476). Venv discovery now follows Poetry's EnvManager.get(): it reads envs.toml under virtualenvs.path, takes ./.venv only when it exists and in-project isn't false, and gates VIRTUAL_ENV / CONDA_PREFIX the way Poetry does. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 0b4a2df. Configure here.
|
[agent] Ready for review at
Generated by Claude Code |
|
[burn-down agent] Labeled Ready for review at
Generated by Claude Code |
|
Reviewed No actionable correctness/security regressions found. Checked Validation: |
Resolve the python_crawler.rs conflict with the Poetry env selection fix (#527): keep main's poetry_active_prefix for VIRTUAL_ENV and add the PDM_IGNORE_ACTIVE_VENV gate on top. Assisted-by: Claude Code:claude-opus-5-5
LLM Description written by Claude Code:claude-opus-5-5
Fixes #476
Fixes #526
Summary
Agent mode, hosted mode's stale-install check, and VEX now use the Poetry virtualenv that Poetry itself uses. Before this change, two common Poetry setups led socket-patch to patch (or inspect) the wrong environment. The env behind
poetry runstayed unpatched while the run reported success, andvexattestednot_affected.Root cause
Poetry venv discovery in
crates/socket-patch-core/src/crawlers/python_crawler.rsapproximated Poetry'sEnvManager.get()instead of following it:poetry env useon two Python minors), agent mode patches the alphabetically first env instead of the one Poetry activated, and VEX attests not_affected #526: it never read<virtualenvs.path>/envs.toml, wherepoetry env userecords the activated env. With several<name>-<hash>-py*envs it returned all of them in lexicographic order, so the first one (often a dead older minor) got patched. It also let an unrelated activatedVIRTUAL_ENVwin, but Poetry ignoresVIRTUAL_ENVonceenvs.tomlnames the project (second trigger in the issue thread).virtualenvs.in-project = trueas "only./.venv" andpoetry_virtualenvs_rootreturnedNonefor it. Poetry only uses./.venvwhen the directory exists (in_project_venv_exists). Otherwise it keeps installing into the existing out-of-tree env.Fix
Follow
EnvManager.get()for Poetry projects:load_poetry_projectreadsenvs.tomlundervirtualenvs.path([<name>-<hash>] minor = "X.Y"). When the project has an entry, only<name>-<hash>-pyX.Yis probed.VIRTUAL_ENVshortcut is gated the way Poetry gates it: it's skipped whenenvs.tomlhas an entry,CONDA_PREFIXis honoured likeVIRTUAL_ENV, and conda'sbaseenv doesn't count as an activated venv. This mirrors the existing Pipenv gate (pipenv_uses_virtual_env)../.venvis the env only when it exists andin-projectisn't an explicitfalse.virtualenvs.pathis resolved whateverin-projectsays, andcreate = falsestill opts out.load_poetry_projectnow takes the injected environment instead of reading the process env. This also removes a race between the new tests and the existing serial env-mutating test.docs/testing/poetry-compatibility.md"Mode notes" are updated to match.Hosted mode's
redirect_pypi_stale_installcheck andvexboth go throughfind_local_venv_site_packages, so they pick up the fix with no further changes. There are no wrapper changes:npm/,pypi/andgem/only dispatch to the binary.Per-issue checklist
3.10vs3.9lexicographic trap)crawlers::python_crawler::tests::poetry_envs_toml_activated_env_is_the_only_one_probedenvs.tomlbeatsVIRTUAL_ENV; conda prefix /basecrawlers::python_crawler::tests::poetry_envs_toml_entry_overrides_virtual_envVIRTUAL_ENVreturnedin-project = true(poetry.toml andPOETRY_VIRTUALENVS_IN_PROJECT) with no./.venvcrawlers::python_crawler::tests::poetry_in_project_true_without_dot_venv_keeps_the_out_of_tree_env[]Two existing assertions encoded the #476 behaviour (
in-project = true⇒ nothing probed, and aNonevirtualenvs root). They now assert Poetry's behaviour instead.Test evidence (Linux)
main's code: 3 failed (output above). With the fix:cargo test -p socket-patch-core --lib -- crawlers::python_crawlergives 57/57 passed.find_local_venv_site_packages):poetry env useon two Python minors), agent mode patches the alphabetically first env instead of the one Poetry activated, and VEX attests not_affected #526 layout:poetry env use python3.11, install, thenpoetry env use python3.12, install. The probe returns onlyenvmulti-…-py3.12, which is whatpoetry env info -pprints. It still returns that env with an unrelatedVIRTUAL_ENV=/tmp/other, and so does Poetry.poetry config --local virtualenvs.in-project trueand install again, leaving no./.venv. The probe returnsipapp-…-py3.11, matchingpoetry env info -p.cargo clippy --workspace --all-features -- -D warnings: clean.cargo test --workspace --all-features --no-fail-fast: all pass except 12 permission-based write-failure tests. They fail only because this sandbox runs as uid 0 (root ignores read-only bits), they fail the same way onmain, and all 12 pass when re-run as uid 65534.rustfmt --checkon the changed file: clean.mainisn'tcargo fmt-clean workspace-wide, so unrelated reflows were left out.Follow-ups (not in scope)
envs.tomlentry, Poetry picks the env matching the interpreter it would use (pythonon PATH or its own, depending onvirtualenvs.use-poetry-python). Resolving that would mean running an interpreter, so in that case every env is still returned, as before.vexcollapsing to the first copy (collapse_to_first) is tracked for npm in Agent-mode npmvexhashes only the first installed copy of a package, so it attests not_affected while another nested copy of the same name@version is unpatched #516 / Fix agent vex checking only one installed copy (#516) #517.🤖 Generated with Claude Code
https://claude.ai/code/session_01Rh6wkfBxavb2aj1JWKbSxM
Note
Medium Risk
Changes which
site-packagespaths agent mode patches—a wrong choice previously left the real Poetry env unpatched; the new logic is more complex but targets documented Poetry behavior with regression tests.Overview
Agent-mode Python crawling now picks the same virtualenv Poetry uses, instead of approximating it.
envs.toml(#526): The crawler reads<virtualenvs.path>/envs.tomlfor the envpoetry env userecorded and probes only that<name>-<hash>-py<minor>tree. When that entry exists, an unrelatedVIRTUAL_ENVis ignored; otherwiseVIRTUAL_ENVor a non-baseCONDA_PREFIXcan still win, matching Poetry’sEnvManager.get().In-project setting (#476):
virtualenvs.in-project = trueno longer blocks out-of-tree discovery when./.venvis missing—only an existing./.venv(and not an explicitin-project = false) counts as the in-project env.virtualenvs.path/envs.tomlresolution is unchanged byin-project.load_poetry_projecttakes an injected env lookup for tests; regression tests anddocs/testing/poetry-compatibility.mdagent-mode notes are updated. Anything that already usesfind_local_venv_site_packages(hosted stale-install checks, VEX, etc.) inherits the fix.Reviewed by Cursor Bugbot for commit 0b4a2df. Configure here.
Generated by Claude Code