fix(workstation): close tabs at canonical resource owners - #727
Open
beruro wants to merge 5 commits into
Open
Conversation
beruro
force-pushed
the
junyu/fix-tab-lifecycle-ownership
branch
from
August 10, 2026 04:11
51805c3 to
9dff00a
Compare
beruro
force-pushed
the
junyu/fix-tab-lifecycle-ownership
branch
from
August 10, 2026 05:24
9dff00a to
30bb5ac
Compare
Pre-commit hook ran. Total eslint: 0, total circular: 0
Pre-commit hook ran. Total eslint: 0, total circular: 0
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.
Problem
Closing a WorkStation Browser tab removed only its visible workspace projection. The live Browser session and its localStorage record remained authoritative, so switching surfaces could recreate the supposedly closed tab.
The same ownership ambiguity existed around Terminal teardown and entity-backed Session or Project Org tabs: presentation state could be removed while the underlying resource or another workspace reference survived. In addition, initialized xterm/WebGL renderers stayed mounted for inactive terminal sessions and hidden keep-alive tabs, retaining renderer/listener resources the user could not see.
Solution
develop; the one AppShell conflict keeps upstream status-bar visibility while preserving this PR's removal of the obsolete terminal teardown hook.The resulting invariant is: a user close destroys a resource at its canonical owner and then removes all projections; workspace disposal removes only that workspace reference; heavy terminal renderers exist only for the terminal the user can see.
Potential risks
Verification
develop:pnpm exec vitest runover the 4 terminal lifecycle files,statusBarVisibility.test.ts, andterminalAtoms.test.ts— PASS, 6 files / 32 tests.pnpm exec eslintover AppShell and the three changed terminal render components — PASS.pnpm typecheckafter the merge/conflict resolution — PASS, real full TypeScript check.--no-verifyso the old hook would not lint every unrelated upstream file; the focused 32-test run, ESLint, full typecheck, andgit diff --checkran afterward.tsc --noEmit, circular-dependency scan across 6,321 modules, diff check, and secret/personal-path/debug-log scan — PASS.pnpm verify:quickandpnpm verify:finalare not available on this branch's current base (the new entry points are in separate PR chore(quality): add scoped verification workflow #801), so they were not run.Architecture audit
All 10 layers were reviewed. Browser/Terminal ownership is canonical; resource and presentation semantics are distinct; lifecycle policy switches remain exhaustive; cross-surface invalidation stays in lifecycle aggregators; PTY identity survives renderer detach but not canonical close; no wire/serialization contract changed; persistence restore and provider entry paths converge on the same owners; and single, bulk, delete, revoke, hide, switch, restart, and rapid reopen paths have symmetric coverage. No layers were skipped.
Performance guard
Verdict: pass. The change adds no polling, timers, subscriptions, workers, or scans. A visible terminal owns at most one xterm/WebGL surface per host; hidden terminals retain zero renderer streams. Active close performs bounded in-memory filtering plus one owner teardown; repeated switch/hide detaches and remounts cleanly; terminal generations protect rapid reopen; multi-workspace references share one owner; restart prunes stale projections. The remaining bounded-snapshot tradeoff is documented above.
UI audit and evidence
Frontend UI audit reports for TerminalCore, TerminalMainContent, and TerminalTabRenderer record 0 fix candidates, 0 UI hits requiring keep exceptions, and 0 abstraction candidates. The change introduces no raw interactive elements, arbitrary Tailwind values, hardcoded visual literals, or accessibility regressions.
No screenshot is included because the acceptance criterion is visual parity; the change affects hidden/active resource mounting, not layout, styling, loading, empty, or error-state appearance.