Skip to content

fix(session): persist defaultTerminalTabsAppliedByWorktreeId - #18223

Closed
innocarpe wants to merge 1 commit into
stablyai:mainfrom
innocarpe:fix/persist-default-terminal-tabs-applied
Closed

innocarpe wants to merge 1 commit into
stablyai:mainfrom
innocarpe:fix/persist-default-terminal-tabs-applied

Conversation

@innocarpe

Copy link
Copy Markdown
Contributor

Description

workspaceSession.defaultTerminalTabsAppliedByWorktreeId never gained entries, so every launch and re-attach treated every worktree as never having default terminals applied and spawned a fresh pendingActivationSpawn tab.

Host persist snapshots already wrote tabs, but they omitted this write-once map. Full session replaces and hydration then treated omission as "never applied".

Focused fix

  • In scope: stamp the marker on host PTY-binding persist, union it across renderer session replaces, and union it on hydration so an omitted persist snapshot cannot un-apply it.
  • Out of scope (explicit): a second persistence system, restore-path "already has tabs" seeding changes, hibernation, SSH merge of other maps.

Preserves

  • Existing tabs, SSH/remote session merge, hydration of other maps, hibernation flags.
  • Worktree teardown still removes keys; this only treats omission as "never stamped".

Evidence

  • Test: pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/lib/default-terminal-tabs-applied-persist.test.ts src/main/persistence/runtime-authored-workspace-session-fields.test.ts src/main/persistence-host-admitted-terminal-membership.test.ts src/renderer/src/lib/session-write-subscriber.test.ts
  • Before: host persist wrote tabs with the map still {}; a later full write or hydrate from an omitted snapshot wiped any in-memory marks; applyDefaultTerminalTabs ran again.
  • After: markDefaultTerminalTabsApplied → persist/patch → omitted snapshot → hydration still has the worktreeId, so default tabs are not applied again.

User-regression-tradeoffs

  • A persist snapshot that lists a subset of marks will keep prior keys (write-once). Clearing a worktree remains the teardown path, same as SSH merge.

Fixes #18117

@coderabbitai

coderabbitai Bot commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: aabf46b8-1553-425a-b467-88a7952c508c

📥 Commits

Reviewing files that changed from the base of the PR and between da39a95844deeb0f6a5a1203393f6e1300b16cfe and 281deb1.

📒 Files selected for processing (2)
  • src/main/persistence/loading-store/pty-binding-persistence.ts
  • src/renderer/src/lib/session-write-subscriber.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

The change adds write-once, per-worktree markers for applied default terminal tabs. Host-admitted terminal persistence records the marker. Session writes union prior markers with new payloads. Renderer persistence writes marker patches, and hydration merges persisted markers with local state. Tests cover session preservation, host-admitted terminal handling, persistence subscriber behavior, hydration, schema parsing, and suppression of repeated default-terminal application.

Priority: ⬆️ High

Severity of issue fixed: High

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the problem, scope, solution, regression behavior, testing command, and linked issue. However, it does not follow the required template and omits required sections such as Vis… Use the repository template headings and complete the missing sections. Add Visual Proof with N/A and a reason if there is no UI change, document manual and platform testing, complete AI Disclosure and Review as applicable, address the Ag…
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 8 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: persisting defaultTerminalTabsAppliedByWorktreeId.
Linked Issues check ✅ Passed The PR meets the coding requirements in #18117. applyPtyBinding writes defaultTerminalTabsAppliedByWorktreeId[bindingWorktreeId] = true after tab creation or update. `preserveRuntimeAuthoredWorksp…
Out of Scope Changes check ✅ Passed The reviewed changes stay within #18117. The source changes preserve the affected marker across host PTY binding, renderer session writes, and hydration. The added tests verify those paths. No unrelat…
Full details: Description check

Explanation

The description explains the problem, scope, solution, regression behavior, testing command, and linked issue. However, it does not follow the required template and omits required sections such as Visual Proof with an N/A explanation, Testing checklist details, Notes, Review, Agent skill boundary, and the final Checklist.

Resolution

Use the repository template headings and complete the missing sections. Add Visual Proof with N/A and a reason if there is no UI change, document manual and platform testing, complete AI Disclosure and Review as applicable, address the Agent skill boundary, Notes, and Checklist items.

  • Fix all pre-merge checks with AI

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Team

Run ID: 1dd11312-743f-4a73-a158-31b82be4b6e9

📥 Commits

Reviewing files that changed from the base of the PR and between 8dc3c1d and da39a95844deeb0f6a5a1203393f6e1300b16cfe.

📒 Files selected for processing (8)
  • src/main/persistence-host-admitted-terminal-membership.test.ts
  • src/main/persistence/loading-store/pty-binding-persistence.ts
  • src/main/persistence/runtime-authored-workspace-session-fields.test.ts
  • src/main/persistence/runtime-authored-workspace-session-fields.ts
  • src/renderer/src/lib/default-terminal-tabs-applied-persist.test.ts
  • src/renderer/src/lib/session-write-subscriber.test.ts
  • src/renderer/src/store/terminals/workspace-terminal-hydration-patch.ts
  • src/renderer/src/store/terminals/workspace-terminal-hydration.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 5 remain after this review.

Comment thread src/main/persistence/runtime-authored-workspace-session-fields.ts

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

  • Stamp marker on host PTY-binding persist — persistPtyBinding now writes defaultTerminalTabsAppliedByWorktreeId[bindingWorktreeId] = true on the host session before flush (rolled back by restoreSession() on flush failure).
  • Union the write-once marker across full session replaces — a new unionWriteOnceDefaultTerminalTabsApplied merges prior markers into a renderer full write that omits (or only partially lists) the map; preserveRuntimeAuthoredWorkspaceSessionFields refactored to chain the client-hosted-page guard and the marker union.
  • Union on hydration — hydrateWorkspaceSession now produces { ...session.map, ...liveStore.map } instead of session.map ?? {}, so a snapshot that omits the marker can't no-op a live mark.
  • Local marks win in scoped re-hydration — targetScopedWorkspaceHydrationPatch spreads live state over the hydrated map so an SSH pull replace can't drop a local marker.
  • Tests — round-trip, union, host-stamp, and subscriber coverage added across four files; I also ran adjacent terminals-hydration, workspace-session-host-split, and worktrees-identity-migration suites (all green).

The write-once semantics are consistent with the existing mergeDirectSshRemoteWorkspaceSession rule and documented clearly. Removal still flows through the worktree-teardown path (removeWorkspaceSessionStateForWorktree → deleteOwnerKeyedSessionFields), which bypasses the union, so teardown is not undermined. The patch write path (patchWorkspaceSession) also bypasses preserveRuntimeAuthoredWorkspaceSessionFields, so a normal write that drops a worktree key still removes it correctly.

ℹ️ Nitpicks

  • src/renderer/src/lib/default-terminal-tabs-applied-persist.test.ts imports preserveRuntimeAuthoredWorkspaceSessionFields directly from src/main/persistence/, crossing the main↔renderer layer boundary. It works because the module is pure, but it couples a renderer test to a main-process module.
  • The trailing ...state.defaultTerminalTabsAppliedByWorktreeId in workspace-terminal-hydration-patch.ts makes the non-replace-key remit of the replaceHydratedRecordKeys argument dead weight — correct, but the expression could be just { ...hydrated-markers-for-replaced-keys, ...state.map }.
  • The session-write-subscriber.test.ts case asserts behavior that predates the fix (defaultTerminalTabsAppliedByWorktreeId was already in SESSION_RELEVANT_FIELDS), so it passes with the bug present — a guard, not evidence the fix works.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

Host persist snapshots wrote tabs but omitted this write-once map, and
full session replaces / hydration treated omission as "never applied".
Union the marker across persist and hydrate so default terminals are not
re-spawned on every launch or re-attach.

Fixes stablyai#18117
@innocarpe
innocarpe force-pushed the fix/persist-default-terminal-tabs-applied branch from da39a95 to 281deb1 Compare September 17, 2026 15:13
@innocarpe

Copy link
Copy Markdown
Contributor Author

Sync update (281deb196)

Rebased onto the latest upstream/main and preserved the current pty-binding fast lane and rollback behavior while restoring persistence of the default-terminal write-once marker. Focused persistence and session suites (40 tests), node typecheck, formatting, and targeted lint pass.

@innocarpe

Copy link
Copy Markdown
Contributor Author

Closing as superseded by #21630, merged on 2026-09-19.

That change persists defaultTerminalTabsAppliedByWorktreeId through host writes, session replacement, and hydration, and it also remembers an explicitly empty terminal row. #18117 is closed. This branch was the earlier, narrower persistence fix for the same field.

@innocarpe innocarpe closed this Sep 25, 2026
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.

[Bug]: defaultTerminalTabsAppliedByWorktreeId is never persisted — every launch and re-attach spawns a fresh default terminal in every workspace

1 participant