Conversation
2c411f1 to
ad7bce7
Compare
In a multiplexed gateway, startup bridges only the primary profile's terminal.cwd to process-global TERMINAL_CWD. Sessions routed to a secondary profile resolved their cwd from that process-global latch, so the runtime footer, @-reference preprocessing, and the terminal tool all used the wrong profile's workspace — and whichever profile made the first terminal call after a restart stamped its workspace process-wide for every lane. - gateway/run.py: _set_session_env() resolves the routed profile's terminal.cwd and binds it through the session ContextVar; the runtime footer and @-reference preprocessor read the session-cwd override instead of os.environ["TERMINAL_CWD"]; _resolve_profile_home_for_source() falls back to the gateway process's own home rather than get_active_profile_name(), which can leak a previously routed turn's profile scope through copy_context() - agent/runtime_cwd.py: expose get_session_cwd_override() - tools/terminal_tool.py: seed the per-session cwd from the ContextVar override instead of the process-global TERMINAL_CWD latch - tests: multiplex profile cwd isolation, footer and @-reference coverage, unrouted-source home resolution under an inherited profile scope, and profile-resolution fallback tests repointed at the new gateway-home seam Builds on NousResearch#70600 and addresses its review gaps (@-reference preprocessor and runtime footer now honor the session-cwd override). Co-authored-by: ExitMaster <292490062+ExitMaster@users.noreply.github.com>
ad7bce7 to
bafeb3d
Compare
|
Thanks for this PR. Merged via #101242 (4a7f228) on current main — routed multiplex profiles get their own terminal cwd/backend/docker config; container boot honors config multiplex_profiles. #101242 won as the consolidated fix because it covers the whole multiplex-profile bug class in one change (with tests) rather than the single symptom addressed here; this PR is superseded by it. If anything from your original change is still missing on main >= 4a7f228, please open a fresh PR/issue against main and tag it. Thanks again. |
|
Production evidence for this bug class, from a deployment that ran The bug as it presented: every Matrix session bound to a non-launch profile resolved its workspace from the launch profile's One semantic point the PRs in this class differ on: the cwd source must be the session profile's own Our carry, rebased onto v0.21.0's Honest limitation of the minimal variant: it does not cover the direct |
What does this PR do?
In a multiplexed gateway (
multiplex_profiles: true), startup bridges only the primary profile'sterminal.cwdto the process-globalTERMINAL_CWDenv var. Sessions routed to a secondary profile resolved their cwd from that process-global latch, so:@file:/@folder:reference preprocessing resolved against the wrong profile's workspace,This PR binds the routed profile's cwd through the existing session ContextVar and routes every consumer through it, making cwd resolution deterministic per profile. It builds on #70600 and addresses the gaps raised in its review (the
@-reference preprocessor and the runtime footer still reados.environ["TERMINAL_CWD"]directly), plus two further defects found while verifying the fix in production:_prepare_profile_scoped_inbound_message_textran after_set_session_env()and its pin/clear wiped the ContextVar, so the footer fell back to process-globalTERMINAL_CWD._resolve_profile_home_for_source()fell back toget_active_profile_name(), which honors the context-local profile override. Messaging tasks spawn withcopy_context(), so an unrouted/default-lane turn could inherit a previously routed profile's scope and resolve to the wrong profile home. It now falls back to the gateway process's own home.Single-profile gateways are deliberately unchanged:
_session_cwd_for_source()returns an empty override whenmultiplex_profilesis off, preserving existing process-level cwd behavior.Related Issue
Builds on / supersedes #70600 (review feedback addressed; happy for that branch to be pulled in here or vice versa — whichever is easier for maintainers).
Type of Change
Changes Made
gateway/run.py_set_session_env()resolves the routed profile'sterminal.cwdvia new_session_cwd_for_source()and binds it through the session ContextVar (set_session_vars(cwd=...))get_session_cwd_override()before falling back toTERMINAL_CWD@-reference preprocessor resolves its cwd from the session override first_resolve_profile_home_for_source()falls back to the gateway process home instead ofget_active_profile_name()(context-scope leak viacopy_context())agent/runtime_cwd.py— exposeget_session_cwd_override()tools/terminal_tool.py— seed the per-session cwd from the ContextVar override instead of the process-globalTERMINAL_CWDlatchtests/gateway/test_multiplex_profile_cwd.py— 8 regression tests: per-profile cwd isolation, footer,@-reference resolution, terminal-tool seedingtests/gateway/test_multiplex_credential_isolation.py— regression test: unrouted source resolves to the gateway home even under an inherited profile scopeHow to Test
terminal.cwdvalues, and aprofile_routesentry routing one chat/topic to the secondary profile.terminalcalls must start in that cwd.python -m pytest tests/gateway/test_multiplex_profile_cwd.py tests/gateway/test_multiplex_credential_isolation.py -q→ 13 passed.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests pass — fullscripts/run_tests.shrun: only pre-existing failures on cleanmain(unrelated to cwd), no new failures from this changeDocumentation & Housekeeping
docs/, docstrings) — or N/A (docstrings only)cli-config.yaml.exampleif I added/changed config keys — N/A (no config changes)CONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — N/Apathlibthroughout, no signal/process-group calls;scripts/check-windows-footguns.pycleanScreenshots / Logs
Production footer after fix — routed secondary profile session shows its own workspace instead of the primary profile's: