You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 6138122
Browse filesBrowse the repository at this point in the historyBrowse files
Respect terminal cwd when resolving local venvs (#1708)
## Summary
- resolve terminal environments from the terminal cwd before using
workspace-wide fallbacks
- reject a selected local venv when it belongs to a sibling directory,
then use one nearest, unambiguous venv that contains the cwd
- fail closed instead of activating another project's environment when
the cwd project has no safe match
- keep terminal activation menu context synchronized with the currently
active terminal
Fixes#1631
## Context
The issue uses a single VS Code workspace folder as a container for
several independent Python projects:
```text
AILab/
ProjectA/.venv
ProjectB/.venv
ProjectC/.venv
```
With the default `workspaceSearchPaths` (`[".venv", "*/.venv"]`), all
three environments are discovered. However, the workspace root is
automatically registered as the only Python project unless the nested
projects are explicitly added. A terminal opened in ProjectC could
therefore receive ProjectA's activation command.
Besides activating the wrong dependencies and Python version, this
affects every integrated terminal opened by other extensions because
auto-activation runs on the terminal-open event.
## Root cause
The failure was caused by two scope-collapsing decisions:
1. Nested environment paths resolve to the automatically registered
workspace-root project through ancestor project lookup. `VenvManager`
can therefore associate one sorted or persisted sibling venv with that
root.
2. `getEnvironmentForTerminal()` previously preferred project-wide
environment consensus before checking terminal cwd. With exactly one
registered project, it returned the root's selected environment
immediately, so the cwd heuristic never ran.
Simply moving the existing cwd lookup earlier is insufficient:
`api.getEnvironment(ProjectC)` still maps ProjectC back to the root
project and returns the same sibling environment.
## Fix
### Cwd-aware terminal resolution
The terminal resolver now:
1. reads shell-integration cwd first, then terminal creation cwd
2. finds the most-specific registered project containing that cwd
3. preserves the project's selected environment unless it is a built-in
venv located on a divergent sibling branch
4. for a sibling venv only, searches already-known environments for
candidates that:
- belong to the built-in venv manager
- are valid and have an absolute `sysPrefix`
- live inside the containing project
- have an owner directory that is an ancestor of the terminal cwd
5. selects exactly one nearest candidate
If no candidate exists, multiple candidates are equally near, lookup
fails, or lookup exceeds one second, the resolver returns no environment
rather than activating the wrong one. The losing timeout is cancelled
after a successful lookup.
A known cwd project with no selected environment also stops resolution,
preventing another project's sole environment from leaking through the
previous multi-project fallback.
### Compatibility boundaries
This is intentionally terminal-only. It does not change central
environment selection, persisted manager state, debugger/Pylance
resolution, status-bar selection, task execution, or the public
environment API.
| Scenario | Behavior |
| --- | --- |
| `workspace/.venv` with a terminal in `workspace/src` | Existing root
venv remains selected |
| Registered nested project with an explicit environment | Existing
project environment remains selected |
| Conda/Poetry/Pyenv or another external environment | Existing selected
environment remains selected |
| Terminal cwd outside all registered projects | Existing fallback
behavior remains |
| Terminal cwd unavailable | Existing fallback behavior remains |
| Selected venv is under ProjectA and cwd is under ProjectC | Use
ProjectC's unique nearest venv, or activate nothing |
| Cwd project has no selected environment | Activate nothing; do not
borrow another project's environment |
### Terminal activation UI
Safe resolution can intentionally return `undefined`. The activation
menu contexts are now cleared in that case instead of retaining the
previous terminal's Activate/Deactivate state. Async context updates
also verify that the originating terminal is still active, preventing
slower lookups or background activation events from overwriting the
currently focused terminal's global menu state.
## Tests
Added direct coverage for:
- normal workspace-root venvs and nested cwd paths
- sibling ProjectA/ProjectB/ProjectC venv resolution
- shell-integration cwd precedence
- ambiguous equally near venvs
- missing local venvs
- global venv exclusion
- workspace-root terminals with a selected descendant venv
- projects with no selected environment
- preventing another project's environment from leaking into the cwd
project
- environment-list rejection and timeout
- external environments, explicit nested projects, outside-workspace
cwd, and unavailable cwd
- clearing activation menu contexts when no environment resolves
Validation performed:
- `npm run compile-tests`
- `npm run compile`
- ESLint on all changed TypeScript files
- all 97 tracked unit-test files: **1,525 passing, 5 expected pending**
## Out of scope
The shell-execution timeout also reported in #1631 is a separate
activation-state issue. This PR addresses only selecting the correct
environment for a terminal cwd.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2f537bc5-b389-4ee2-aac2-e2b83be47f5c
0 commit comments