Working directory handling fixes across session types
Cluster 38775 · acp. Data as of
Nothing open on GitHub. Fix merged in #50451 on 21 Jun 2026. Check it covers your case.
The short answer
- Known?
- Yes. 3 related items grouped here, 1 issue already closed.
- Fix event
- A fix was merged to main in PR #50451. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
resolved, deciding PR #50451. That is separate from the fix event. - Still open
- Nothing open on GitHub.
A bug and several fixes addressing how the configured or current working directory is tracked and applied across app-server sessions, terminal sessions, and desktop workspaces. Changes include per-session cwd records, seeding sessions with the correct cwd, and ensuring configured directories take precedence over stale remembered values.
Open issues0
Open PRs0
Fixes on record
-
#50451 fix(codex): seed app-server sessions with configured cwd
files:
acp_adapter/session.py,agent/codex_runtime.py,tests/acp/test_session.py,tests/run_agent/test_codex_app_server_integration.pyShow the diff
-
acp_adapter/session.py@@ -617,6 +617,10 @@ def _make_agent( _register_task_cwd(session_id, cwd) agent = AIAgent(**kwargs) + # Codex app-server sessions are spawned lazily on the first turn. Stamp + # the ACP workspace onto the agent so the Codex runtime starts from the + # editor/session cwd instead of the Hermes daemon's process cwd. + agent.session_cwd = cwd # ACP stdio transport requires stdout to remain protocol-only JSON-RPC. # Route any incidental human-readable agent output to stderr instead. agent._print_fn = _acp_stderr_print -
agent/codex_runtime.py@@ -250,7 +250,9 @@ def run_codex_app_server_turn( # Spawned on first turn, reused across turns, closed at AIAgent # shutdown (see _cleanup hook). if not hasattr(agent, "_codex_session") or agent._codex_session is None: - cwd = getattr(agent, "session_cwd", None) or os.getcwd() + from agent.runtime_cwd import resolve_agent_cwd + + cwd = getattr(agent, "session_cwd", None) or str(resolve_agent_cwd()) # Approval callback: defer to Hermes' standard prompt flow if a # CLI thread has installed one. Gateway / cron contexts get the # codex-side fail-closed default. -
tests/acp/test_session.py@@ -77,6 +77,50 @@ def test_get_session(self, manager): def test_get_nonexistent_session_returns_none(self, manager): assert manager.get_session("does-not-exist") is None + def test_make_agent_stamps_session_cwd_for_codex_runtime(self, monkeypatch): + class FakeAgent: + model = "fake-model" + + def __init__(self, **kwargs): + self.kwargs = kwargs + + monkeypatch.setattr("run_agent.AIAgent", FakeAgent) + monkeypatch.setattr( + "acp_adapter.session.load_config", + lambda: { + "model": { + "default": "fake-model", + "provider": "fake-provider", + }, + "mcp_servers": {}, + }, + raising=False, + ) + monkeypatch.setattr( + "hermes_cli.config.load_config", + lambda: { + "model": { + "default": "fake-model", + "provider": "fake-provider", + }, + "mcp_servers": {}, + }, + ) + monkeypatch.setattr( + "hermes_cli.runtime_provider.resolve_runtime_provider", + lambda requested=None: { + "provider": requested, + "api_mode": "codex_app_server", + "base_url": "https://example.invalid", + "api_key": "[redacted:secret-assignment]", + }, + ) + monkeypatch.setattr("acp_adapter.session._register_task_cwd", lambda task_id, cwd: None) + + state = SessionManager(db=None).create_session(cwd="/tmp/project") + + assert state.agent.session_cwd == "/tmp/project" + -
tests/run_agent/test_codex_app_server_integration.py@@ -293,6 +293,39 @@ def test_chat_completions_loop_is_not_entered(self, fake_session): agent.run_conversation("hi") assert not client_mock.chat.completions.create.called + def test_gateway_terminal_cwd_seeds_codex_thread_cwd(self, monkeypatch, tmp_path): + """Gateway sessions set TERMINAL_CWD without stamping agent.session_cwd. + Codex app-server must still start in that configured workspace instead + of falling back to the Hermes daemon process cwd.""" + from agent.transports.codex_app_server_session import ( + CodexAppServerSession, TurnResult, + ) + + captured: dict[str, str] = {} + + def fake_init(self, **kwargs): + captured["cwd"] = kwargs["cwd"] + self._thread_id = "thread-stub-1" + + def fake_run_turn(self, user_input: str, **kwargs): + return TurnResult( + final_text="ok", + projected_messages=[{"role": "assistant", "content": "ok"}], + turn_id="turn-stub-1", + thread_id="thread-stub-1", + ) + + monkeypatch.setenv("TERMINAL_CWD", str(tmp_path)) + monkeypatch.setattr(CodexAppServerSession, "__init__", fake_init) + monkeypatch.setattr(CodexAppServerSession, "run_turn", fake_run_turn) + + agent = _make_codex_agent() + assert not hasattr(agent, "session_cwd") + with patch.object(agent, "_spawn_background_review", return_value=None): + agent.run_conversation("hi") + + assert captured["cwd"] == str(tmp_path) + class TestReviewForkApiModeDowngrade: """When the parent agent runs on codex_app_server, the background
-
1 PR closed without merging
From the close comments: merged via another change 1
-
#38778 fix(codex): seed app-server sessions with configured cwd · merged via another change →
c11ae82,#50451
Closed issues · 1
- Closed#38775[Bug]: Codex app-server sessions ignore configured/session cwd and start sandbox in Hermes home
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.67: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Subsystem
- acp
- Merged PRs
- #50451
- Closed issues
- 1
- Attempts
- 1 PR closed without merging
- Fix link checked
- 21 Jun 2026