fix(agent): launch agent uv-run subprocesses with --no-sync

Agents with a write workspace (developer/product_owner/head_marketing/documenter)
run with cwd = their git workspace clone. Claude Code launches each MCP server
(flow/do/git-readonly/optimal/docs/search) and the SDK server as
`uv run python -m ...` from that cwd. When the clone's uv.lock drifts from the
baked image, `uv run` re-resolves and re-syncs /app/.venv against the clone's
lock — a multi-minute stall on a cold wheel cache — so the servers never reach
"connected": they sit at status="pending" and the agent gets ZERO gateway
verbs. It then can't claim/commit/idle (all MCP verbs), its Stop is rejected,
and it respawns in a loop redoing work it can't submit.

UV_PROJECT_ENVIRONMENT pins the venv location but does NOT stop the cwd-relative
resolve/sync (confirmed empirically on uv 0.11.1); `--no-sync` does, so the
servers reuse the baked /app/.venv as-is and start instantly. The /app-cwd roles
(qa/cell_pm/main_pm/auditor) were unaffected because their env already matches.

- orchestrator.py: --no-sync on all 6 generated MCP servers
- docker/scripts/sdk-startup-hook.sh: --no-sync on the agent_sdk.server launch
- test_spawn_strict_mcp.py: assert every server's args start with run,--no-sync
This commit is contained in:
Renn F
2026-06-15 22:43:05 +02:00
parent f443a60d29
commit 25aed51c04
3 changed files with 29 additions and 9 deletions
@@ -92,3 +92,13 @@ class TestMcpConfigPinsBakedVenv:
f"/app/.venv — without it `uv run` re-downloads deps into a "
f"cwd-relative venv on every spawn (#179). env={spec['env']}"
)
# Pinning the env location is necessary but NOT sufficient: from a
# workspace-clone cwd `uv run` still discovers the clone project and
# re-syncs the pinned venv against its drifted lock, which stalls and
# leaves the server stuck at status="pending" (zero gateway verbs).
# `--no-sync` skips that resync — it must come right after `run`.
assert spec["args"][:2] == ["run", "--no-sync"], (
f"MCP server {name!r} must launch with `uv run --no-sync ...` so "
f"a drifted workspace-clone lock can't trigger a resync stall; "
f"got args={spec['args']}"
)