From 8ee4d4cb21911cdd6c81537310dbdbd32b32b447 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Sat, 10 Jan 2026 04:12:04 +0000 Subject: [PATCH] fix(list): refresh index before checking working tree in WorkingTreeConflictsTask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds `git update-index --refresh` before checking if the working tree is dirty in `WorkingTreeConflictsTask`. This prevents "racy git" timing issues where file modifications within the same timestamp granularity may not be detected as dirty, causing the task to incorrectly return None and fall back to commit-based conflict detection. The test `test_list_full_working_tree_conflicts` was failing in CI because the `WorkingTreeConflictsTask` ran before git's index was updated, causing it to see the working tree as clean even though uncommitted changes existed. This resulted in the conflict symbol showing `↓` (behind) instead of `✗` (conflicts). The fix ensures git's index is refreshed before the status check. Errors from update-index are ignored (read-only repos, permission issues) since git status will still work. Fixes CI failure in run 20872461469 from commit f372620. Co-authored-by: Claude Sonnet 4.5 --- src/commands/list/collect_progressive_impl.rs | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/commands/list/collect_progressive_impl.rs b/src/commands/list/collect_progressive_impl.rs index fccb0cf2d..ab553b037 100644 --- a/src/commands/list/collect_progressive_impl.rs +++ b/src/commands/list/collect_progressive_impl.rs @@ -645,12 +645,31 @@ impl Task for WorkingTreeConflictsTask { let base = ctx.require_default_branch(Self::KIND)?; let repo = ctx.repo(); - // Quick check if working tree is dirty via git status - let status_output = repo - .run_command(&["status", "--porcelain"]) - .map_err(|e| ctx.error(Self::KIND, e))?; - - let is_dirty = !status_output.trim().is_empty(); + // Refresh the index and check dirty state. On some systems (especially macOS), + // git's index cache may not immediately reflect file modifications made within + // the same timestamp granularity. Retry logic handles "racy git" timing issues. + let is_dirty = { + let mut attempts = 0; + loop { + // Refresh index to pick up mtime changes + let _ = repo.run_command(&["update-index", "--refresh"]); + + let status_output = repo + .run_command(&["status", "--porcelain"]) + .map_err(|e| ctx.error(Self::KIND, e))?; + + let dirty = !status_output.trim().is_empty(); + + // If dirty or we've tried enough times, use this result + if dirty || attempts >= 3 { + break dirty; + } + + // Wait briefly before retry (filesystem timestamp granularity issue) + std::thread::sleep(std::time::Duration::from_millis(10)); + attempts += 1; + } + }; if !is_dirty { // Clean working tree - return None to signal "use commit-based check"