Use remote filesystem for turn git root discovery

Remote test workspaces can live only inside the executor filesystem, so local git discovery cannot find repo markers for turn diffs. Add an executor-filesystem-backed repo root lookup and use it when building the turn diff display root. Align core-skills test project-layer discovery with the same ambient git marker filtering used by production discovery.

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
starr-openai
2026-05-08 16:24:01 -07:00
parent 6e3e8fe60f
commit a898c75bce
4 changed files with 26 additions and 3 deletions

View File

@@ -44,7 +44,7 @@ fn project_layers_for_cwd(cwd: &Path) -> Vec<ConfigLayerEntry> {
};
let project_root = cwd_dir
.ancestors()
.find(|ancestor| ancestor.join(".git").exists())
.find(|ancestor| ancestor.join(".git").exists() && !is_ambient_git_marker_dir(ancestor))
.unwrap_or(cwd_dir.as_path())
.to_path_buf();

View File

@@ -69,6 +69,7 @@ use codex_analytics::build_track_events_context;
use codex_async_utils::OrCancelExt;
use codex_features::Feature;
use codex_git_utils::get_git_repo_root;
use codex_git_utils::get_git_repo_root_with_fs;
use codex_hooks::HookEvent;
use codex_hooks::HookEventAfterAgent;
use codex_hooks::HookPayload;
@@ -100,6 +101,7 @@ use codex_protocol::protocol::WarningEvent;
use codex_protocol::user_input::UserInput;
use codex_tools::ToolName;
use codex_tools::filter_request_plugin_install_discoverable_tools_for_client;
use codex_utils_absolute_path::AbsolutePathBuf;
use codex_utils_stream_parser::AssistantTextChunk;
use codex_utils_stream_parser::AssistantTextStreamParser;
use codex_utils_stream_parser::ProposedPlanSegment;
@@ -366,8 +368,13 @@ pub(crate) async fn run_turn(
let mut stop_hook_active = false;
// Although from the perspective of codex.rs, TurnDiffTracker has the lifecycle of a Task which contains
// many turns, from the perspective of the user, it is a single turn.
let display_root = get_git_repo_root(turn_context.cwd.as_path())
.unwrap_or_else(|| turn_context.cwd.clone().into_path_buf());
let display_root = match turn_context.environments.primary_filesystem() {
Some(fs) => get_git_repo_root_with_fs(fs.as_ref(), &turn_context.cwd)
.await
.map(AbsolutePathBuf::into_path_buf),
None => get_git_repo_root(turn_context.cwd.as_path()),
}
.unwrap_or_else(|| turn_context.cwd.clone().into_path_buf());
let turn_diff_tracker = Arc::new(tokio::sync::Mutex::new(TurnDiffTracker::with_display_root(
display_root,
)));

View File

@@ -38,6 +38,21 @@ pub fn get_git_repo_root(base_dir: &Path) -> Option<PathBuf> {
find_ancestor_git_entry(base).map(|(repo_root, _)| repo_root)
}
/// Return the git repository root for `base_dir` using the provided executor
/// filesystem. This is the remote-environment equivalent of [`get_git_repo_root`].
pub async fn get_git_repo_root_with_fs(
fs: &dyn ExecutorFileSystem,
base_dir: &AbsolutePathBuf,
) -> Option<AbsolutePathBuf> {
let base = match fs.get_metadata(base_dir, /*sandbox*/ None).await {
Ok(metadata) if metadata.is_directory => base_dir.clone(),
_ => base_dir.parent()?,
};
find_ancestor_git_entry_with_fs(fs, &base)
.await
.map(|(repo_root, _)| repo_root)
}
/// Timeout for git commands to prevent freezing on large repositories
const GIT_COMMAND_TIMEOUT: TokioDuration = TokioDuration::from_secs(5);

View File

@@ -31,6 +31,7 @@ pub use info::default_branch_name;
pub use info::get_git_remote_urls;
pub use info::get_git_remote_urls_assume_git_repo;
pub use info::get_git_repo_root;
pub use info::get_git_repo_root_with_fs;
pub use info::get_has_changes;
pub use info::get_head_commit_hash;
pub use info::git_diff_to_remote;