Skip to content

fix(editor): load file diffs without waiting for background Git work - #3386

Merged
jschwxrz merged 5 commits into
generalaction:mainfrom
ykakade:fix/3382-responsive-file-diffs
Oct 30, 2026
Merged

jschwxrz merged 5 commits into
generalaction:mainfrom
ykakade:fix/3382-responsive-file-diffs

Conversation

@ykakade

@ykakade ykakade commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

Description

Changed-file diffs now load while background Git scans run. The editor shows a loading state or an error instead of a blank pane.

Git snapshots use a separate queue with at most two reads per repository family. Each read resolves a blob OID before loading its content. Mutations keep their existing ordering and object-store locks. Closing a content query cancels its queued or active read.

The Monaco editor stays mounted while content loads or recovers. Missing sides still render as empty content for added and deleted files.

Related issues

Fixes #3382.

Testing

  • pnpm run format and pnpm run format:check
  • pnpm run lint
  • pnpm run typecheck
  • EMDASH_TEST_SKIP_BROWSER=1 pnpm run test -- --maxWorkers=4
  • All 11 tests in sticky-diff-editor.browser.test.tsx in Chromium
  • Linux automated checks. macOS, Windows, and SSH were not manually tested.

On base, a held background job prevented content reads from starting. The scheduling regression failed with this assertion.

AssertionError: expected "vi.fn()" to be called once, but got 0 times

The browser regression failed with this assertion on base.

AssertionError: expected '' to contain 'Loading diff...'

The tests now cover reads during a blocked background job, bounded concurrency, cancellation, and repository disposal. Browser coverage checks errors on either side, recovery, and empty sides for added or deleted files.

The non-browser workspace run passes, including 4,869 desktop tests. All 11 focused Monaco Chromium tests also pass.

The broad desktop browser suite crashes in the Playwright route handler on both this branch and unchanged base. The same command produces this runner error.

Error: route.fulfill: The object has been collected to prevent unbounded heap growth.

Screenshot/Recording (if applicable)

The same Chromium fixture at 900 × 500, while the original side loads:

Before After
Blank diff while loading Visible loading state
Checklist
  • Keep reads bounded and cancel them when their owner closes
  • Cover background contention, errors, and recovery with regression tests
  • Document the diff lifecycle and scheduling
  • I kept this PR small and focused
  • I ran a self-review before opening this PR
  • I ran the relevant local checks or explained why not
  • I updated docs when behavior or setup changed
  • I added or updated tests when behavior changed, or explained why not
  • I only added comments where the logic is not obvious
  • I used Conventional Commits for commit messages and the PR title

Bound snapshot reads separately from repository status scans. Show loading and
failure states while the existing diff editor waits for its content.
@ykakade
ykakade marked this pull request as ready for review October 30, 2026 02:30
@greptile-apps

greptile-apps Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge, with a non-blocking gap in the notice shown during retries.

Findings

  1. P2 Retry hides the loading notice ▶
Fix with agent prompt
### Issue 1
apps/emdash-desktop/src/core/features/editor/contributions/browser/monaco/sticky-diff-editor.tsx:99-100
Retrying a failed Git side sets its status to `loading`. For an already loaded diff, `diffNotice` then removes the banner because there is no error. But the editor keeps `readOnly` enabled and the save command still returns early. Users see a diff that looks ready but cannot be edited or saved while the retry runs. Keep a loading banner visible until both sides recover.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

File diffs use a separate queue with at most two reads per repository family, so background Git work no longer holds them up.

  • Git snapshots load without waiting for background scans.
  • Diff panes show loading and error states instead of going blank.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Git[Repository Git work] --> Ordered[Existing ordered queue]
  Diff[Diff content request] --> Reads[Separate queue: two reads]
  Reads --> OID[Resolve blob OID]
  OID --> Content[Read blob content]
  Close[Last owner closes] --> Cancel[Cancel queued or active read]
Loading

Reviews (2) · Last reviewed commit: "fix(editor): keep a loaded diff read-onl..." · Reviewed by Greptile

Content queries stay cached after their last lease, and a query only aborts
its fetch on dispose, so closing a diff left its read running. With at most
two content reads per repository family, reads from closed diffs could delay
the next diff. Releasing the last owner of an entry with a read in flight now
evicts it, which cancels the queued or active read; reopening starts fresh.

Move the content-read scheduling notes to the git runtime doc, next to the
repository-family ordering they depart from.
The status overlay covered the editor whenever a side was loading or failed,
including after a diff was shown. A refresh failure then hid the diff while
the modified buffer kept focus, so typing and Cmd+S still changed and saved a
buffer the user could not see.

Cover the editor only until a diff is first attached. After that, keep the
last loaded diff visible, make it read-only, and name the failure in a banner
above it; editing resumes when both sides recover. The save command also
refuses to save while the editor is read-only.
@jschwxrz

Copy link
Copy Markdown
Member

Thanks for this. Moving content reads to their own lane is the right fix. I pushed two commits on top for the review findings:

  • fix(git): cancel content reads once their last owner releases them: content queries stay cached after their last lease and only abort on dispose, so closing a diff didn't cancel its read. Releasing the last owner of an entry that has a read in flight now evicts it, which cancels the queued or active read. Covered through fileContent in allocation-graph.test.ts.
  • fix(editor): keep a loaded diff read-only when a side fails: the overlay now covers the editor only until a diff is first shown. After that, a failing side keeps the last loaded diff visible and read-only under a banner, and Cmd+S does nothing while it is read-only. Covered by a new browser test.

I also moved the scheduling notes to agents/architecture/git-runtime.md, next to the repository-family ordering they depart from.

Comment on lines +99 to +100
if (attached) {
if (!error) return null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Retry hides the loading notice

Retrying a failed Git side sets its status to loading. For an already loaded diff, diffNotice then removes the banner because there is no error. But the editor keeps readOnly enabled and the save command still returns early. Users see a diff that looks ready but cannot be edited or saved while the retry runs. Keep a loading banner visible until both sides recover.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/emdash-desktop/src/core/features/editor/contributions/browser/monaco/sticky-diff-editor.tsx
Line: 99-100

Comment:
**Retry hides the loading notice**

Retrying a failed Git side sets its status to `loading`. For an already loaded diff, `diffNotice` then removes the banner because there is no error. But the editor keeps `readOnly` enabled and the save command still returns early. Users see a diff that looks ready but cannot be edited or saved while the retry runs. Keep a loading banner visible until both sides recover.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Valid. Fixed in 7c373de: while a side reloads, an attached diff now shows a "Reloading diff..." banner, and stays read-only until both sides recover. The browser test covers error → retry → ready.

Retrying a failed side moves it back to loading. The notice only covered
errors for an attached diff, so the banner vanished while the editor stayed
read-only, and the diff looked ready but ignored edits and Cmd+S. Show a
reloading banner until both sides recover.

@jschwxrz jschwxrz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Content reads now run in their own lane with real cancellation, and the diff editor covers the editor only until a diff is first shown; after that, failures and reloads keep the diff visible and read-only under a banner. CI is green on top of the git 2.56 test fix (#3388). Thanks!

@jschwxrz
jschwxrz merged commit 84dd080 into generalaction:main Oct 30, 2026
7 checks passed
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.

[bug]: Changed file diff stays blank in large repositories

2 participants