Fix terminal surfaces staying occluded after a worktree selection flap - #759
Merged
sbertix merged 2 commits intoAug 2, 2026
Merged
Conversation
Deselecting a worktree occludes and unfocuses every surface, but re-selection never re-asserted activity: the view-layer sync only fires on a remount, so a transient selection flap inside one render commit left the picture frozen at the last frame while the pty kept draining and input was delivered invisibly (#757). Derive surface activity from worktree selection at a single selection choke point, fail open on unknown window visibility, heal from user input at a key window using the window's fresh readings, read window activity from the observed window instead of NSApp.keyWindow, force a fresh emit on app activation, wake dormant tabs from the selection commit, and log occlusion transitions.
kill(pid, 0) fails with EPERM for sandboxed processes that are still running; only ESRCH proves death. Aligns the presence sweep with ProcessLiveness and cross-references the mirrors.
sbertix
enabled auto-merge (squash)
August 2, 2026 20:57
sbertix
deleted the
sbertix/gh-757-terminal-window-freezes-after-first-prom
branch
August 2, 2026 21:06
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 #757
Summary
Terminal panes could freeze after an agent's first prompt: the picture stopped at the last frame, typing / Ctrl+C / scrolling appeared dead, and closing the tab was the only way out.
Root cause is a one-way occlusion latch. Deselecting a worktree occludes and unfocuses every surface (
setAllSurfacesOccluded()), but re-selection never re-asserted activity; the only heals lived in view-layeronAppear/onChange, which do not fire when the detail view never remounts. A transient selection flap inside a single render commit (for example the selected sidebar row moving when the first presence flip lands) latched the renderer off while the pty kept draining, so input was still delivered invisibly and window shortcuts kept working.The fix derives surface activity from worktree selection at a single selection choke point, fails open on unknown window visibility, heals from user input at a key window using the window's fresh readings, reads window activity from the observed window instead of
NSApp.keyWindow, force-emits a fresh read on app activation, wakes dormant tabs from the selection commit, and logs every occlusion transition so any future report is diagnosable from logs.Also aligns the agent presence liveness sweep with #748:
kill(pid, 0)returning EPERM means the process is alive but unsignalable, not dead.Type of change
ready)How was this tested?
A regression test reproduces the latch deterministically (worktree select, deselect, re-select with spy surfaces; it fails without the fix), plus reducer-level coverage for the cold-cache flap, the user-input heal including the covered-window negative, stale heal closures staying inert, dormant wake gating, the
surfaceActivitytruth table, and the EPERM probe.make checkpasses (format + lint)make testpassesChecklist
Closes #above.ready.