Redundant temp-file read in LocalEnvironment._update_cwd

NousResearch/hermes-agent · cluster 63225

Data as of

Nothing open on GitHub. Fix merged in #65483. Check it covers your case.

The short answer

0open issues
0open PRs
8items grouped
Known?
Yes. 8 related items grouped here, 1 issue already closed.
Fix event
A fix was merged to main in PR #65483. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this resolved, deciding PR #65483. That is separate from the fix event.
Still open
Nothing open on GitHub.

A bug report and multiple fix attempts addressing unnecessary file I/O in LocalEnvironment._update_cwd(), which was writing and then immediately re-reading a temp file on every terminal() call. Several approaches are represented, including removing the read, parsing cwd from stdout, and dropping the temp-file write entirely.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #65483 fix(local): parse cwd from the stdout marker, drop the temp-file write

    merged to main

    files: tests/tools/test_base_environment.py, tests/tools/test_local_env_cwd_recovery.py, tests/tools/test_local_env_windows_msys.py, tools/environments/base.py, tools/environments/local.py

    Show the diff
    • tests/tools/test_base_environment.py
      @@ -68,7 +68,8 @@ def test_basic_shape(self):
               assert "eval 'echo hello'" in wrapped
               assert "__hermes_ec=$?" in wrapped
               assert "export -p >" in wrapped
      -        assert "pwd -P >" in wrapped
      +        # cwd travels via the stdout marker only — no temp-file write.
      +        assert "pwd -P >" not in wrapped
               assert env._cwd_marker in wrapped
               assert "exit $__hermes_ec" in wrapped
       
      @@ -357,7 +358,9 @@ def cleanup(self):
       
                   assert stat.S_IMODE(user_file.stat().st_mode) == 0o644
                   assert stat.S_IMODE(Path(env._snapshot_path).stat().st_mode) == 0o600
      -            assert stat.S_IMODE(Path(env._cwd_file).stat().st_mode) == 0o600
      +            # The cwd temp file is no longer written (cwd travels via the
      +            # stdout marker for every backend) — nothing to leak on disk.
      +            assert not Path(env._cwd_file).exists()
               finally:
                   os.umask(old_umask)
       
    • tests/tools/test_local_env_cwd_recovery.py
      @@ -160,13 +160,14 @@ def test_skips_assignment_when_marker_path_missing(self, tmp_path):
               with patch.object(LocalEnvironment, "init_session", autospec=True, return_value=None):
                   env = LocalEnvironment(cwd=str(original), timeout=10)
       
      -        # Simulate the stale-marker case: the prior command's ``pwd -P`` left
      -        # a path in the cwd file, but that path has since been deleted.
      +        # Simulate the stale-marker case: the prior command emitted a cwd
      +        # marker for a directory that has since been deleted.
               deleted = tmp_path / "wedge-repro"
      -        with open(env._cwd_file, "w") as f:
      -            f.write(str(deleted))
      +        marker = env._cwd_marker
       
      -        env._update_cwd({"output": "", "returncode": 0})
      +        env._update_cwd(
      +            {"output": f"x\n{marker}{deleted}{marker}\n", "returncode": 0}
      +        )
       
               assert env.cwd == str(original)
       
      @@ -178,10 +179,10 @@ def test_accepts_assignment_when_marker_path_exists(self, tmp_path):
       
               with patch.object(LocalEnvironment, "init_session", autospec=True, return_value=None):
                   env = LocalEnvironment(cwd=str(original), timeout=10)
      +        marker = env._cwd_marker
       
      -        with open(env._cwd_file, "w") as f:
      -            f.write(str(new_dir))
      -
      -        env._update_cwd({"output": "", "returncode": 0})
      +        env._update_cwd(
      +            {"output": f"x\n{marker}{new_dir}{marker}\n", "returncode": 0}
      +        )
       
               assert env.cwd == str(new_dir)
    • tests/tools/test_local_env_windows_msys.py
      @@ -180,15 +180,15 @@ def test_msys_path_resolves_to_native_when_native_exists(
       
       
       # ---------------------------------------------------------------------------
      -# End-to-end: _update_cwd via marker file (Windows simulation)
      +# End-to-end: _update_cwd via stdout marker (Windows simulation)
       # ---------------------------------------------------------------------------
       
       class TestUpdateCwdWindowsMsys:
      -    def test_marker_file_msys_path_stored_in_native_form(
      +    def test_marker_output_msys_path_stored_in_native_form(
               self, monkeypatch, tmp_path,
           ):
      -        """When Git Bash writes ``/c/Users/x`` to the cwd marker file on
      -        Windows, ``_update_cwd`` must translate to native form before
      +        """When Git Bash emits ``/c/Users/x`` in the cwd marker on Windows,
      +        ``_update_cwd`` must translate to native form before
               validating and storing — otherwise ``os.path.isdir`` rejects a
               perfectly real directory."""
               original = tmp_path / "starting"
      @@ -205,18 +205,21 @@ def test_marker_file_msys_path_stored_in_native_form(
               # Pretend Git Bash wrote an MSYS path that maps to tmp_path/"next"
               new_dir = tmp_path / "next"
               new_dir.mkdir()
      +        marker = env._cwd_marker
       
      -        with open(env._cwd_file, "w") as f:
      -            f.write("/c/whatever/from/bash")
      -
      -        # Translate the synthetic MSYS string to the real native dir.
      +        # Translate the synthetic MSYS marker path to the real native dir.
               def fake_translate(p):
                   if p == "/c/whatever/from/bash":
                       return str(new_dir)
                   return p
       
               with patch.object(local_mod, "_msys_to_windows_path", side_effect=fake_translate):
      -            env._update_cwd({"output": "", "returncode": 0})
      +            env._update_cwd(
      +                {
      +                    "output": f"x\n{marker}/c/whatever/from/bash{marker}\n",
      +                    "returncode": 0,
      +                }
      +            )
       
               assert env.cwd == str(new_dir)
       
    • tools/environments/base.py
      @@ -478,7 +478,6 @@ def init_session(self):
               # ``Directory \\drivers\\etc does not exist`` failure class.
               # On POSIX this is plain ``shlex.quote``.
               _quoted_snap = self._quote_shell_path(self._snapshot_path)
      -        _quoted_cwd_file = self._quote_shell_path(self._cwd_file)
               # Use atomic file replacement: assemble the snapshot in a temp file,
               # then mv it over the final path.  This prevents concurrent source()
               # calls from reading a half-written snapshot when another terminal
      @@ -523,7 +522,6 @@ def init_session(self):
                   # partial temp rather than leave it to be sourced or orphaned.
                   f"mv -f {_snap_tmp} {_quoted_snap} || rm -f {_snap_tmp}\n"
                   f"builtin cd -- {_quoted_cwd} 2>/dev/null || true\n"
      -            f"pwd -P > {_quoted_cwd_file} 2>/dev/null || true\n"
                   f"printf '\\n{self._cwd_marker}%s{self._cwd_marker}\\n' \"$(pwd -P)\"\n"
               )
               try:
      @@ -602,10 +600,9 @@ def _wrap_command(self, command: str, cwd: str) -> str:
               re-dumps env vars, and emits CWD markers."""
               escaped = command.replace("'", "'\\''")
       
      -        # Quote snapshot/cwd-file paths (see init_session — LocalEnvironment
      -        # rewrites ``C:/...`` to ``/c/...`` so MSYS doesn't mangle them).
      +        # Quote the snapshot path (see init_session — LocalEnvironment
      +        # rewrites ``C:/...`` to ``/c/...`` so MSYS doesn't mangle it).
               _quoted_snap = self._quote_shell_path(self._snapshot_path)
      -        _quoted_cwd_file = self._quote_shell_path(self._cwd_file)
               # Use atomic file replacement for env snapshot updates (issue #38249).
               # Assemble into a per-writer-unique temp file, then mv to atomically
               # replace the snapshot so concurrent source() calls never read a
      @@ -651,8 +648,8 @@ def _wrap_command(self, command: str, cwd: str) -> str:
                       f"2>/dev/null || rm -f {_snap_tmp} 2>/dev/null || true"
                   )
       
      -        # Write CWD to file (local reads this) and stdout marker (remote parses this)
      -        parts.append(f"pwd -P > {_quoted_cwd_file} 2>/dev/null || true")
      +        # Emit the CWD stdout marker; all backends (including local, since
      +        # PR #63255) parse it from output — no temp-file write needed.
               # Use a distinct line for the marker. The leading \n ensures
               # the marker starts on its own line even if the command doesn't
               # end with a newline (e.g. printf 'exact'). We'll strip this
    • tools/environments/local.py
      @@ -1314,31 +1314,14 @@ def _wait_for_group_exit(pgid: int, timeout: float) -> bool:
                       pass
       
           def _update_cwd(self, result: dict):
      -        """Read CWD from temp file (local-only, no round-trip needed).
      -
      -        Skip the assignment when the path no longer exists as a directory —
      -        ``pwd -P`` on a deleted cwd can leave a stale value in the marker
      -        file, and propagating it would re-wedge the next ``Popen``.  The
      -        ``_run_bash`` recovery path will resolve a safe fallback if needed.
      -
      -        On Windows, the value written by Git Bash's ``pwd -P`` is in
      -        MSYS form (``/c/Users/x``). Translate it to native Windows form
      -        before validating with ``os.path.isdir`` and before storing on
      -        ``self.cwd``; otherwise the isdir check rejects every valid
      -        result and ``_run_bash`` later prints a misleading "cwd is
      -        missing" warning on every command.
      -        """
      -        try:
      -            with open(self._cwd_file, encoding="utf-8") as f:
      -                cwd_path = f.read().strip()
      -            if _IS_WINDOWS:
      -                cwd_path = _msys_to_windows_path(cwd_path)
      -            if cwd_path and os.path.isdir(cwd_path):
      -                self.cwd = cwd_path
      -        except (OSError, FileNotFoundError):
      -            pass
      +        """Update cwd from the stdout marker emitted by the wrapped command.
       
      -        # Still strip the marker from output so it's not visible
      +        The base command wrapper already appends ``pwd -P`` to stdout inside a
      +        session-specific marker, so the local backend can share the same parser
      +        as remote backends instead of re-reading the temp file it just wrote.
      +        ``_extract_cwd_from_output`` keeps the local Windows normalization and
      +        stale-path rollback semantics intact.
      +        """
               self._extract_cwd_from_output(result)
       
           def _extract_cwd_from_output(self, result: dict):

6 PRs closed without merging

From the close comments: duplicate 3 · done elsewhere 1 · merged via another change 1 · other 1

  • #63255 fix(local): stop re-reading cwd marker file · merged via another change → 0ccd05b, #65483
  • #63445 fix(local): remove redundant temp-file read in _update_cwd · duplicate
  • #63615 fix(local): remove redundant temp-file read from `LocalEnvironment._update_cwd` · duplicate
  • #63947 fix(local-env): remove redundant temp-file read in _update_cwd (#63225) · duplicate
  • #64095 fix(local): remove redundant temp-file read from LocalEnvironment._update_cwd() · done elsewhere → #63255, #63225, #63445, #63615, #63947
Show 1 more
  • #64128 fix(local): remove redundant temp-file read in _update_cwd · other
Closed issues · 1
  • Closed#63225[Bug]: `LocalEnvironment._update_cwd()` reads back a temp file it just wrote — redundant file I/O on every `terminal()` call
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.25: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means 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 Lab

At a glance

Merged PRs
#65483
Closed issues
1
Attempts
6 PRs closed without merging
Fix link checked
16 Jul 2026

For your agent

The same facts, typed.