Normalize PWD for POSIX agent launches (#7110)

Keep the child process environment consistent with the cwd used to launch native POSIX coding agents. Some Node-based agents use PWD during project-root discovery, so inheriting a stale PWD can make them edit files in a parent or unrelated directory even when the wrapper process cwd is correct.

Only apply this normalization for native POSIX launches. WSL-launched Windows shims stay on the existing WSLENV bridge path so path translation behavior is unchanged.

Add regression coverage that launches an agent with a deliberately stale inherited PWD and asserts the child environment is normalized to os.getcwd().

Co-authored-by: Leo Borcherding <borchborchmail@gmail.com>
This commit is contained in:
Lee Jackson 2026-07-23 23:54:09 +01:00 committed by GitHub
commit a26692612d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 26 additions and 0 deletions

View file

@ -2110,6 +2110,11 @@ def _launch(
for name in unset_env:
child_env.pop(name, None)
child_env.update(env)
if os.name != "nt" and not wsl_env_bridge:
# Keep POSIX child processes from seeing a stale inherited PWD when
# subprocess cwd was changed by the caller. Some Node CLIs use PWD for
# project-root discovery instead of process.cwd().
child_env["PWD"] = os.getcwd()
# Ctrl+C cancels a turn inside the agent; don't let it kill this wrapper.
previous = signal.signal(signal.SIGINT, signal.SIG_IGN)
try:

View file

@ -874,6 +874,27 @@ def test_connect_claude_compact_window_omitted_without_context(fake_studio, monk
assert "CLAUDE_AUTOCOMPACT_PCT_OVERRIDE" not in result.output
def test_launch_native_posix_child_gets_current_pwd(fake_studio, monkeypatch, tmp_path):
captured = {}
monkeypatch.chdir(tmp_path)
monkeypatch.setenv("PWD", "/stale/outer/repo")
monkeypatch.setattr(start.shutil, "which", lambda _: "/usr/local/bin/opencode")
def run(command, env):
captured["command"] = command
captured["env"] = env
return SimpleNamespace(returncode = 0)
monkeypatch.setattr(start.subprocess, "run", run)
result = CliRunner().invoke(start.start_app, ["opencode"])
assert result.exit_code == 0, result.output
assert captured["command"][0] == "/usr/local/bin/opencode"
if os.name != "nt":
assert captured["env"]["PWD"] == os.getcwd()
def test_connect_claude_launch_scrubs_conflicting_auth_env(fake_studio, monkeypatch):
captured = {}
monkeypatch.setenv("ANTHROPIC_API_KEY", "sk-anthropic-stale")