mirror of
https://github.com/stablyai/orca.git
synced 2026-10-22 16:03:47 +00:00
fix(terminal): migrate hidden delivery gate default
This commit is contained in:
@@ -31,8 +31,7 @@ const droppedSinceHiddenPtys = new Set<string>()
|
||||
let droppedHiddenDeliveryChars = 0
|
||||
let droppedHiddenDeliveryChunks = 0
|
||||
|
||||
/** Gate kill switches, both read main-side: the gate only operates under main
|
||||
* side-effect authority AND the gate-specific setting (both default on). */
|
||||
/** The gate operates only when main side-effect authority and the gate setting are enabled. */
|
||||
export function isHiddenPtyDeliveryGateEnabled(
|
||||
settings: HiddenPtyDeliveryGateSettings | null | undefined
|
||||
): boolean {
|
||||
|
||||
@@ -7933,6 +7933,43 @@ 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 () => {
|
||||
|
||||
@@ -3290,6 +3290,15 @@ 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.
|
||||
@@ -3503,6 +3512,8 @@ 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,
|
||||
|
||||
@@ -42,6 +42,11 @@ 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)
|
||||
|
||||
+2
-10
@@ -311,17 +311,9 @@ export function getDefaultSettings(homedir: string): GlobalSettings {
|
||||
terminalHiddenWorktreeRetentionBudget: true,
|
||||
browserGuestWorktreeRetentionBudget: true,
|
||||
terminalMainSideEffectAuthority: true,
|
||||
// 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.
|
||||
// Why: keep hidden-pane xterm state synchronized while rendering remains suspended.
|
||||
terminalHiddenDeliveryGate: false,
|
||||
terminalHiddenDeliveryGateDefaultedOffForAllUsers: true,
|
||||
terminalModelQueryAuthority: true,
|
||||
defaultTuiAgent: null,
|
||||
disabledTuiAgents: [...DEFAULT_DISABLED_TUI_AGENTS],
|
||||
|
||||
@@ -3009,6 +3009,8 @@ 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.
|
||||
|
||||
Reference in New Issue
Block a user