Skip to content

fix(code): keep diff stats, PR button, and diff panel refreshing in sync#3093

Merged
adboio merged 3 commits into
mainfrom
posthog-code/consistent-diff-stats-refresh
Jul 2, 2026
Merged

fix(code): keep diff stats, PR button, and diff panel refreshing in sync#3093
adboio merged 3 commits into
mainfrom
posthog-code/consistent-diff-stats-refresh

Conversation

@adboio

@adboio adboio commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Problem

The diff numbers in the top bar (and the PR +/- badge) updated on a different cadence than the diff panel and PR button — they'd sit stale for up to 30s after the agent edited files.

Root cause: the header badge / session chip read diffStats.getDiffStats over the workspace-client transport, while the panel, PR button, and changes panel read git.getDiffStats over the host-router transport. The file-watcher invalidation (invalidateGitWorkingTreeQueries) is keyed on the host git.* namespace, so it never named the workspace-client query — that path only refreshed on a 30s poll. The two procedures were byte-identical, and both were mounted at once, so the split also ran git diff --numstat twice.

Changes

  • Unify the stats onto the watcher-invalidated query. useDiffStats now reads the host-router git.getDiffStats — the same query useGitQueries (changes panel + PR button) and the diff panel already use. The header badge and session chip share one watcher-invalidated cache entry: no duplicate fetch, no separate 30s poll, and all diff surfaces refresh together.
  • Remove the orphaned diffStats router from workspace-server (it duplicated git.getDiffStats).
  • Add a max-wait to the file watcher. The working-tree watcher used a pure trailing 500ms debounce that reset on every FS event, so a continuously-writing agent never tripped it until it paused (the "panel lags behind the agent" feeling). A 1000ms max-wait keeps coalescing bursts but guarantees a flush at least once a second during sustained activity, so the panel/stats advance mid-run.

The PR button was already on the correct (watcher-invalidated) path and is unchanged; only the +/- number beside it was stale, which the unification fixes.

Tests

  • New fake-timer tests for the watcher: trailing debounce coalesces a burst and emits once quiet; the max-wait forces a flush during sustained activity (fails on the old trailing-only behavior).
  • @posthog/ui and @posthog/workspace-server typecheck clean; biome check clean; watcher suite 4/4, full workspace-server unit suite 547 pass. (The only failing suites are pre-existing git/archive integration tests that shell out to git commit, unrelated to this change.)

The top-bar diff numbers (and the PR `+/-` badge) lagged behind the diff
panel and PR button because they were fed by a second, separate query.

`useDiffStats` read `diffStats.getDiffStats` over the workspace-client
transport, whose cache key the file-watcher invalidation
(`invalidateGitWorkingTreeQueries`, keyed on the host `git.*` namespace)
never named. So while the panel and PR button refreshed on the watcher, the
header/chip numbers only updated on a 30s poll. The two procedures were
byte-identical, and both surfaces were mounted at once, so the split also
duplicated the `git diff --numstat` work.

- Point `useDiffStats` at the host-router `git.getDiffStats` — the same query
  the changes panel and PR button already use. The header badge and session
  chip now share one watcher-invalidated cache entry (no duplicate fetch, no
  30s poll), so all diff surfaces move together.
- Remove the now-orphaned `diffStats` router from workspace-server.

Separately, the diff panel felt like it lagged behind the agent: the
working-tree watcher used a pure trailing 500ms debounce that reset on every
FS event, so a continuously-writing agent never tripped it until it paused.
Add a 1000ms max-wait so a burst still coalesces but flushes at least once a
second during sustained activity, keeping the panel/stats advancing mid-run.

Adds fake-timer tests covering both the trailing debounce and the max-wait.

Generated-By: PostHog Code
Task-Id: 6c689b1a-75d5-40f5-91fc-edf40df99467
@trunk-io

trunk-io Bot commented Jul 2, 2026

Copy link
Copy Markdown

Merging to main in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

React Doctor found no issues in the changed files. 🎉

Reviewed by React Doctor for commit c6e5053.

@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Reviews (1): Last reviewed commit: "fix(code): keep diff stats, PR button, a..." | Re-trigger Greptile

Comment thread packages/workspace-server/src/services/watcher/service.test.ts Outdated
adboio added 2 commits July 2, 2026 09:03
Export DEBOUNCE_MS and MAX_WAIT_MS from the watcher service and import them
in the test instead of re-declaring the literals, so the timing assertions
can't silently pass against stale thresholds if the source values change.
Also derive the max-wait test's step/boundary from the constants rather than
magic numbers, and assert it stayed active past the debounce window before
the max-wait fired.

Addresses Greptile review feedback on the PR.

Generated-By: PostHog Code
Task-Id: 6c689b1a-75d5-40f5-91fc-edf40df99467
The header badge's query observer survives task switches (HeaderRow never
remounts), so the `(prev) => prev` placeholder carried the previous repo's
numbers onto the next task — indefinitely when that task has no cwd and the
query stays disabled (e.g. suspended tasks). Use the plain empty-stats value
instead; same-key background refetches keep data regardless, so the function
form only bought the cross-key carry-over.

Also dedupe the three EMPTY_DIFF_STATS copies onto the existing export from
@posthog/core/code-review/selectTaskDiffStats, and drop the watcher test's
ignore-pattern discrimination in the watch() mock — with resolveGitDirs
returning no git dirs, the working-tree watch is the only call.

Generated-By: PostHog Code
Task-Id: c798dbdd-7555-4d15-bffe-b293af635026
@adboio adboio added the Stamphog This will request an autostamp by stamphog on small changes label Jul 2, 2026 — with Graphite App
@adboio adboio marked this pull request as ready for review July 2, 2026 17:54
@adboio adboio requested a review from a team July 2, 2026 17:54

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Well-coordinated fix that consolidates three previously divergent data sources (diff stats badge, PR button, diff panel) onto a single shared cache entry with event-driven invalidation, and adds a max-wait timer to the file watcher so sustained agent writes no longer freeze the UI. The removed diffStats workspace-server sub-router had exactly one consumer (useDiffStats), which is being migrated in the same PR; the new query is already covered by the existing invalidateGitWorkingTreeQueries invalidation path. The resolved bot comment about duplicated constants is addressed by exporting them from service.ts.

@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Reviews (2): Last reviewed commit: "fix(code): don't carry diff stats across..." | Re-trigger Greptile

@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Want your agent to iterate on Greptile's feedback? Try greploops.

@adboio adboio merged commit 489a308 into main Jul 2, 2026
30 checks passed
@adboio adboio deleted the posthog-code/consistent-diff-stats-refresh branch July 2, 2026 19:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Stamphog This will request an autostamp by stamphog on small changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant