Skip to content

Refresh working tree diff after turns#3906

Open
jakeleventhal wants to merge 3 commits into
pingdotgg:mainfrom
jakeleventhal:t3code/fix-deleted-file-diff-state
Open

Refresh working tree diff after turns#3906
jakeleventhal wants to merge 3 commits into
pingdotgg:mainfrom
jakeleventhal:t3code/fix-deleted-file-diff-state

Conversation

@jakeleventhal

@jakeleventhal jakeleventhal commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

What changed

  • include the latest completed turn and live working-tree summary in the diff preview query cache identity
  • allow environment RPC queries to accept a client-only cache key without changing the RPC payload
  • cover cache-key isolation and untracked-file deletion with regression tests

Why

The Working tree diff preview could reuse a cached response after a later agent turn changed the repository. This was especially visible when a file created in one turn was deleted in the next: Git correctly omitted the deleted untracked file from a fresh preview, but the UI could continue rendering the earlier cached patch.

The updated cache identity selects a fresh preview after completed turns and working-tree status changes, while keeping the refresh declarative in the query layer.

Impact

Working tree and branch diff views now reflect the latest repository state after agent turns and Git status changes instead of briefly showing a stale patch.

Validation

  • vp test packages/client-runtime/src/state/runtime.test.ts apps/server/src/vcs/GitVcsDriverCore.test.ts
  • vp check
  • vp run typecheck

Note

Medium Risk
Touches VCS streaming semantics (more localUpdated events) and review UI caching; behavior is well-tested but clients depending on deduplicated local updates may see extra refetches.

Overview
Fixes stale working-tree and branch diff previews after agent turns or repo changes by tying client query cache identity to live VCS signals, not only RPC inputs.

localGeneration increments on every local status refresh in VcsStatusBroadcaster and flows through stream events and VcsStatusResult; localUpdated is published whenever a refresh is published, even if the local summary is unchanged. remoteRefHash (SHA-256 of refs/remotes) is added to remote status so fetches that move tracking refs invalidate cache without relying on ahead/behind alone.

DiffPanel builds a diffPreviewCacheKey from latest turn id, localGeneration, and remoteRefHash and passes it to environment diff preview queries. environmentRpcKey accepts an optional client-only cacheKey so the same RPC input can map to separate cached results.

Regression tests cover untracked-file deletion in review previews, remote ref hash movement, unchanged local status still bumping generation, and cache key isolation.

Reviewed by Cursor Bugbot for commit fe250ed. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Refresh working tree diff after turns by tracking local and remote ref changes

  • Adds a localGeneration counter to VCS status that increments on every local status update, replacing fingerprint-based deduplication in VcsStatusBroadcaster.
  • Adds remoteRefHash to remote status by hashing all remote-tracking refs via git for-each-ref; the hash changes when any remote ref moves.
  • Introduces diffPreviewCacheKey in DiffPanel composed from latestTurnId, localGeneration, and remoteRefHash, so diff preview queries re-execute after each turn or remote ref change.
  • Extends environmentRpcKey in runtime.ts with an optional cacheKey to isolate environment queries when the cache key differs.
  • Behavioral Change: local status events are now always published on update (no fingerprint gating), so consumers may receive more frequent localUpdated events than before.

Macroscope summarized fe250ed.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 29a3efa1-bc4f-439f-ac1e-217b14782aca

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the vouch:unvouched PR author is not yet trusted in the VOUCHED list. label Jul 12, 2026
@jakeleventhal jakeleventhal marked this pull request as ready for review July 12, 2026 03:13
@github-actions github-actions Bot added the size:S 10-29 changed lines (additions + deletions). label Jul 12, 2026
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Jul 12, 2026
@macroscopeapp

macroscopeapp Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a new caching mechanism for diff previews that changes runtime behavior across server and client. The three open review comments raise valid design concerns about potential edge cases where the cache key may not properly invalidate stale diffs.

You can customize Macroscope's approvability policy. Learn more.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 68f23c90ce

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +273 to +276
const diffPreviewCacheKey = JSON.stringify({
latestTurnId: latestTurn?.turnId ?? null,
workingTree: gitStatusQuery.data?.workingTree ?? null,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include HEAD state in the diff preview cache key

When the current ref changes while the working tree summary is unchanged, this cache key does not change even though getReviewDiffPreview recomputes the branch-range diff from the current HEAD/branch. For example, switching between two clean branches leaves workingTree as an empty summary and latestTurnId unchanged, so the branch diff panel can keep reusing the previous ${baseRef}...HEAD preview. Include ref/HEAD-relevant status (or a VCS generation) in the cache key, not just the working-tree summary.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines +273 to +276
const diffPreviewCacheKey = JSON.stringify({
latestTurnId: latestTurn?.turnId ?? null,
workingTree: gitStatusQuery.data?.workingTree ?? null,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Track content changes hidden by the status summary

When an already-listed changed file is edited without changing its path or numstat summary, this key stays identical while the patch returned by getReviewDiffPreview changes. This is especially easy for untracked files because the status summary records them as the same path with 0 insertions/deletions, so editing the file contents after the preview is cached leaves the Working tree panel rendering the old patch until something else changes the key. Use a content/diff generation or refreshed diff hash rather than only the lossy workingTree summary.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@macroscopeapp macroscopeapp Bot dismissed their stale review July 12, 2026 03:29

Dismissing prior approval to re-evaluate 601d479

@github-actions github-actions Bot added size:M 30-99 changed lines (additions + deletions). and removed size:S 10-29 changed lines (additions + deletions). labels Jul 12, 2026

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 601d479ebe

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const latestTurn = orderedTurnDiffSummaries[0];
const diffPreviewCacheKey = JSON.stringify({
latestTurnId: latestTurn?.turnId ?? null,
localGeneration: gitStatusQuery.data?.localGeneration ?? null,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include remote ref changes in diff preview keys

When the branch preview is based on a remote ref, a fetch can move that base ref while the working tree and HEAD stay unchanged; VcsStatusBroadcaster.updateCachedRemoteStatus publishes only remoteUpdated, and applyGitStatusStreamEvent preserves the old localGeneration, so this cache key stays identical even though getReviewDiffPreview recomputes ${baseRef}...HEAD against the new ref. Include a remote generation/fingerprint in the key for branch-range previews so the panel refreshes after remote status updates.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant