Skip to content

feat(review): auto-recover review-window panes when their process exits - #569

Merged
jlong merged 1 commit into
mainfrom
jlong/tui-reload-review-window-panes-when-they-exit-vim-diff-chat-nav-defaulting-the-mid-view-back-to-chat
Aug 15, 2026
Merged

feat(review): auto-recover review-window panes when their process exits#569
jlong merged 1 commit into
mainfrom
jlong/tui-reload-review-window-panes-when-they-exit-vim-diff-chat-nav-defaulting-the-mid-view-back-to-chat

Conversation

@jlong

@jlong jlong commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Task

The review window is composed of panes (a navigation sidebar plus a "mid" view that can be Chat / Diff / Edit-in-Vim / Browser). Each content pane runs an exec'd process (exec $EDITOR, exec git difftool, …) so the pane dies when that process exits. Today, when a pane's process quits, the review window is left with a dead/empty pane instead of recovering — the user has to leave and reload the whole task.

We want the review window to detect any of its panes exiting and recover automatically, so quitting a tool never leaves a broken window.

Current Behavior

  • Open Edit in Vim in the review window, then :q out of Vim → the editor pane is now dead/empty. Nothing switches the view or rebuilds the pane; the review window is left in a broken state.
  • The same is true for the other panes: if the diff pane's git difftool exits, the chat pane's process exits, or the navigation pane dies, the window is left with a dead pane and no recovery.

Expected Behavior

  • Mid-view content pane exits (e.g. Vim closed with :q, difftool exits): detect the dead pane and switch the mid view back to Review chat (the default view). The window is never left showing a dead pane.
  • Re-selecting that view from the navigation reloads it: after Vim (or Diff, etc.) was closed and we fell back to Chat, choosing "Edit in Vim" / "View Diff" again from the nav must rebuild the pane fresh (a new exec'd process), not try to re-focus the dead one. The existing reuse guard should treat a dead pane as absent so the view is recreated on demand.
  • This applies to every pane in the review window, including the navigation pane: if any pane quits, it is reloaded. If the navigation (sidebar) pane itself dies, it is rebuilt so the window stays usable.
  • Recovery is prompt (detected on the review UI's normal poll tick, same cadence the sidebar already uses to poll liveness) and idempotent (a live pane is never rebuilt or double-switched).

Technical Details

  • Review-window panes are created and tracked in crates/shelbi-orchestrator/src/review_ui.rs, keyed by tmux session vars (MID_KEY, PANEL_KEY, EDITOR_KEY, DIFF_KEY, CHAT_KEY, TASK_KEY). The ensure_*_pane helpers already reuse an existing pane id via read_session_var; extend that so a dead pane id (tmux reports the pane no longer alive) is treated as absent and recreated, rather than reused.
  • Pane liveness can be checked the same way the workspace supervisor does (query tmux for the pane / pane_alive); the sidebar/review loop already runs a poll tick (poll_review_load, and now poll_active_window) where a poll_review_panes (or equivalent) check fits.
  • The mid-view state lives in the review panel (crates/shelbi-tui/src/review_panel.rs, ActiveView / PanelEffect). Falling back to Chat on a dead mid pane should reuse the existing view-switch path (PanelEffect::ShowChat / the Chat activate_row) so it converges with the click path, mirroring the window-switch convergence just shipped.
  • Distinguish an intentional teardown (leaving the review, FocusDashboard) from an in-place pane death so recovery only fires while the review window is still the active context.

Acceptance Criteria

  • Quitting Vim (:q) in the review window auto-switches the mid view to Review chat; no dead/empty pane remains.
  • After that fallback, selecting "Edit in Vim" again from the nav rebuilds the editor pane fresh (new process), not a re-focus of the dead pane.
  • The same detect-and-reload behavior holds for the Diff pane and the Chat pane when their processes exit.
  • If the navigation pane exits, it is rebuilt so the review window stays usable.
  • Recovery fires on the normal review poll tick and is idempotent: a live pane is never rebuilt or the view double-switched.

Auto-opened by Shelbi — review at: /Users/jlong/.shelbi/projects/shelbi/tasks/tui-reload-review-window-panes-when-they-exit-vim-diff-chat-nav-defaulting-the-mid-view-back-to-chat.md

The review window's content panes each `exec` a process (editor, git
difftool, review agent) so the pane dies when that process exits. Quitting
Vim with `:q` (or the difftool exiting) used to leave the window showing a
dead/empty pane with no way back short of reloading the whole task.

Recover on the normal poll cadence, split by which loop can observe the death:

- Mid content pane (Vim/difftool): the review panel's own loop detects a dead
  middle pane via `review_ui::mid_content_pane_dead` and falls the view back to
  Chat through the existing `ShowChat` path (`recover_to_chat` mirrors the Chat
  switch click), so recovery converges with the manual path.
- Nav/panel pane: the panel is run-once and can't rebuild itself, so the
  dashboard sidebar loop (`App::poll_review_panes` -> `review_panel_pane_dead`)
  rebuilds it — `poll_active_window` only fires on a window *change*, so this
  catches a panel that dies while its window is already current.
- `ensure_editor_pane`/`ensure_diff_pane` now treat a stashed-but-dead pane id
  as absent (`pane_alive_anywhere`), so re-selecting a view rebuilds the pane
  fresh instead of swapping in a corpse.
- `show_review_view` handles a dead current-mid: a killed mid pane collapses
  the window to just its panel, so there's nothing to swap against — join the
  target beside the panel instead (the clamp hook re-clamps the width).

Decisions made without asking (spec was prescriptive):
- Chat/agent-pane death while Chat is the mid view is left to the existing
  workspace supervisor (window-level auto-restart), not duplicated here — the
  review UI's reuse guards just avoid trusting stale ids. Reviving a crashed
  agent is a workspace-lifecycle concern, not review-window layout.
- Recovery is gated to the *active* review window (`review_window_active`) so a
  Back-to-dashboard (FocusDashboard) or the quit teardown never triggers a
  rebuild, per the "distinguish teardown from in-place death" requirement.
- Dead-mid recovery uses `join-pane` (verified against tmux 3.7b: a dead
  swapped-in pane strands chat in its stash window and collapses the review
  window) rather than a full teardown+respawn, to preserve the panel and avoid
  a dashboard flicker.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
shelbi Ready Ready Preview Aug 15, 2026 11:22pm

Request Review

@jlong
jlong merged commit c01419e into main Aug 15, 2026
3 checks passed
@jlong
jlong deleted the jlong/tui-reload-review-window-panes-when-they-exit-vim-diff-chat-nav-defaulting-the-mid-view-back-to-chat branch August 15, 2026 23:54
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