From 16d4a197095e9f01f48dd99616130ea467f41df7 Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Thu, 13 Aug 2026 12:15:35 -0700 Subject: [PATCH] Revert "fix(terminal): migrate hidden delivery gate default" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The migration was unnecessary. terminalHiddenDeliveryGate is never written: every reference in the codebase reads it (`?? null`, `!== false`), no settings UI exposes it, and it is absent from real long-lived profiles — 153 persisted keys and this is not one of them. An unset key takes the constants default at read time, so flipping that default already reaches existing users. The only thing that would have persisted the key was the migration itself, which also added a permanent marker field to the settings schema to solve a problem that does not exist. The precedent it copied (experimentalActivity) IS persisted, which is why that one needed migrating and this one does not. --- src/main/ipc/pty-hidden-delivery-gate.ts | 3 +- src/main/persistence.test.ts | 37 ------------------------ src/main/persistence.ts | 11 ------- src/shared/constants.test.ts | 5 ---- src/shared/constants.ts | 12 ++++++-- src/shared/types.ts | 2 -- 6 files changed, 12 insertions(+), 58 deletions(-) diff --git a/src/main/ipc/pty-hidden-delivery-gate.ts b/src/main/ipc/pty-hidden-delivery-gate.ts index 0fa58e6f909..43fa8567b88 100644 --- a/src/main/ipc/pty-hidden-delivery-gate.ts +++ b/src/main/ipc/pty-hidden-delivery-gate.ts @@ -31,7 +31,8 @@ const droppedSinceHiddenPtys = new Set() let droppedHiddenDeliveryChars = 0 let droppedHiddenDeliveryChunks = 0 -/** The gate operates only when main side-effect authority and the gate setting are enabled. */ +/** Gate kill switches, both read main-side: the gate only operates under main + * side-effect authority AND the gate-specific setting (both default on). */ export function isHiddenPtyDeliveryGateEnabled( settings: HiddenPtyDeliveryGateSettings | null | undefined ): boolean { diff --git a/src/main/persistence.test.ts b/src/main/persistence.test.ts index 96f697c976d..17a73fa0e48 100644 --- a/src/main/persistence.test.ts +++ b/src/main/persistence.test.ts @@ -7933,43 +7933,6 @@ describe('Store', () => { expect(store.getSettings().experimentalActivity).toBe(true) }) - it('disables the generated hidden PTY delivery gate for existing profiles', async () => { - writeDataFile({ - schemaVersion: 1, - repos: [], - worktreeMeta: {}, - settings: { terminalHiddenDeliveryGate: true }, - ui: {}, - githubCache: { pr: {}, issue: {} }, - workspaceSession: {} - }) - - const store = await createStore() - - expect(store.getSettings().terminalHiddenDeliveryGate).toBe(false) - expect(store.getSettings().terminalHiddenDeliveryGateDefaultedOffForAllUsers).toBe(true) - }) - - it('preserves hidden PTY delivery gate opt-ins after the default-off migration', async () => { - writeDataFile({ - schemaVersion: 1, - repos: [], - worktreeMeta: {}, - settings: { - terminalHiddenDeliveryGate: true, - terminalHiddenDeliveryGateDefaultedOffForAllUsers: true - }, - ui: {}, - githubCache: { pr: {}, issue: {} }, - workspaceSession: {} - }) - - const store = await createStore() - - expect(store.getSettings().terminalHiddenDeliveryGate).toBe(true) - expect(store.getSettings().terminalHiddenDeliveryGateDefaultedOffForAllUsers).toBe(true) - }) - // ── worktree-card property migration ─────────────────────────────── it('adds split-out default card properties for legacy detailed profiles', async () => { diff --git a/src/main/persistence.ts b/src/main/persistence.ts index 975d558cec8..f9fee511d39 100644 --- a/src/main/persistence.ts +++ b/src/main/persistence.ts @@ -3290,15 +3290,6 @@ export class Store { const migratedExperimentalActivity = experimentalActivityDefaultedOffForAllUsers ? (parsed.settings?.experimentalActivity ?? false) : false - const terminalHiddenDeliveryGateDefaultedOffForAllUsers = - parsed.settings?.terminalHiddenDeliveryGateDefaultedOffForAllUsers === true - // Why: the old generated true is indistinguishable from an opt-in, so reset it once before preserving later overrides. - const migratedTerminalHiddenDeliveryGate = terminalHiddenDeliveryGateDefaultedOffForAllUsers - ? (parsed.settings?.terminalHiddenDeliveryGate ?? false) - : false - if (!terminalHiddenDeliveryGateDefaultedOffForAllUsers) { - this.loadNeedsSave = true - } const autoRenameBranchFromWorkDefaultedOn = parsed.settings?.autoRenameBranchFromWorkDefaultedOn === true // Why: default-on rollout activates old profiles once, but a later Settings opt-out survives reloads. @@ -3512,8 +3503,6 @@ export class Store { ...migratedTerminalTuiScrollSensitivity.settings, experimentalActivity: migratedExperimentalActivity, experimentalActivityDefaultedOffForAllUsers: true, - terminalHiddenDeliveryGate: migratedTerminalHiddenDeliveryGate, - terminalHiddenDeliveryGateDefaultedOffForAllUsers: true, // Why: compact worktree cards graduated from Experimental; preserve the old opt-in for rollout-era profiles. compactWorktreeCards: loadedCompactWorktreeCards, experimentalCompactWorktreeCards: undefined, diff --git a/src/shared/constants.test.ts b/src/shared/constants.test.ts index bd3e799793e..ea41c8a6af9 100644 --- a/src/shared/constants.test.ts +++ b/src/shared/constants.test.ts @@ -42,11 +42,6 @@ describe('getDefaultSettings', () => { expect(getDefaultSettings('/tmp').terminalCursorStyleDefaultedToBlock).toBe(true) }) - it('keeps hidden PTY bytes flowing to the renderer by default', () => { - expect(getDefaultSettings('/tmp').terminalHiddenDeliveryGate).toBe(false) - expect(getDefaultSettings('/tmp').terminalHiddenDeliveryGateDefaultedOffForAllUsers).toBe(true) - }) - it('allows OSC 52 clipboard writes by default for new settings', () => { expect(getDefaultSettings('/tmp').terminalAllowOsc52Clipboard).toBe(true) expect(getDefaultSettings('/tmp').terminalAllowOsc52ClipboardDefaultedOnForAllUsers).toBe(true) diff --git a/src/shared/constants.ts b/src/shared/constants.ts index 95d85109557..ec0f8358005 100644 --- a/src/shared/constants.ts +++ b/src/shared/constants.ts @@ -311,9 +311,17 @@ export function getDefaultSettings(homedir: string): GlobalSettings { terminalHiddenWorktreeRetentionBudget: true, browserGuestWorktreeRetentionBudget: true, terminalMainSideEffectAuthority: true, - // Why: keep hidden-pane xterm state synchronized while rendering remains suspended. + // Why default off: dropping renderer-bound bytes leaves the renderer's xterm + // a second emulator that has seen a different stream than the model, and a + // gap can strand any carried state — a swallowed `ESC[22m` leaves bold on + // every later cell, a swallowed `ESC(B` leaves line-drawing on (STA-4042). + // Every recovery path then has to reconstruct state it cannot actually know. + // Feeding the emulator unconditionally and suspending only the *rendering* + // (pane-manager suspendRendering + WebGL retention already do this) removes + // the gap class outright rather than repairing it after the fact. The gate + // stays available for anyone who needs to trade that correctness for the + // hidden-pane IPC/parse saving. terminalHiddenDeliveryGate: false, - terminalHiddenDeliveryGateDefaultedOffForAllUsers: true, terminalModelQueryAuthority: true, defaultTuiAgent: null, disabledTuiAgents: [...DEFAULT_DISABLED_TUI_AGENTS], diff --git a/src/shared/types.ts b/src/shared/types.ts index 29ad921082f..4d9a2e9b810 100644 --- a/src/shared/types.ts +++ b/src/shared/types.ts @@ -3009,8 +3009,6 @@ export type GlobalSettings = { terminalMainSideEffectAuthority?: boolean /** Kill switch for main's hidden-delivery gate (Phase 4): drops PTY bytes to hidden views after model ingestion; requires terminalMainSideEffectAuthority. */ terminalHiddenDeliveryGate?: boolean - /** One-shot guard for defaulting the hidden-delivery gate off for existing profiles. */ - terminalHiddenDeliveryGateDefaultedOffForAllUsers?: boolean /** Kill switch for main's model query responder (Phase 5); active only when both Phase-4 gates are also on. */ terminalModelQueryAuthority?: boolean /** Which agent to pre-select in the new-workspace composer.