hermes-agent/tools/environments
ethernet 16a173a8d6 fix(tools): do not adopt a stale cwd after an interrupted command
The command wrapper prints the cwd marker after the command returns. A
killed or timed-out command emits no marker, so ``env.cwd`` still holds the
directory of the last command to FINISH. One local environment serves every
session, because ``_resolve_container_task_id`` collapses cwd-only overrides
to ``"default"``. That leftover directory is therefore routinely another
session's.

The post-command dual-write copied ``env.cwd`` into the interrupted session's
durable record. Every later command in that session then ran in the foreign
directory, and the cwd echo told the model it had moved there. A desktop chat
silently re-homed into a worktree that another chat had opened.

Report the observation instead of inferring it. The marker parse now sets
``result["cwd_observed"]``, and both the record write and the echo read that
flag. The local override clears the flag when it rolls back a path that does
not exist, because the restored value is also unobserved. When a command
reports no cwd, the session keeps the directory it already had.

This needs no second session to be wrong: a lone session that interrupts a
command re-adopts a stale value too. A second session only makes the wrong
directory belong to somebody else.

The same class of write exists in the file-tools rescue for a reaped
environment (#26211). That rescue copied the cached snapshot of the shared
``env.cwd`` into the session record. The rescue is now fill-only: it writes
the snapshot when the session has no record, and it never overwrites a
record that the session wrote for itself.

The tests drive ``terminal_tool`` itself through an interrupt, not a copy of
its gate. Review found that a revert of either call site passed the first
version of the tests. Each gate now has a test that fails when the gate is
removed (verified by mutation).

Two exact-dict assertions in the Vercel sandbox tests now assert the two
fields they care about, so a new result key does not fail them.
2026-08-13 20:30:26 -07:00
..
__init__.py Revert "remove Vercel AI Gateway and Vercel Sandbox (#33067)" 2026-07-29 19:48:37 -07:00
base.py fix(tools): do not adopt a stale cwd after an interrupted command 2026-08-13 20:30:26 -07:00
daytona.py fix(daytona): quote single-upload mkdir parent path (#54440) 2026-06-28 14:33:03 -07:00
docker.py fix(docker): per-session container isolation and session-scoped workspace mounts 2026-08-09 14:35:02 -07:00
file_sync.py fix(file-sync): serialize concurrent sync cycles 2026-08-03 22:53:32 +05:30
local.py fix(tools): do not adopt a stale cwd after an interrupted command 2026-08-13 20:30:26 -07:00
managed_modal.py
…
modal.py fix(async): close unscheduled coroutines in all threadsafe bridges (#26584) 2026-05-15 14:00:01 -07:00
modal_utils.py fix(terminal): make bounded capture opt-in for the foreground terminal path only 2026-07-14 22:00:28 -07:00
singularity.py refactor: single build_subprocess_env() factory for all child-process spawns (profile + secret-scrub single owner) 2026-07-29 10:14:11 -07:00
ssh.py fix(windows): SSH ControlMaster gating + stop hijacking the user's python (#84452) 2026-08-12 02:56:33 -07:00
vercel_sandbox.py modernize re-added Vercel integrations: SDK 0.7.2, telemetry off, sibling-site wiring 2026-07-29 19:48:37 -07:00