Skip to content

phase 11 — detect_python_version v2 (venv-aware) #34

Description

@ayhammouda

Type: Enhancement of an existing MCP tool (detect_python_version). Backlog (post-v0.1.5).
Brought up to the AGENT-EXECUTION-PIPELINE.md §3 agent-ready standard.

Context

  • Per-issue context file (read first): .planning/agent-context/detect-python-version-v2-venv-aware.md
  • Pipeline: AGENT-EXECUTION-PIPELINE.md
  • v1 implementation: src/mcp_server_python_docs/detection.py — detect_python_version() 3-step chain (.python-version → python3 --version → sys.version_info).
  • Existing tests: tests/test_detection.py already exists (125 lines) and covers the three v1 sources. Extend it; do not recreate it.
  • Tool wrapper: src/mcp_server_python_docs/server.py:372; result model: src/mcp_server_python_docs/models.py:147 (DetectPythonVersionResult).

Goal

Make detect_python_version report the Python version of the active virtual environment in the user's project, while preserving the v1 fallback chain and the existing MCP wire contract verbatim.

Acceptance criteria

  • DETV2-01: When VIRTUAL_ENV is set, detection.py reads <VIRTUAL_ENV>/pyvenv.cfg, parses the version = X.Y[.Z] key (falling back to version_info if version is absent), and returns source "venv:VIRTUAL_ENV".
  • DETV2-02: With no VIRTUAL_ENV, a .venv/ or venv/ directory found in cwd or an ancestor (bounded at filesystem/project root) is read via its pyvenv.cfg and returns source "venv:.venv".
  • DETV2-03: uv's and poetry's project-root .venv are covered by the generic DETV2-02 check (no tool-specific branching).
  • DETV2-04: The v1 fallback chain is preserved unchanged and below the new venv checks. Final order: VIRTUAL_ENV → .venv/venv dir → .python-version → python3 PATH → server runtime.
  • DETV2-05: detect_python_version() still returns a (major_minor, source) tuple. Five distinct source strings exist: the two new "venv:VIRTUAL_ENV", "venv:.venv" plus the three preserved-verbatim v1 strings ".python-version file", "python3 in PATH", "server runtime".
  • The source Field(description=...) in models.py (DetectPythonVersionResult, line ~147) is updated to enumerate all five sources, so the published tool schema does not lie. (Type stays str; description-only edit.)
  • tests/test_detection.py is extended (not replaced): new tests cover venv:VIRTUAL_ENV and venv:.venv (incl. a Windows-layout pyvenv.cfg path), AND the existing v1 tests are hardened with monkeypatch.delenv("VIRTUAL_ENV", raising=False) so they stay deterministic now that VIRTUAL_ENV is checked first. All five source strings are covered.
  • uv run pytest tests/test_detection.py -q passes.

Success criteria (illustrative)

  1. Inside an activated venv (3.12) on a 3.13 host → ("3.12", "venv:VIRTUAL_ENV").
  2. No venv but .python-version present → ("X.Y", ".python-version file") (v1 preserved verbatim).
  3. Nothing else available → (sys-version, "server runtime") (v1 fallback preserved verbatim).

Scope boundaries

In scope: the venv-detection logic in src/mcp_server_python_docs/detection.py, the source description string in models.py, and extending tests/test_detection.py.

Out of scope (stop and comment):

  • conda / mamba environments (separate phase if demand surfaces).
  • Cross-platform path quirks beyond Unix + Windows.
  • Changing the detect_python_version MCP wrapper signature or the (major_minor, source) return shape.
  • Renaming or altering any of the three v1 source strings.

Forbidden-territory reminders (pipeline §2)

  • Tool name / parameter / return shape — the server.py:372 wrapper signature and the tuple/model shape must not change. Only the set of possible source values grows, plus its description text.
  • Existing tests — extend and harden, never delete or weaken. (Adding delenv to keep a test deterministic is hardening, and is required here.)
  • No schema, no workflow, no pyproject.toml edits.

Validation commands (pipeline §5)

uv run ruff check src/ tests/
uv run pyright src/
uv run pytest --tb=short -q
uv run python-docs-mcp-server doctor
# detect_python_version backs an MCP tool — also run the wire smoke:
uv run pytest tests/test_stdio_smoke.py -q

PR template & recovery (pipeline §6, §8)

  • Use .github/PULL_REQUEST_TEMPLATE/agent.md; PR title matches this issue verbatim.
  • This extends an existing tool's behavior (new source values) without changing its wire shape — under "Why this triggered human review", state "None" unless you find you must touch the wrapper signature, in which case stop and comment (§8).
  • Ambiguity about detection order or pyvenv.cfg variants? Stop, write WORKING-NOTES.md, comment per §8 — do not invent.

Effort estimate

~2–3 hours.

Activity

  1. added
    enhancementNew feature or request
    help wantedExtra attention is needed
    phase-planBacklog phase with on-disk CONTEXT skeleton; ready for /gsd-plan-phase
    on May 14, 2026
  2. ayhammouda commented on Oct 1, 2026

    @ayhammouda
    OwnerAuthor

    Vision — automated project maintainer: I am pausing this v2 spec pending a client-context check, not rejecting the version-accuracy goal. detection.py reads the MCP server process environment and cwd; its VIRTUAL_ENV and .venv may belong to uvx/the client launch context rather than the user project. The current tool has no project-path input, and server.py also combines a startup-cached matched version with a fresh raw detection result. Therefore DETV2-01/02 could confidently report the wrong project Python version in common MCP setups. Before implementation, reproduce cwd/env behavior in the documented Claude/Cursor/Codex integration flows, then revise acceptance criteria around an observable project context or explicitly label this as server-environment detection. Do not dispatch the current spec as agent-ready.

  3. added
    supervisor-reviewVision supervisor decision required before further automation
    on Oct 1, 2026
  4. ayhammouda commented on Oct 10, 2026

    @ayhammouda
    OwnerAuthor

    This was generated by AI during triage.

    Codex — automated triage assistant.

    Agent Brief — resolve detection context before implementation

    Category: enhancement
    Triage state: ready-for-human (Vision supervisor routing); retain supervisor-review.
    Summary: Establish an observable and truthful Python-detection context, then revise the venv-aware acceptance criteria. The existing implementation hold remains in force.

    Context and redundancy check: Reviewed the full issue and Vision's 2026-10-01 hold. Searched the detector, both server call sites, application context, result model, detection/retrieval tests, README, manual integration runbook and transport ADR. At main c97600ecc5430044e66500d04192bc61e7df71dc, detection still uses cwd .python-version, PATH python3, then server runtime. Neither VIRTUAL_ENV nor pyvenv.cfg is read, and the public tool has no project-path argument. The requested behavior is not already implemented. No matching prior rejection records were found in .out-of-scope/. ADR-008's subprocess/stdio model is consistent with inherited server context; it does not establish which user's project that context represents.

    Current behavior and fresh verification:

    • uv run --locked pytest tests/test_detection.py -q: 12 passed.
    • A controlled project fixture with VIRTUAL_ENV and .venv/pyvenv.cfg declaring 3.12, with the PATH probe controlled to report 3.13, returns ("3.13", "python3 in PATH").
    • With separate user-project and server-launch directories requesting 3.12 and 3.13 respectively, a detector invoked from the launch directory returns ("3.13", ".python-version file").
    • Calling the current registered wrapper with a startup-cached 3.12 match while fresh cwd detection reports 3.13 returns detected_version="3.13", matched_index_version="3.12", is_default=true. The model describes the matched version as the detected version's indexed match, so this combination needs an explicit consistency/freshness decision.

    These are controlled local probes of current code, not measurements from actual Claude Desktop, Cursor or Codex client sessions. No client configuration or product code was changed.

    Desired behavior: The reported version, source and indexed-match/default fields have documented, consistent meanings. A server runtime or launcher venv must not be presented as the user's project interpreter without an observable relationship to that project.

    Key interfaces: detect_python_version(), match_to_indexed(), startup detection in app_lifespan, AppContext.detected_python_version, and DetectPythonVersionResult.

    Acceptance criteria for Vision's decision:

    • Reproduce the documented client launches and record only the relevant cwd, interpreter/PATH and venv observations; avoid credential/environment dumps.
    • Record how project context is observed and bounded, or explicitly scope the feature to server-environment detection. Do not invent an API/project-path extension inside the current issue's forbidden scope.
    • Define how fresh detection, cached default and indexed matching remain coherent when a version file or environment changes during a session; turn the contradictory controlled result into a deterministic acceptance case.
    • Rewrite precedence and error/fallback cases for the chosen context, including unreadable/malformed venv metadata, unrelated launcher venvs, ancestor boundaries and Windows layout. Preserve existing source strings and wire shape unless Vision explicitly authorizes a compatible scope revision.
    • Only after that decision, provide an agent-targetable implementation brief and pipeline preflight. Require focused detection/stdio tests and the locked canonical gate for the resulting change.

    Why supervisor routing: The blocker is an unresolved product/context contract already identified by Vision, not unanswered reporter reproduction steps. Existing test success does not settle that contract. The original VIRTUAL_ENV → .venv → ... spec is not ready for unattended implementation.

    Out of scope: Implementing the paused spec now, silently changing tool inputs or return shape, conda/mamba support, unrelated transport changes, a new MCP server, or claiming actual-client acceptance from these local fixtures.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthelp wantedExtra attention is neededphase-planBacklog phase with on-disk CONTEXT skeleton; ready for /gsd-plan-phaseready-for-humanRequires a Vision supervisor decisionsupervisor-reviewVision supervisor decision required before further automation

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions