fix(terminals): preserve saved tmux sessions during workspace recovery - #933
Merged
Merged
Conversation
Decode every saved window through the canonical workspace reader before classifying managed processes. Partial restoration is not evidence that an unmatched process is abandoned, so retain it and report bounded inventory uncertainty instead of authorizing orphan cleanup. Keep known-reference recovery and complete-empty cleanup, and exercise the startup boundary with the real decoder and reconciliation. This is a startup snapshot guarantee, not a durable damaged-workspace repair journal. Refs #898 Refs #918
This was referenced Sep 12, 2026
Retain a digest with the inventory decision so diagnostics can distinguish two empty-looking inventories after a subsequent autosave. Failed reads remain distinct from captured unreadable bytes. Refs #898
This was referenced Sep 12, 2026
Refresh a 340-commit-old branch so CI measures the merge result. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The earlier cases drive the real decoder and reconciliation, but with typed workspace literals. This adds the live workspace.json the app persisted on 2026-09-19, sanitized: only cwd, title and projectTabTitle go through a stable placeholder map, and it keeps its real terminal and tmuxName. The test asserts three things: - the exact legacy read (`parsed.workspace?.sessions`) finds nothing in this real file, which is the #898 cause; - the live terminal's tmux session is never killed; - a proven orphan is still cleaned, because the inventory is complete. Refs #898 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Juliusolsson05
added a commit
that referenced
this pull request
Sep 19, 2026
…ckage PR Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ARCHITECTURE.md's risk row still described #898 as open, contradicting the rewritten section 6.6.1. It now names the narrower gap an independent review found: a complete but stale workspace file (after a partial restore, a crash inside the autosave debounce, or two apps sharing state) still authorises cleaning unsaved terminals. The fix direction is on #918. The plan status is updated too. Refs #898 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Juliusolsson05
added a commit
that referenced
this pull request
Sep 19, 2026
…htly Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Juliusolsson05
added a commit
that referenced
this pull request
Sep 19, 2026
Pick up #1022 (goal-loop input freeze), #1023, #933 (tmux inventory) and #1012. One conflict, in useKeybinds' onBlur: keep #1022's dismissGoalLoop() and drop `pendingTiledResizeIndex`, which #992 deleted along with tiled resize. #1022's overlay gate and rebind-safe dismiss chord merged intact. Verified: tsc -b clean. goal-loop + tile-tree + tldr renderer 175/175; tmux + storage + remote-client unit 112/112. That includes #933's real-workspace recovery test running against #992's model. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Juliusolsson05
added a commit
that referenced
this pull request
Sep 19, 2026
…l v2 file Fail-first against the branch: the stage document was written as file version 2, and nothing backed up the original. The input is the live v2 workspace.json from #933's sanitized fixture, driven through the real store on the real filesystem in a temp directory. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
A normal v2 workspace could lose its surviving terminals at startup: recovery read only the legacy
workspace.sessionspath, supplied an empty reference list, and classified managed tmux sessions as orphans.This change collects references from every window through the canonical workspace decoder. It retains legacy v1 recovery and ordinary complete-empty cleanup. Discarded/duplicate windows, malformed session references, unreadable state, and read failures now withhold cleanup of unmatched sessions while retaining known-reference recovery. Startup reports inventory completeness, bounded issue counts, preserved-session counts, and a SHA-256 receipt identifying the exact workspace byte snapshot used for the decision. Failed reads carry no digest.
The decoder's completeness evidence is additive and is not persisted as a format change. Hidden/detached terminals are collected from saved metadata without copying renderer layout ownership rules. Registry failures still propagate as failures. WHY comments explain the distinction between partial restoration and authority to terminate a process.
Validation:
npm run typecheck,npm run test:contract,npm run submodules:check(seven pins),npm run test:package, andgit diff --checkpassed.d424520c(run 34716892305).Limits: no live user tmux processes were touched. The build verified app entry points; runtime archives were not downloaded, so this is not a signed release or bundled-tmux smoke test. Preservation applies to the workspace read for this startup; durable quarantine/repair provenance across later saves remains part of #918. Unknown-owner routing (#920) is a separate slice.
Fixes #898
Refs #918
First implementation-loop slice of the program documented in #931. The branch begins with the focused implementation plan.
Program-plan conformance follow-up: commit
d424520cadds the inventory snapshot receipt. The original implementation atff9724depassed both CI gates. The follow-up passed the updated 58-test suite and type checking locally, and both CI gates passed ond424520cin run 34716892305. Review-ready; unmerged.2026-09-19 update (release readiness)
93f60755). That was 340 commits, and the only conflict was in the imports ofsrc/main/index.ts. Startup order is unchanged: state lock → tmux detection → recovery → SessionManager → store open.b3961fba): the live v2workspace.jsonthe app persisted on 2026-09-19, sanitized (testing/fixtures/workspace-v2/, provenance README).reconcilewith the old startup read against this file, and it kills the file's detached terminal. That is bug(terminals): read v2 workspace references before tmux reconciliation #898 reproduced on a real file.src/main/tmuxplussrc/main/storage. CI was green onb3961fba(run 35426719774) and is re-running on the docs commit.7da7a255:🤖 Generated with Claude Code