From 8030c3697019b32dd0fc2b232cea0c2c2574fe9d Mon Sep 17 00:00:00 2001 From: jif Date: Wed, 3 Jun 2026 18:36:10 +0200 Subject: [PATCH] feat: guard git enrichment (#26175) Skip turn git metadata enrichment when a turn has remote or multiple executors, so we do not report the orchestrator checkout as executor workspace metadata. Test: `just test -p codex-core` (blocked by existing `Session::conversation_id` compile error in `close_agent.rs`). --- codex-rs/core/src/environment_selection.rs | 59 ++++++++++++++++++++++ codex-rs/core/src/session/review.rs | 4 +- codex-rs/core/src/session/turn_context.rs | 8 ++- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/codex-rs/core/src/environment_selection.rs b/codex-rs/core/src/environment_selection.rs index 749212f70..479132925 100644 --- a/codex-rs/core/src/environment_selection.rs +++ b/codex-rs/core/src/environment_selection.rs @@ -50,6 +50,14 @@ impl ResolvedTurnEnvironments { self.primary() .map(|environment| environment.environment.get_filesystem()) } + + pub(crate) fn single_local_environment_cwd(&self) -> Option<&AbsolutePathBuf> { + let [environment] = self.turn_environments.as_slice() else { + return None; + }; + + (!environment.environment.is_remote()).then_some(&environment.cwd) + } } pub(crate) fn resolve_environment_selections( @@ -210,4 +218,55 @@ url = "ws://127.0.0.1:8765" ); assert_eq!(resolved.primary().expect("primary environment").shell, None); } + + #[tokio::test] + async fn single_local_environment_cwd_requires_exactly_one_local_environment() { + let cwd = AbsolutePathBuf::current_dir().expect("cwd"); + let local_manager = EnvironmentManager::default_for_tests(); + let local = resolve_environment_selections( + &local_manager, + &[TurnEnvironmentSelection { + environment_id: LOCAL_ENVIRONMENT_ID.to_string(), + cwd: cwd.clone(), + }], + ) + .expect("local environment should resolve"); + let remote_manager = EnvironmentManager::create_for_tests( + Some("ws://127.0.0.1:8765".to_string()), + Some(test_runtime_paths()), + ) + .await; + let remote = resolve_environment_selections( + &remote_manager, + &[TurnEnvironmentSelection { + environment_id: REMOTE_ENVIRONMENT_ID.to_string(), + cwd: cwd.clone(), + }], + ) + .expect("remote environment should resolve"); + local_manager + .upsert_environment( + REMOTE_ENVIRONMENT_ID.to_string(), + "ws://127.0.0.1:8765".to_string(), + ) + .expect("remote environment should register"); + let multiple = resolve_environment_selections( + &local_manager, + &[ + TurnEnvironmentSelection { + environment_id: LOCAL_ENVIRONMENT_ID.to_string(), + cwd: cwd.clone(), + }, + TurnEnvironmentSelection { + environment_id: REMOTE_ENVIRONMENT_ID.to_string(), + cwd: cwd.clone(), + }, + ], + ) + .expect("multiple environments should resolve"); + + assert_eq!(local.single_local_environment_cwd(), Some(&cwd)); + assert_eq!(remote.single_local_environment_cwd(), None); + assert_eq!(multiple.single_local_environment_cwd(), None); + } } diff --git a/codex-rs/core/src/session/review.rs b/codex-rs/core/src/session/review.rs index fe78e033e..5a26cce2e 100644 --- a/codex-rs/core/src/session/review.rs +++ b/codex-rs/core/src/session/review.rs @@ -160,7 +160,9 @@ pub(super) async fn spawn_review_thread( client_id: None, }]; let tc = Arc::new(review_turn_context); - tc.turn_metadata_state.spawn_git_enrichment_task(); + if tc.environments.single_local_environment_cwd().is_some() { + tc.turn_metadata_state.spawn_git_enrichment_task(); + } // TODO(ccunningham): Review turns currently rely on `spawn_task` for TurnComplete but do not // emit a parent TurnStarted. Consider giving review a full parent turn lifecycle // (TurnStarted + TurnComplete) for consistency with other standalone tasks. diff --git a/codex-rs/core/src/session/turn_context.rs b/codex-rs/core/src/session/turn_context.rs index d60036813..166f8cea8 100644 --- a/codex-rs/core/src/session/turn_context.rs +++ b/codex-rs/core/src/session/turn_context.rs @@ -814,7 +814,13 @@ impl Session { turn_context.final_output_json_schema = final_schema; } let turn_context = Arc::new(turn_context); - turn_context.turn_metadata_state.spawn_git_enrichment_task(); + if turn_context + .environments + .single_local_environment_cwd() + .is_some() + { + turn_context.turn_metadata_state.spawn_git_enrichment_task(); + } turn_context }