[bug] agent image: stop baking VIRTUAL_ENV=/app/.venv (silences uv run warning)

The agent-base image baked VIRTUAL_ENV=/app/.venv globally (since 8e201901,
conventional venv-baking, no targeted rationale), so every bare uv run in a
workspace clone warned 'VIRTUAL_ENV=/app/.venv does not match project .venv
and will be ignored' on every gate run. uv used the workspace .venv correctly
(the warning was noise), but it flooded every agent transcript.

The load-bearing MCP/SDK pin is UV_PROJECT_ENVIRONMENT=/app/.venv + --no-sync
(added in #179, the actual startup-stall fix), NOT VIRTUAL_ENV — so removing
VIRTUAL_ENV does not regress #179. The gateway tools stay on PATH.

Verified by building the image (roboco-agent-base:venv-verify) and smoke-
testing in a real container: (1) VIRTUAL_ENV is empty, python resolves to
/app/.venv/bin/python via PATH; (2) bare uv run from /app imports a roboco
module with no warning; (3) the MCP-launch path — cwd with its OWN .venv —
UV_PROJECT_ENVIRONMENT=/app/.venv uv run --no-sync resolves to /app/.venv/
bin/python, overriding the cwd .venv (the exact MCP-server invariant), no
warning; (4) grep for 'does not match|will be ignored' across all output is
empty. bash-guard-tests.sh 64/0, ruff clean, test_workspace_uv_resolves_clone_venv 3/3.

Ships on next agent-image rebuild + redeploy.
This commit is contained in:
Renn F
2026-06-30 09:58:36 +02:00
parent 0051339915
commit 7be10057d0
4 changed files with 14 additions and 12 deletions
+5 -6
View File
@@ -338,15 +338,14 @@ if echo "$low" | grep -qE '(^|[[:space:];&|])(uv[[:space:]]+(sync|lock|add|remov
exit 2
fi
# `uv run` retargeting onto /app/.venv — same brick as the package-mutation
# block above, via a verb that block doesn't list. In the agent container
# VIRTUAL_ENV=/app/.venv is baked globally, so `uv run --active` ALWAYS
# resolves onto /app/.venv and uv rebuilds it (be-dev-1 root cause,
# 2026-06-29). Also catch `uv run`/`uvx` with an explicit /app target.
# `uv run --active` is denied as a footgun: the contract is bare `uv run`
# (workspace .venv, cwd-relative). VIRTUAL_ENV is no longer image-baked (it
# leaked into every workspace `uv run` as a warning), so --active has no active
# env and errors; an explicit /app target still bricks the gateway (next block).
# Bare `uv run` (workspace .venv, cwd-relative) is untouched.
if echo "$low" | grep -qE '(^|[[:space:];&|])uv[[:space:]]+run([[:space:]]|$)' && \
echo "$low" | grep -qE '(^|[[:space:]=])--active([[:space:]]|$)'; then
echo "Denied: \`uv run --active\` retargets onto VIRTUAL_ENV=/app/.venv (the image-baked MCP-gateway venv) and rebuilds it, bricking your own gateway tools. Use bare \`uv run\` (it uses your workspace .venv under /data/workspaces, never /app). If /app's environment looks broken, report it via your blocked / escalation verb." >&2
echo "Denied: \`uv run --active\` is not the contract — use bare \`uv run\` (it uses your workspace .venv under /data/workspaces, never /app). If /app's environment looks broken, report it via your blocked / escalation verb." >&2
exit 2
fi
if echo "$low" | grep -qE '(^|[[:space:];&|])(uv[[:space:]]+run|uvx)([[:space:]]|$)' && \