Skip to content

Commit 38f8d5b

Browse files
zerone0xclaudevkodithala
authored
fix(context_chips): stop GitDiffStats flicker from shell fallback (#9244)
## Summary Fixes #9228. When a per-repo `GitRepoStatusModel` is attached to `CurrentPrompt`, the `GitDiffStats` chip is updated via filesystem-watcher events whose `DiffStateModel::diff_metadata_against_head()` count includes untracked files (it walks `git status --untracked-files=all`). However, every time the prompt context is rebuilt (e.g. when a new block's metadata arrives after a command completes), `run_chips` was still firing the chip's periodic shell-based generator once. For `GitDiffStats` that fallback is `shell_git_line_changes()`, which runs `git diff --shortstat HEAD` and counts only tracked changes. Its result was overwriting the watcher's structured `GitLineChanges` value until the next watcher `MetadataChanged` event restored it — causing the chip to visibly flicker between the tracked-only count and the all-files count whenever untracked files were present. ## Fix In `CurrentPrompt::run_chips`, when a chip is `is_updated_externally`, only run an `initial_value_generator` if one is provided. The shell-based `chip.generator()` is no longer used as a fallback for externally-driven chips: - `ShellGitBranch` continues to seed its initial value from `current_environment.git_branch()` via `initial_value_generator`, then receives updates from the watcher. - `GitDiffStats` has no `initial_value_generator`, so the periodic shell command is now skipped entirely. Initial population is handled by the watcher: `GitRepoStatusModel::new()` kicks off `refresh_metadata` immediately and emits `MetadataChanged` once metadata is computed, which `set_git_repo_status` handles by updating `GitDiffStats` with the structured `GitLineChanges`. Existing chip values survive across `clear_chips()` (which only aborts in-flight generators), so there is no transient empty state on subsequent prompt refreshes. This keeps the diff-count semantics consistent (always all-files) without changing the behavior of remote/non-watched sessions, which still fall back to the shell generator via the periodic timer branch. ## Test plan - [ ] In a repo with both modified tracked files and untracked files, run a command (e.g. `ls`) and observe the `GitDiffStats` chip — it should stay on the all-files count without flickering down to the tracked-only count. - [ ] In a repo without the watcher available (e.g. remote session), confirm the chip still updates periodically via the shell fallback (unchanged code path). - [ ] `ShellGitBranch` continues to update on branch changes via the watcher and shows the correct branch on first paint. CHANGELOG-BUG-FIX: Fix git diff chip flickering between tracked-only and all-files count when untracked files are present --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: vkodithala <varoon@warp.dev>
1 parent 0964e69 commit 38f8d5b

1 file changed

Lines changed: 25 additions & 9 deletions

File tree

‎app/src/context_chips/current_prompt.rs‎

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,15 +1041,31 @@ impl CurrentPrompt {
10411041
}
10421042
RefreshConfig::Periodically { .. } => {
10431043
if self.is_updated_externally(chip_kind) {
1044-
let initial_gen = chip_kind.initial_value_generator();
1045-
let generator = initial_gen.as_ref().unwrap_or(chip.generator());
1046-
self.fetch_chip_value_once(
1047-
chip_kind,
1048-
generator,
1049-
chip.on_click_generator().cloned(),
1050-
true,
1051-
ctx,
1052-
);
1044+
// For chips updated externally (e.g. by the per-repo
1045+
// git status filesystem watcher), avoid running the
1046+
// periodic shell-based generator. Doing so can briefly
1047+
// overwrite the structured watcher value with one that
1048+
// uses different semantics (for example, the
1049+
// `GitDiffStats` shell fallback runs `git diff
1050+
// --shortstat HEAD`, which excludes untracked files,
1051+
// whereas the watcher counts untracked files as
1052+
// changes), causing the chip to flicker between the
1053+
// tracked-only count and the all-files count when
1054+
// untracked files are present.
1055+
//
1056+
// If a chip provides an `initial_value_generator` that
1057+
// sources from the prompt context (rather than running
1058+
// a shell command), use it for a fast initial value
1059+
// until the watcher emits a metadata-changed event.
1060+
if let Some(initial_gen) = chip_kind.initial_value_generator() {
1061+
self.fetch_chip_value_once(
1062+
chip_kind,
1063+
&initial_gen,
1064+
chip.on_click_generator().cloned(),
1065+
true,
1066+
ctx,
1067+
);
1068+
}
10531069
} else {
10541070
self.fetch_chip_value_at_interval(
10551071
chip_kind,

0 commit comments

Comments
 (0)