Skip to content

fix(app): archiving a worktree no longer holds its dialog open (BRA-2199) - #175

Open
Stener1 wants to merge 1 commit into
cosscom:mainfrom
Stener1:bra-2199-archive-in-background
Open

Stener1 wants to merge 1 commit into
cosscom:mainfrom
Stener1:bra-2199-archive-in-background

Conversation

@Stener1

@Stener1 Stener1 commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Archive… held its confirm dialog open with a spinner until the box answered. For a repo with no archive script, the box removes the worktree before it answers (dropWorktree: stop services, git worktree remove, stop sessions), and for a monorepo checkout with node_modules that takes 5 to 30 seconds or more. Archiving several finished worktrees in a row meant waiting on each one.

Archive… still asks first, but pressing Archive now closes the dialog at once. The worktree shows Archiving… right away and goes when its box gets to it. It uses the same per-box queue that Remove worktree already uses, one removal at a time per box.

  • lib/remove-worktree.ts: queueRemoval now takes the kind ("archive" | "remove"). For an archive it gives today's toasts:

    • Archived NAME / "Branch … is kept." when there is no script.
    • Archiving NAME / "Its archive script is running…" when there is a script. Archived NAME follows when worktree.removed arrives, as before.
    • A warning, Couldn't archive NAME / "NAME has uncommitted changes, so it was left as it is. Commit them first, or use Remove worktree to discard them."

    keepsWork is the one copy of git's "it would lose work" check. It is shared with use-bulk.ts.

  • lib/removing.ts: inTurn(box, job) is the per-box line, built on the existing oneAtATime. It replaces the queue's hand-rolled waiting/drain.

  • components/sidebar/actions.tsx: archiveWorktree's run just queues. The sidebar's ⋯ and right-click, zen's worktree menu and the launcher's "Archive this worktree…" all go through it.

  • views/worktrees/use-bulk.ts: bulk Archive skips a worktree that is already on its way out, so its box never gets a second DELETE for it. Codex's adversarial review raised this.

  • lib/mock.ts: ?mock=1&slowremove=MS makes a mock box take that long to remove a worktree with no archive script, answering once it is gone.

One behaviour change: an error is now a toast instead of text inside the dialog, so the dialog no longer offers a retry. Archive… can be pressed again.

Not changed: bulk Archive N… in the Worktrees table (archive-dialog.tsx). Its dialog stays open on purpose, showing each row's outcome, so it still waits on each box. Moving it onto the queue would be a redesign of that dialog, so it is left for a separate change.

Evidence

Driven with the verify skill's new worktree-archive scenario: the production build on the mock fixtures with slowremove=4000 and the list sidebar, in Chromium. It right-clicks a row, chooses Archive…, presses Archive, and times how long the dialog takes to close.

Before (origin/main app code, same slow mock): the dialog spun for 4638 ms, the full length of the box's removal.

Before: the dialog spins while the box removes the worktree

After: the dialog closed in 149–308 ms, which is its close animation, across four archives.

Archive pressed on gpu/ci-flake, then gpu/judge-v2 at once: both marked, the dialog gone ~4.2 s later gpu answers: Archived ci-flake, judge-v2 still waits its turn
Both rows say Archiving… Archived ci-flake toast
Archive script (devl/qa-deck, pnpm db:drop) Uncommitted work (devl/checkout-fix): kept, with a warning
Archiving qa-deck toast Couldn't archive checkout-fix toast

The scenario's steps:

- the dialog closed 149 ms after Archive was pressed        (gpu/ci-flake, no script)
- the dialog closed 276 ms after Archive was pressed        (gpu/judge-v2, queued behind it)
- Archived ci-flake toast 4239 ms after Archive
- Archived judge-v2 toast 8663 ms after the first Archive   (one at a time on gpu)
- the dialog closed 295 ms after Archive was pressed        (devl/qa-deck, archive script)
- the dialog closed 308 ms after Archive was pressed        (devl/checkout-fix, uncommitted)
OK

The mock can't show a real box's teardown time. The fix is app-side and doesn't depend on it.

Checks: pnpm typecheck:plugins, check:titles, check:type, check:grid, check:csp, check:themes, pnpm test (565 pass), npx tsc -p e2e, pnpm build, and (cd docs-site && pnpm build) all pass. In the browser, e2e/worktree-remove.spec.ts passes, including a new test: Archive with slowremove, the dialog hidden within 1 s, Archiving…, the toast, and the dirty case. e2e/publish-failed.spec.ts passes too. There is no Go change.

Unit tests: removing.test.ts checks that a box takes its removals one at a time and that another box's don't wait.

The verify skill now has features/worktree-archive.md, a row in features/README.md, and scripts/scenarios/worktree-archive.mjs. There is also a changelog bullet under Unreleased.

Worth a separate fix: why the box is slow

Without an archive script, dropWorktree calls Locations.RemoveWorktree, which runs git worktree remove. git deletes the folder itself, one file at a time, before the HTTP answer goes back, and a node_modules tree has hundreds of thousands of files. The box could instead rename the folder aside on the same filesystem, run git worktree prune, answer and publish worktree.removed, and delete the renamed folder in the background. Removals would then be quick everywhere, the Worktrees table's bulk Archive and the CLI included.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Oct 21, 2026

Copy link
Copy Markdown

@Stener1 is attempting to deploy a commit to the seanbrydonio's projects Team on Vercel.

A member of the Team first needs to authorize it.

…199)

Archive… still asks, but pressing Archive closes the dialog at once. The
worktree shows Archiving… and goes when its box gets to it, through the
same per-box queue Remove worktree uses, now carrying the kind. The
toasts are today's: Archived (branch kept), Archiving (its script is
running), and a warning for uncommitted work.

Bulk archive in the Worktrees table skips a worktree already on its way
out, so its box never gets a second request for it. The mock takes
?slowremove=MS to make a box slow to remove a worktree, and the verify
skill gains a worktree-archive scenario and feature file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Stener1
Stener1 force-pushed the bra-2199-archive-in-background branch from 6e65e87 to a13428b Compare October 23, 2026 23:05

This branch has not been deployed

No deployments
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