Skip to content

Conversation

@AnnatarHe
Copy link
Contributor

Summary

  • Fix race condition in cc statusline when parallel requests come from different CWDs
  • Previously, only a single activeWorkingDir and gitInfo was stored, causing requests to overwrite each other
  • Now each CWD has its own cache entry with separate git info

Changes

  • Add GitCacheEntry struct with Info, LastAccessed, and LastFetched fields
  • Replace single cache with map[string]*GitCacheEntry keyed by normalized path
  • Background fetch iterates over all recently accessed directories
  • Stale entries evicted after inactivity timeout
  • Add 8 new tests for multi-CWD caching

Test plan

  • All daemon tests pass
  • Race detector finds no issues
  • Build successful
  • Manual test: Run two Claude Code instances in different repos, verify each shows correct branch

🤖 Generated with Claude Code

Previously, the daemon stored only a single activeWorkingDir and gitInfo,
causing race conditions when parallel requests came from different CWDs.
Now each working directory has its own cache entry with separate git info,
preventing incorrect branch/dirty status from being returned.

- Add GitCacheEntry struct with Info, LastAccessed, and LastFetched fields
- Replace single cache with map[string]*GitCacheEntry keyed by normalized path
- Background fetch iterates over all recently accessed directories
- Stale entries evicted after inactivity timeout

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @AnnatarHe, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical race condition in the daemon's cc statusline functionality, which previously struggled with concurrent requests from multiple working directories. By refactoring the git information storage from a single global state to a robust, per-working-directory cache, the system can now correctly maintain and serve distinct git details for each active CWD. This change significantly enhances the stability and accuracy of the statusline feature, especially in multi-project development environments.

Highlights

  • Race Condition Fix: Resolved a race condition in the cc statusline feature that occurred when parallel requests originated from different current working directories (CWDs).
  • Per-CWD Git Info Cache: Replaced the single global activeWorkingDir and gitInfo storage with a new per-CWD caching mechanism to prevent requests from overwriting each other's git information.
  • New Cache Structure: Introduced a GitCacheEntry struct to encapsulate git information along with LastAccessed and LastFetched timestamps, managed by a map[string]*GitCacheEntry keyed by normalized paths.
  • Optimized Background Fetch: The background git info fetching now intelligently iterates only over recently accessed directories, improving efficiency and relevance.
  • Stale Entry Eviction: Implemented a mechanism to automatically evict stale cache entries after a defined inactivity timeout, ensuring the cache remains lean and up-to-date.
  • Comprehensive Testing: Added 8 new dedicated test cases to validate the multi-CWD caching logic, covering scenarios like path normalization, concurrency, and stale entry cleanup.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link

codecov bot commented Jan 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

Flag Coverage Δ
unittests 37.74% <100.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
daemon/cc_info_timer.go 95.58% <100.00%> (+8.62%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses a race condition by introducing a per-CWD cache for git information, which is a solid improvement. The implementation is clean and the new tests provide good coverage for the changes. I have a couple of suggestions. First, to improve performance when multiple repositories are active, the git info fetching could be parallelized. Second, several of the new tests use hardcoded Unix-style path separators, which will cause them to fail on Windows. Making them platform-independent will improve test suite robustness. Overall, great work on fixing the race condition and improving the caching logic.

Comment on lines +324 to 338
for _, dir := range dirsToFetch {
info := GetGitInfo(dir)

s.mu.Lock()
if entry, exists := s.gitCache[dir]; exists {
entry.Info = info
entry.LastFetched = time.Now()
}
s.mu.Unlock()

slog.Debug("Git info updated",
slog.String("workingDir", dir),
slog.String("branch", info.Branch),
slog.Bool("dirty", info.Dirty))
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation fetches git info for each directory sequentially. If there are multiple active repositories and GetGitInfo is slow (as it involves disk I/O), this loop could take longer than the CCInfoFetchInterval, causing fetches to pile up. To improve performance, you could fetch the git info for each directory in parallel using goroutines and a sync.WaitGroup.

	var wg sync.WaitGroup
	for _, dir := range dirsToFetch {
		wg.Add(1)
		go func(dir string) {
			defer wg.Done()
			info := GetGitInfo(dir)

			s.mu.Lock()
			if entry, exists := s.gitCache[dir]; exists {
				entry.Info = info
				entry.LastFetched = time.Now()
			}
			s.mu.Unlock()

			slog.Debug("Git info updated",
				slog.String("workingDir", dir),
				slog.String("branch", info.Branch),
				slog.Bool("dirty", info.Dirty))
		}(dir)
	}
	wg.Wait()

defer service.mu.RUnlock()
// Both should map to the same normalized path
assert.Len(s.T(), service.gitCache, 1)
assert.Contains(s.T(), service.gitCache, "/project/a")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test uses a hardcoded path /project/a which assumes a Unix-like path separator. The implementation correctly uses filepath.Clean which will produce platform-specific paths (e.g., \project\a on Windows). This will cause the test to fail on Windows. To make the test platform-independent, you should use filepath.Clean in the assertion as well.

This issue is present in multiple new tests (TestGetCachedGitInfo_CreatesNewEntry, TestGetCachedGitInfo_MultipleCWDs, TestGetCachedGitInfo_UpdatesLastAccessed, TestGetCachedGitInfo_ReturnsCachedValue, TestCleanupStaleGitCache_RemovesOldEntries, TestConcurrentGetCachedGitInfo_DifferentDirs, TestStopTimer_ClearsGitCache). Please apply similar fixes there. You'll also need to import the path/filepath package in this test file.

Suggested change
assert.Contains(s.T(), service.gitCache, "/project/a")
assert.Contains(s.T(), service.gitCache, filepath.Clean("/project/a"))
References
  1. For platform-independent paths, use filepath.Join to combine segments and os.UserHomeDir() to get the home directory, rather than hardcoding path separators or environment variables like $HOME.

@AnnatarHe AnnatarHe merged commit 863689b into main Jan 8, 2026
6 checks passed
@AnnatarHe AnnatarHe deleted the fix/cc-statusline-per-cwd-git-cache branch January 8, 2026 15:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants