Skip to content

feat(worktree): show checkout progress while a worktree is created - #24093

Merged
brennanb2025 merged 6 commits into
mainfrom
brennanb2025/create-checkout-progress
Oct 16, 2026
Merged

brennanb2025 merged 6 commits into
mainfrom
brennanb2025/create-checkout-progress

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 5 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​308 $\color{#cf222e}{\Huge{\mathbf{−}}}$​1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​307
Prod 23 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​313 $\color{#cf222e}{\Huge{\mathbf{−}}}$​28 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​285

ELI5

When you create a worktree in a big repo, most of the wait is Git writing out every file.
Until now the create card just said "Creating worktree…" the whole time, so you couldn't tell whether it was moving, stuck, or almost done.
Git already reports how far along it is; Orca was throwing that away.
This PR shows it: the card now reads "Checking out files… 45%" with a thin progress bar that fills as Git writes the files.

Refreshed on current main (2026-10-15)

What Changed

The problem. Checking out a large repo takes 5–15 s on a busy Mac, and minutes when the disk is contended.
For that whole time, the sidebar row and the in-tab creation panel showed only "Creating worktree…", a spinner and a clock.
Orca's style guide asks for real progress on anything that takes more than 3 s.

Why it happened. Git already writes a progress meter (Updating files: 45% (13770/30600)) into the pipe Orca reads while git worktree add runs.
Orca collected that text only to use as an error message and dropped it when the create succeeded.

What is different for users:

  • Local creates whose checkout takes more than about a second: the panel's status line changes from "Creating worktree…" to "Checking out files… 45%", and a thin progress bar appears under it. The sidebar row shows the same text, without a bar, so its height doesn't change.
  • When Git reports that the checkout is done, the bar disappears and the label goes back to "Creating worktree…" for the last few steps (Git's post-checkout hook, config writes, confirming the new worktree). Then the card hands off to the terminal as before.
  • Everything else looks exactly as it did: checkouts shorter than about a second, sparse checkouts, folder workspaces, SSH repos, and creates from the CLI, automations or a paired remote server.
  • Creates that reuse a prepared spare checkout also look as they do today: "Creating worktree…" with no bar. Opening the composer on a local repo starts checking out a spare in the background, so a create from the composer on its default base often reuses that spare. Reusing it runs no git worktree add, so there is no meter to read. The bar appears on creates that do their own checkout: when no spare matches (another base, an existing branch, an expired or already-used spare, or the spare isn't armed yet), or when the spare fails and the create falls back to a normal checkout.
  • Retrying a failed create starts clean; no leftover bar from the attempt that failed.
  • In a non-English Orca, every status line on the create card is now translated. Before, only the new "Checking out files…" line would have been, so the label would have switched from English to your language and back during one create.

How (mechanism):

  • Git's command and environment are unchanged. git worktree add has no --progress flag (Git 2.25 and 2.50 both reject it). It doesn't need one: it checks out through a child git reset --hard, which prints its meter into a pipe after about a second on every Git from 2.25 on, Windows included. Orca only reads bytes Git was already writing.
  • A passive stderr observer on the shared Git runner (GitExecOptions.onStderr). The runner still collects stderr exactly as before, so error messages, output limits, timeouts and exit handling are unchanged. If the observer throws, the runner catches it, logs once and detaches it, so progress reporting can never fail a create. Asking for an observer together with the termination-barrier mode, which doesn't support it, fails before the command is queued instead of being silently ignored.
  • A reader for Git's progress lines (src/shared/git-progress-records.ts). It splits on \r and \n, keeps a bounded tail of an unfinished line, handles lines split across reads, and handles the narrow-terminal layout where Git prints the title on its own line.
  • Checkout policy (src/main/git/worktree-checkout-progress.ts). It reports increases only, which drops the one same-percentage line Git reprints after each one-second tick. Every increase is reported as soon as Git prints it, so a checkout produces at most about 100 reports. There is no timer, and reporting stops when Git reports done or the command settles, so nothing can arrive after a failure.
  • Delivery: the local create attaches the reader to its git worktree add calls only when a pending card is waiting for it. The result travels on the existing createWorktree:progress event as one new optional field, checkout (null means done); no new channel. The renderer shows the bar only while the create's status and phase are both "creating", and Retry and Continue clear it.
  • UI: the existing Progress component at the slim h-1.5 height already used by the update card, labelled by the status text. The new label and the create's five existing status labels go through translate(), with entries in all six locale catalogs, so the label never switches language partway through a create.

Why

  • Why read what Git already prints instead of asking for more. It costs the checkout nothing: no extra Git work, no new flag that an older Git might reject, no environment change, no capability probe. Git 2.25 already behaves this way.
  • Why an observer on the shared runner instead of a separate spawn for worktree add. The create keeps the runner's queueing, WSL routing, timeouts, process cleanup, tracing and error text. A separate spawn path would have to rebuild all of that.
  • Why parse in the main process, with no time-based limit. The renderer receives at most about 100 small messages per checkout instead of raw stderr. Git's own output is already bounded, so a time-based limit on top would only add a way to lag behind Git.

Not in this PR

  • SSH repos, and creates from the CLI, automations and a paired remote server. On current main an SSH repo is served by an Orca server on that host, and these creates all go through the runtime create path. That path emits no phase events and has no pending card in the renderer to update; it only sends a "created" event once the create finishes. Adding a meter there means a new optional field on what the server publishes, which needs its own change with mixed-version clients in mind.
  • Prepared spare checkouts. Reusing one moves an already checked-out directory into place, so there is no git worktree add meter to show. Two waits on that path still show only "Creating worktree…": waiting for a spare that is still being checked out, and moving the spare to a newer base commit (git reset --hard).
  • Sparse checkouts. They run worktree add --no-checkout, then a git checkout that prints no progress into a pipe unless given --progress. Changing that command is out of scope, and sparse checkouts are small by design.

Where this fits

On 2026-09-28, creating a worktree took 80–268 s instead of 5–15 s, mostly because a create waited on an unfinished spare checkout while Orca's own background Git competed for the disk.
This PR doesn't fix that wait; it only makes a create's own checkout visible.
It lands on its own on main and doesn't depend on the other slow-create PRs (#23699, #24085, #22356).

Differences from the common pattern

This matches the common pattern for checkout progress: it reads Git's own "Updating files: N% (x/y)" meter from the stderr of the existing git worktree add, treats \r as a line break, hooks the reader into the shared Git runner while stderr is still captured for error messages, sends every change with no time-based limit as one more field on the create's existing progress channel, and shows the percentage as text.

  • Intended: Git's progress delay is left at its default and no per-command locale is set. The common pattern forces the delay to 0 so its meter starts at 0%. Orca's meter starts about a second into the checkout, with "Creating worktree…" until then. Safe because the create's Git command and environment stay exactly as before, checkouts under a second never flash a bar, and Orca's shared Git runner already forces English output for every Git command.
  • Intended: the checkout ends when Git prints its own "done" line, not when the command returns. Safe because Git ends every meter it showed with that line once the checkout completes; if the command fails first, reporting stops when it settles and the error card never shows the bar.
  • Intended: only increases are reported, which drops the one same-percentage line Git reprints after each one-second tick. Safe because a single Git meter never goes down.
  • Intended: the reader also understands the layout Git uses when its line is wider than the terminal width it sees (title on its own line, counters on the next). It comes from Git's source; it costs one flag in the reader.
  • Intended: the panel shows a thin determinate progress bar under the label; the sidebar row shows the same text without a bar. Safe because it is the existing progress component at the slim height already used by the update card.
  • Intended: after the checkout finishes, the label returns to "Creating worktree…" instead of a finished row with the file count. Orca's card has a single status line, so there is no row to keep.
  • Intended: progress travels as small updates on an existing desktop-only event, one per percentage increase. Safe because the main process and the window ship together and can't disconnect from each other, and web and mobile clients never receive this event.
  • Intended: every create status label is translated, so the label never switches language partway through a create.
  • Intended: a create that reuses a ready spare checkout shows no meter. Safe because a ready spare is already checked out: the create only moves it into place, and a create that can't use the spare falls back to a normal add, which shows the meter.
  • Temporary: a create waiting on a spare that is still being checked out, or on a spare being reset to a newer commit, shows no meter. Follow-up not yet filed: either pass the spare's checkout meter to the create that claims it, or, if the re-cut of fix(worktree): a create does one fetch and one checkout, and background work waits for it #23699 stops creates from waiting on unfinished spares, there is nothing left to do.
  • Temporary: SSH repos and runtime creates (CLI, automations, paired servers) show no checkout meter. The common pattern runs Git on the machine that owns the repo and streams progress to whichever client is attached. Follow-up not yet filed: give the runtime create path phase events first, then the meter as an optional field.
  • Temporary: LFS's later "Filtering content" stage isn't shown; the card says "Creating worktree…" during it, which is accurate. Follow-up: the reader already takes the meter's title as a parameter, so a second stage is a small change.

Linked Issue

No separate issue; this was listed as deferred work in #23699 and lands independently on main.

Visual Proof

Electron QA on head 7e54872 on a separate Mac (the M4Air), in a throwaway app profile and home, with no credentials. Grok drove the app over the Chrome DevTools protocol, and every create used a blank terminal. The fixture was a ~30k-file repo where 300 files go through a slow checkout filter, so a cold checkout takes several seconds. Each create was matched to its trace, which records whether it reused a prepared spare checkout or ran its own git worktree add.

Checking out files… 19%: the panel label with the progress bar, and the sidebar row with the same text
A create that ran its own checkout (trace: no spare available, git worktree add 14.5 s): the panel shows "Checking out files… 19%" with the bar, and the sidebar row shows the same text at its usual height.

Checking out files… 46%: the bar has moved on
The same create at 46%. Across the run the percentage only went up, from 9% to 99%. Then the bar went away, the label went back to "Creating worktree…", and the terminal opened.

The new worktree open in its terminal, with no bar left behind
The worktree opened in its terminal, with no leftover bar or percentage.

  • Cold create completes with the meter: PASS. It was confirmed on three creates across two app launches: each one ran its own git worktree add (6 s, 14 s and 40 s), the meter rose with no step backwards, and each worktree opened.
  • Create that reuses a prepared spare: PASS. Six creates reused a spare, in three repos (two of them waited 29 s and 63 s for the spare to finish). Each one showed "Creating worktree…" with no bar, no percentage and no error, and opened.
  • Folder workspace: PASS. It opened with no bar, no "Checking out files" text and no error.
  • Small repo (10 files): PASS. It opened with no bar.
  • Console: no renderer errors on the cold-create runs. The only main-process error lines were port scans timing out while the machine was busy, which is unrelated.
  • A checkout slower than three minutes (an earlier pass with a far slower filter, on a heavily loaded machine): the meter rose 0–6%, then Git hit Orca's existing 3-minute git worktree add limit and the create failed. The error card showed no leftover bar or percentage. That limit is on main and this PR doesn't change it.
  • Isolation: the real Claude and Codex config files had the same hashes before and after the final pass.

Testing

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

  • Real Git binaries: a case in src/shared/git-binary-compatibility.test.ts, which CI runs against Git 2.25.5, 2.38.1 and 2.49.1. It checks that a piped worktree add writes records the reader parses, ending in "done".

  • src/shared/git-progress-records.test.ts uses the exact bytes captured from Git 2.25.5, including the narrow-terminal layout, re-splits each capture at every byte offset, ignores other stderr, and keeps a line that never ends bounded.

  • src/main/git/worktree-checkout-progress-real-git.test.ts runs addWorktree against real Git: the meter rises through 100% and then reports done; a failing add produces the byte-identical error and stderr with or without the observer; a throwing listener doesn't fail the create.

  • src/main/ipc/worktrees-create-event-timing.test.ts: the local create forwards Git's meter on createWorktree:progress to the pending create it belongs to (fails if the wiring in worktree-remote.ts is removed).

  • WorktreeCreationPanel.test.tsx: the bar's value and label while checking out; no bar without a meter or on a failed create.

  • After the refresh: those files plus the worktree add suites, the pending-create and create-flow suites, and the runner admission suite pass locally (macOS); CI ran lint, typecheck and the full test shards on head 7e54872.

  • Platforms: macOS locally and on the QA machine; Linux and Windows through CI. Windows' meter is covered by reading Git for Windows' source; WSL wasn't run.

Review

A fresh reviewer re-checked the merge result against the approved version: the production diff is unchanged, main's runner changes are intact, the observer still reaches the real Git process on every local worktree add route, no new create path was missed, and no spare-checkout path can report a meter. One suggestion (pin the path from Git's meter to the card's event) was taken.

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

  • Security: no new input surface. The reader parses Git's own stderr, and only numbers leave the main process.
  • Cross-platform: the meter is printed into a pipe on macOS, Linux and Windows; carriage-return plus newline endings are handled; if nothing is printed (for example behind wsl.exe), the card falls back to today's label.
  • SSH and remote: unchanged; see "Not in this PR".
  • Mobile and web clients: they never receive this desktop-only event, and the new field is optional.
  • Performance: string parsing of a few KB per create, and at most about 100 small messages to the renderer.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

@brennanb2025

brennanb2025 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor Author

Review status: ready for review (head 3607360)

The problem. Creating a worktree in a large repo spends most of its time in the file checkout that git worktree add performs. That can be 5-15 s on a repo the size of Orca's (~30k files), and minutes when the disk is busy. For that whole time the sidebar row and the creation panel said only "Creating worktree…" with a spinner, so there was no way to tell whether the create was moving, stuck, or nearly done.

What changes for the user. For a local create whose checkout lasts more than about a second, the panel now reads "Checking out files… 23%" with a thin progress bar under it, and the sidebar row shows the same text (the row doesn't change height). When git finishes writing files, the bar goes away and the label returns to "Creating worktree…" for the last few steps. Fast checkouts, sparse creates, SSH and CLI/automation creates, and folder workspaces look the same as before. In a non-English Orca, every status line on the create card is now translated, so the label never switches language partway through a create.

Create at 23%: panel label with the progress bar; the sidebar row shows the same text

Fixed during review

  • A CI blocker: four new type casts in a test file failed the changed-lines quality check, which also stopped the unit test job from running. They now use the typed form.
  • The bar could fall behind git: a 100 ms rate limit dropped progress updates and never sent them later, so a checkout that stalled on a large file could show 40% while git had already reached 60%. The rate limit is gone. Every percent increase git prints is now reported; git itself prints only when the percent changes, so a checkout sends about 100 updates.
  • Language switching mid-create: only the new "Checking out files…" label was translated, so a Japanese user saw English, then Japanese, then English again. The five other create status labels ("Fetching base branch…", "Creating worktree…", and the rest) are now translated in all six languages.
  • Test coverage for the key promise that watching git's output never changes an error: a real-git test now makes git print progress and then fail on the last file, and checks that the error carries exactly the bytes the progress reader saw and matches a run without the reader. It is written so git's one-second timer can't make it flaky.
  • A code comment that misdescribed how often git reprints progress.

Deferred (low priority, not blocking)

  • The worktree jump palette rebuilds its list on each progress update while it is open (about 100 times per checkout). Measured as harmless; the sidebar and panel don't have this.
  • The progress reader handles one title at a time and only recognises git's final "done" in the checkout format. Adopting it for clone progress later needs a small extension.
  • If a later change adds a progress stage for large-file (LFS) filtering, the progress fields will need to be tagged by step.
  • One half of a panel test ("no bar after a failure") would pass without the change; the rule it checks is proven by another test.
  • The elapsed clock next to the label shifts sideways when the label changes, as it already does on other label changes.
  • Passing the new stderr listener together with raw-bytes output decodes each chunk on its own instead of being refused. No caller does this.
  • Two issues that existed before this PR, found during QA and left for follow-ups: a failed create's error card includes git's whole raw "Updating files: N% …" progress dump (the base branch shows the same dump), and cancelling a create hides the card but doesn't stop git, so the worktree still appears later.

What was verified

  • Three independent reviews (main-process git code, renderer and UI, overall design) plus a focused review of the fixes and a final readiness pass. The design was kept as is: the git worktree add command line and environment are unchanged, and the create only reads progress git was already writing into Orca's pipe. No extra git work.
  • CI: all checks passed at 4719ccc (27 pass, 0 fail), including all 8 unit test shards, the six-platform persistence jobs, the Windows package, and the Git compatibility job covering the progress output at Git 2.25.5 and 2.49.1. After merging the updated base branch (now head 3607360, base 96bd7f3), CI passed again: 21 pass, 0 fail, including all unit test shards, Git compatibility and the Windows package.
  • Live QA of a build of 4719ccc on a separate Mac, in an isolated app profile (the later base merge changed none of this PR's files):
    • A slow ~30k-file checkout climbed 1% → 99% one step at a time, then cleared and handed off to the terminal. The sidebar row stayed 48 px tall throughout.
    • The plain ~30k-file repo showed the bar for about 3 s. A 10-file repo and a sparse create never showed a bar.
    • A checkout that fails partway showed an error card with no leftover bar, and Retry started clean.
    • Two creates at once, in different repos and in the same repo, each kept their own percentage (314 samples, no mix-ups).
    • Cancelling mid-checkout made the card go away for good.
    • In Japanese, every label in the sequence was Japanese.
    • About one store update per percent; no timer delays above 360 ms.

Error card after a checkout that failed partway: no progress bar is left behind
Two creates in the same repo, each row showing its own percentage
Japanese: the panel and sidebar row read ファイルをチェックアウト中… 21%

Not verified

  • Windows and Linux were not run live. On Windows, the package build and the persistence jobs passed; the unit test shards run on Linux.
  • The real-git progress test runs in CI only on Linux, not on Windows or Git 2.25; the Git compatibility job covers the progress output itself on 2.25.
  • WSL-hosted repos weren't run live. If git prints nothing there, the card keeps today's "Creating worktree…" label.
  • SSH, CLI and folder-workspace creates weren't run live. They are unchanged by design and show no bar.
  • The brief "Creating worktree…" moment after the checkout ends and the ~3 s bar on the plain big repo were captured only by an in-page sampler, not in screenshots.
  • No React profiler trace; render cost is from update counts and timer gaps.

@brennanb2025
brennanb2025 marked this pull request as ready for review September 30, 2026 11:10
@greptile-apps

greptile-apps Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

[Medium risk] Adds checkout progress reporting to worktree creation.

The PR is not ready to merge because the new prepared-worktree test fails deterministically.

Findings

  1. P1 Reset assertion always fails ▶

Summary

The PR reads Git’s checkout meter during local worktree creation and shows it in the pending-create UI.

  • Adds a passive stderr observer, progress parser, and create-progress event field.
  • Shows a labeled progress bar and translates creation status labels.
  • Adds parser, Git compatibility, IPC, and renderer tests.
Diagram
sequenceDiagram
  participant Git
  participant Main
  participant Renderer
  Git-->>Main: worktree add stderr meter
  Main-->>Renderer: createWorktree:progress with checkout
  Renderer->>Renderer: update label and progress bar
  Git-->>Main: checkout done
  Main-->>Renderer: checkout null
Loading

Reviews (7) · Last reviewed commit: "test(worktree): pin that finalizing a pr..."

@pullfrog pullfrog Bot left a comment

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.

✅ No new issues found.

Reviewed changes

  • Passive git stderr observer — GitExecOptions.onStderr is added on the shared runner as a second, passive listener on the execFile stderr stream; execFileCaptureToTermination omits it and gitExecFileAsync rejects the onStderr + terminationBarrier combination up front, so capture, errors, limits, and timeout handling are unchanged.
  • Progress-record reader — src/shared/git-progress-records.ts parses Title: NN% (x/y) records across chunk boundaries, \r/\n/\r\n redraws, the narrow-COLUMNS title-on-its-own-line layout, and a bounded unfinished-line tail.
  • Checkout policy — worktree-checkout-progress.ts reports increases only and closes on the , done. record; worktree-add.ts wires it to git worktree add only when a listener is supplied and the add is not --no-checkout, closing it once the process settles.
  • Delivery — the local create attaches the reader only when args.creationId is set; the meter rides the existing createWorktree:progress event as an optional checkout field (null = done), and the renderer bridge stores it or clears it on every event.
  • UI and i18n — the create panel shows a Progress bar labelled by the status line (aria-labelledby); all six create-phase labels now go through translate(), with entries added to all six locale catalogs, and Retry/Continue clear the meter.

I read the complete diff, traced the main-to-renderer state path (including the hasChange no-op merge and the status === 'creating' && phase === 'creating' gate that hides a meter left from a failed or earlier phase), and ran the touched suites locally — the progress parser, checkout policy, IPC forwarding, bridge, panel, and real-git tests all pass. The documented exclusions (SSH, CLI/runtime, sparse, LFS filtering) are deliberate and correctly fenced by noCheckout/creationId.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

A local create spends most of its time in the checkout `git worktree add`
performs, and the card only said "Creating worktree…" for that whole time.
Git already writes its "Updating files: N%" meter into our stderr pipe, so
the add call reads it passively (same command line and environment) and the
create card shows "Checking out files… N%" with a thin bar. All six create
labels are translated so a create never switches language mid-flight.

Rebuilt on main from the version stacked on the create-gating branch. On
main a create can also claim a prepared checkout; that path never runs
`git worktree add`, so it keeps today's "Creating worktree…" label with no
bar, and a missed claim falls back to the plain add, which shows the bar.
@brennanb2025
brennanb2025 force-pushed the brennanb2025/create-checkout-progress branch from 3607360 to 1e5b7ce Compare October 2, 2026 01:10
@brennanb2025
brennanb2025 requested a review from Jinwoo-H as a code owner October 2, 2026 01:10
@brennanb2025
brennanb2025 changed the base branch from brennanb2025/create-scan-idle-gate to main October 2, 2026 01:10
@greptile-apps

greptile-apps Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Comments Outside Diff

These findings could not be posted inline.

  • P1 Rollback skips the health window .github/workflows/cloud-deploy-relay-production-same-cap-job.yml:483 ▶

    A same-cap rollback can isolate and drain a cell, but this pre-drain health window runs only for apply. The change also removes the required 15-minute aggregate monitor check. Rollback therefore proceeds after a single live health reading even if a recent cell crash or spike in director 503 responses has only briefly subsided, risking another disruption as hosts are moved.

@coderabbitai

coderabbitai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 030694b9-e3a8-45c0-b96a-98f225ab18fe

📥 Commits

Reviewing files that changed from the base of the PR and between 1e5b7ce and cccd58a.

📒 Files selected for processing (1)
  • src/main/git/worktree-preparation-base-oid.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.

📝 Walkthrough

The change adds Git stderr parsing for worktree checkout progress and forwards progress events for local worktree creation. The renderer stores the progress, displays it during active checkout, and clears it when creation restarts. Progress labels are added to six locales. Tests cover parsing, Git execution, event delivery, and UI rendering.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to cccd5

Prepared-worktree finalization remains outside checkout-progress reporting, while ordinary local checkout progress is covered by the supplied tests. No concrete merge-blocking risk is established.

### Architecture Summary

Architecture risk: 🔵 Low · up to cccd5

The change affects 1 system.

Changed systems: src

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — src (service) was modified; 32 changed files map to changed impact.

Before / after behavior

  • observed — Modified behavior in src/main/git/command-runner/exec-file-capture.ts: ExecFileCaptureOptions retains onStderr, but execFileCaptureToTermination now omits it from its accepted options type; the function’s implementation comment states that runProcess owns the child streams and git-exec-file refuses onStderr with a termination barrier.
  • observed — Modified behavior in src/main/git/command-runner/exec-file-capture.ts: Added observeStderr, which registers a passive data listener, converts Buffer chunks to UTF-8 strings, and calls the observer. If the observer throws, it removes its listener and warns rather than propagating the exception.
  • observed — Modified behavior in src/main/git/command-runner/exec-file-capture.ts: execFileCapture now installs the stderr observer on the spawned child when options.onStderr is provided.
  • observed — Modified behavior in src/main/git/command-runner/git-exec-file.ts: gitExecFileAsyncUnlocked now throws before admission when both onStderr and terminationBarrier are set. Previously, it had no such check.
Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 43.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 30 functions across 26 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Title check Passed The title clearly and concisely describes the main change: showing checkout progress during worktree creation.
Description check Passed The description is detailed and covers the user impact, implementation, rationale, testing, visual proof, platform considerations, limitations, and checklist. The Linked Issue field is not populated w…
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.

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.

…eckout progress

Claiming a prepared checkout never runs `git worktree add`, so the create
card keeps its label with no bar; this pins that at the finalize step,
including the retarget `reset --hard`.
@brennanb2025

Copy link
Copy Markdown
Contributor Author

Moved onto main (head cccd58a). #23699 is parked, so this PR no longer depends on it; it now targets main and lands on its own.

What the user sees: the same as before the move. A local create whose checkout takes more than about a second shows "Checking out files… N%" with a thin bar; SSH, CLI/runtime, sparse and folder-workspace creates are unchanged.

One thing that is different on main: main still has the prepared spare checkout, which #23699 would have removed. Opening the composer on a local repo starts checking out a spare in the background, and a create on that base usually reuses it. Reusing a spare runs no git worktree add, so those creates keep today's "Creating worktree…" label with no bar. Creates that do their own checkout (no matching spare, an existing branch, or a spare that fails and falls back) show the bar. Waiting on a spare that is still being checked out shows no bar either; that is listed as a Temporary difference in the description.

How it was moved:

  • The PR's own changes were rebuilt as one commit on main. The production code is line-for-line the same as the stacked version, apart from one comment. Conflicts were textual only: a neighbouring option and import already on main, a neighbouring test, and the six translation catalogs (merged as JSON).
  • Nothing the PR used came only from fix(worktree): a create does one fetch and one checkout, and background work waits for it #23699.
  • Two tests were added for the spare path: the create sends no checkout meter when it reuses a spare, and finalizing a spare (including its reset to a newer commit) gives no Git command a progress reader. The second test fails if a reader is added there.

Checks: tsc for node and web; the PR's tests plus the runtime, local create, spare-checkout and worktree add suites (21 files, 1516 passed; the real-Git-binary suite runs only in CI's Git matrix); oxlint; changed-code quality gate. pnpm-lock.yaml is untouched. A fresh review of the move found no behaviour change. Electron QA was not re-run: the create card code is unchanged, and the spare behaviour is covered by the tests above.

Comment thread src/main/git/worktree-preparation-base-oid.test.ts Outdated

@pullfrog pullfrog Bot left a comment

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.

✅ No new issues found.

Reviewed changes

  • Regression test for prepared-checkout finalize — worktree-preparation-base-oid.test.ts gains a test that passes onCheckoutProgress into finalizePreparedWorktree on the retarget path and pins that claiming a prepared checkout reports no meter: no gitExec call carries onStderr and the listener is never invoked.

This increment is test-only. I ran the file (6/6 pass) and pnpm tc:node (clean).

One note: Greptile's P1 at line 117 is a false positive. The refs/heads/main base resolves targetHead to the refreshed oid while the prepared HEAD probe resolves to the original, so the retarget reset does run and the expect(...reset...).toBe(true) assertion holds — verified by the passing run.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

# Conflicts:
#	src/main/git/command-runner/git-exec-file.ts
#	src/main/git/worktree-add.ts
#	src/preload/api/worktrees-bridge.ts
#	src/renderer/src/i18n/locales/en.json
#	src/renderer/src/i18n/locales/es.json
#	src/renderer/src/i18n/locales/fr.json
#	src/renderer/src/i18n/locales/ja.json
#	src/renderer/src/i18n/locales/ko.json
#	src/renderer/src/i18n/locales/zh.json
…ract

Drops unit tests that mirror the implementation; the real-git flow, the parser
captures, the cross-version Git contract and the create card test remain.
@brennanb2025
brennanb2025 merged commit 131986a into main Oct 16, 2026
32 checks passed
@brennanb2025
brennanb2025 deleted the brennanb2025/create-checkout-progress branch October 16, 2026 01:15
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.

1 participant