d on an empty worktree band with a pull request deletes the worktree, and its right-click opens the worktree's menu - #105
Merged
Conversation
…worktree, and its right-click opens the worktree's menu - An empty band's only row can be its checkout's detected pull request, a link row the grid draws on the band's rule rather than as a card. The cursor rested on it, so d flashed "the pull request link can't be deleted — it comes from git" and the right-click opened the link's menu instead of the worktree's. - empty_band now looks past link rows, and d and the row menu ask it before matching the row under the cursor. - Regression test covers d, a right-click on the band and a right-click on the #N on its rule. Closes #104 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #104.
don an empty worktree band whose branch has a detected pull request refused with "the pull request link can't be deleted", and the right-click opened the pull request's menu. Now both reach the worktree's Delete worktree confirm, as the band's hint says.Contents: 🐛 Symptom · 🔍 Cause · ✅ Fix · 📸 Before / After · 🔁 Flow ·⚠️ Risk · 🔧 Technical overview · 🧪 Proof · 📝 Notes
🐛 Symptom
With Show all worktrees on, a checkout with nothing running is an EMPTY BAND whose hint reads
d: delete worktree. When that checkout's branch has a pull request,donly flashedthe pull request link can't be deleted — it comes from git, and no confirm opened. The worktree could not be deleted from its band while the pull request was detected. Reported on v0.40.0.🔍 Cause
A band's cards are its sessions and terminals only, so the band counts as empty and draws the delete hint. The checkout's row list also carries its detected pull request as a link row, though, and the cursor rests on it. The
dhandler and the right-click menu matched the row under the cursor first: the link row took the "delete this link" path, and the empty-band branch after it never ran. The empty-band test fixture had no pull request, so the test never saw a link row under the cursor.✅ Fix
ddeletes the worktreeDelete worktree '<branch>' from disk?↗ #Non its ruledand the right-click still act on the card under the cursor↗ #N, or⇧Vcannot delete the main checkout, as it did without a pull request📸 Before / After
Captured with the SCREENSHOT HARNESS: a click on
feature-x's empty band (draft PR #39 on its branch), thend.🔁 Flow
flowchart TD K["d, or a right-click, on the grid"] --> E{"empty_band: is the band under the cursor card-less?"} E -- "yes, even with the PR's link row selected" --> W["Delete worktree confirm / worktree menu"] E -- "no" --> R{"row under the cursor"} R -- "session" --> A["Delete agent"] R -- "terminal" --> T["Close terminal"] R -- "saved link" --> L["Delete link"] R -- "detected PR" --> F["flash: can't be deleted"] B["before: the row was matched first"] -. "PR link row on an empty band" .-> F classDef fixed fill:#1f6f3f,color:#fff; classDef bug fill:#7a1f1f,color:#fff; class W fixed; class B bug;Verdict: 🟢 Low risk. The change reorders two existing branches in the TUI's key and menu handlers, and a confirm still stands before any delete.
dpress or a right-click only. On a card the check stops at the selected row, as before. Only a link row or no row builds the band listempty_bandhelper for both the key and the menu (INPUT PARITY), and adds a regression test beside the empty-band tests already thereRollback:
git revertof the merge restores the old order. There's no protocol or store change to undo.🔧 Technical overview
crates/nebula-tui/src/event_loop/launcher.rs—empty_bandreturnedNonewhenever any row was selected. It now returnsNoneonly for a row with a card behind it (SessionRow::sref()isSome: a session or a terminal), so a link row no longer hides an empty band.crates/nebula-tui/src/event_loop.rs—open_delete_confirmandcontext_menu_itemsaskempty_bandfirst, under the SESSIONS focus, and fall back to matching the selected row. The link arm stays for a band that has cards.visible_session_rowsis shared with the panel-era code paths, and about 100 tests pin it. Deciding at the two entry points that act on the band is the smaller change.🧪 Proof
an_empty_band_on_a_pull_request_still_deletes_the_worktreeincrates/nebula-tui/src/event_loop/launcher.rsputs a detected pull request on the empty band's checkout and asserts that the link row is under the cursor. It then checks thatd, a right-click on the band, and a right-click on the↗ #7each lead to the worktree's confirm. It fails onorigin/main(no overlay; the flash instead) and passes here.origin/mainshows the flash, and this branch shows the confirm (the screenshots above).make ci:cargo fmt --checkand clippy are clean.cargo test --workspace --no-fail-fastgives 1657 passed, 2 failed. The two failures aree2e_tui'snebula_open_from_inside_a_session_raises_the_file_tabsandtui_drag_past_the_pane_top_autoscrolls_and_copies_the_run, which already fail onmainwithout this change. This diff touches neither.📝 Notes
v0.40.1(0aa19b2). It merges cleanly intomain.↗ #Ncomes from the project's open-PR list before the checkout's own lookup adds its link row. A scene that depends on that row needs a pause (SHOT_KEY_SECS=3) before the key, or it tests the old no-row path.🤖 Generated with Claude Code