Skip plain hidden terminal renderer writes

This commit is contained in:
Neil
2026-06-09 17:06:04 -07:00
parent 788e2f6a13
commit 404a51ff9f
8 changed files with 312 additions and 88 deletions
@@ -0,0 +1,97 @@
import { describe, expect, it } from 'vitest'
import { shouldSkipHiddenRendererOutput } from './hidden-renderer-skip-eligibility'
describe('shouldSkipHiddenRendererOutput', () => {
it('skips hidden plain ASCII output when a snapshot restore is available', () => {
expect(
shouldSkipHiddenRendererOutput({
foreground: false,
canRestoreHiddenOutput: true,
startupRendererQueryWindowActive: false,
synchronizedOutputActive: false,
data: 'line one\r\nline two\tok\n'
})
).toBe(true)
})
it('keeps visible or non-restorable output on the live renderer path', () => {
expect(
shouldSkipHiddenRendererOutput({
foreground: true,
canRestoreHiddenOutput: true,
startupRendererQueryWindowActive: false,
synchronizedOutputActive: false,
data: 'visible\r\n'
})
).toBe(false)
expect(
shouldSkipHiddenRendererOutput({
foreground: false,
canRestoreHiddenOutput: false,
startupRendererQueryWindowActive: false,
synchronizedOutputActive: false,
data: 'hidden\r\n'
})
).toBe(false)
})
it('keeps startup query windows and terminal-control chunks live', () => {
expect(
shouldSkipHiddenRendererOutput({
foreground: false,
canRestoreHiddenOutput: true,
startupRendererQueryWindowActive: true,
synchronizedOutputActive: false,
data: 'plain\r\n'
})
).toBe(false)
expect(
shouldSkipHiddenRendererOutput({
foreground: false,
canRestoreHiddenOutput: true,
startupRendererQueryWindowActive: false,
synchronizedOutputActive: true,
data: 'plain row inside synchronized frame\r\n'
})
).toBe(false)
expect(
shouldSkipHiddenRendererOutput({
foreground: false,
canRestoreHiddenOutput: true,
startupRendererQueryWindowActive: false,
synchronizedOutputActive: false,
data: '\x1b]0;title\x07'
})
).toBe(false)
expect(
shouldSkipHiddenRendererOutput({
foreground: false,
canRestoreHiddenOutput: true,
startupRendererQueryWindowActive: false,
synchronizedOutputActive: false,
data: '\x1b[?2026hredraw\x1b[?2026l'
})
).toBe(false)
})
it('keeps rewrite and unicode chunks live', () => {
expect(
shouldSkipHiddenRendererOutput({
foreground: false,
canRestoreHiddenOutput: true,
startupRendererQueryWindowActive: false,
synchronizedOutputActive: false,
data: 'progress 10%\rprogress 20%'
})
).toBe(false)
expect(
shouldSkipHiddenRendererOutput({
foreground: false,
canRestoreHiddenOutput: true,
startupRendererQueryWindowActive: false,
synchronizedOutputActive: false,
data: 'emoji 😀\r\n'
})
).toBe(false)
})
})
@@ -0,0 +1,49 @@
export type HiddenRendererSkipEligibility = {
foreground: boolean
canRestoreHiddenOutput: boolean
startupRendererQueryWindowActive: boolean
synchronizedOutputActive: boolean
data: string
}
function isAllowedPlainHiddenOutputCode(code: number): boolean {
if (code === 0x09 || code === 0x0a) {
return true
}
return code >= 0x20 && code <= 0x7e
}
function containsOnlyPlainHiddenOutput(data: string): boolean {
for (let index = 0; index < data.length; index++) {
const code = data.charCodeAt(index)
if (code === 0x0d) {
if (data.charCodeAt(index + 1) !== 0x0a) {
return false
}
continue
}
if (!isAllowedPlainHiddenOutputCode(code)) {
return false
}
}
return true
}
export function shouldSkipHiddenRendererOutput({
foreground,
canRestoreHiddenOutput,
startupRendererQueryWindowActive,
synchronizedOutputActive,
data
}: HiddenRendererSkipEligibility): boolean {
if (
foreground ||
!canRestoreHiddenOutput ||
startupRendererQueryWindowActive ||
synchronizedOutputActive ||
data.length === 0
) {
return false
}
return containsOnlyPlainHiddenOutput(data)
}
@@ -2945,7 +2945,7 @@ describe('connectPanePty', () => {
expect(transport.sendInput).not.toHaveBeenCalled()
})
it('keeps non-visible local PTY bytes on the live xterm path for release', async () => {
it('keeps hidden terminal-control bytes on the live xterm path', async () => {
const pendingTimeouts: (() => void)[] = []
const originalSetTimeout = globalThis.setTimeout
globalThis.setTimeout = vi.fn((fn: () => void) => {
@@ -2975,14 +2975,15 @@ describe('connectPanePty', () => {
await flushAsyncTicks(6)
expect(capturedDataCallback.current).not.toBeNull()
capturedDataCallback.current?.('hello\r\n')
expect(pane.terminal.write).not.toHaveBeenCalledWith('hello\r\n')
const controlOutput = '\x1b[2J\x1b[Hhello\r\n'
capturedDataCallback.current?.(controlOutput)
expect(pane.terminal.write).not.toHaveBeenCalledWith(controlOutput)
for (const fn of pendingTimeouts) {
fn()
}
expect(pane.terminal.write).toHaveBeenCalledWith('hello\r\n')
expect(pane.terminal.write).toHaveBeenCalledWith(controlOutput)
} finally {
globalThis.setTimeout = originalSetTimeout
}
@@ -3306,7 +3307,7 @@ describe('connectPanePty', () => {
binding.dispose()
})
it('writes ordinary hidden output live instead of proactively restoring a snapshot', async () => {
it('restores plain hidden output from the main snapshot when the pane returns', async () => {
const { connectPanePty } = await import('./pty-connection')
const transport = createMockTransport('pty-id')
const capturedDataCallback: {
@@ -3347,20 +3348,24 @@ describe('connectPanePty', () => {
})
await flushAsyncTicks(20)
expect(getMainBufferSnapshot).not.toHaveBeenCalled()
expect(pane.terminal.write).toHaveBeenCalledWith(hidden)
expect(pane.terminal.write).toHaveBeenCalledWith(live, expect.any(Function))
expect(getMainBufferSnapshot).toHaveBeenCalledWith('pty-id', { scrollbackRows: 5000 })
expect(pane.terminal.write).not.toHaveBeenCalledWith(hidden)
expect(pane.terminal.write).not.toHaveBeenCalledWith(live, expect.any(Function))
expect(pane.terminal.write).toHaveBeenCalledWith(
expect.stringContaining(`snapshot-with-${hidden}`),
expect.any(Function)
)
disposable.dispose()
})
it('writes ordinary hidden remote runtime output live instead of restoring a snapshot', async () => {
it('restores plain hidden remote runtime output from its serialized snapshot', async () => {
const { connectPanePty } = await import('./pty-connection')
const transport = createMockTransport('remote:env-1@@terminal-1')
const capturedDataCallback: {
current: ((data: string, meta?: { seq?: number; rawLength?: number }) => void) | null
} = { current: null }
transport.serializeBuffer = vi.fn().mockResolvedValue({
data: 'remote snapshot\r\n',
data: 'remote snapshot with hidden remote output\r\n',
cols: 120,
rows: 40,
seq: 40,
@@ -3394,13 +3399,16 @@ describe('connectPanePty', () => {
await flushAsyncTicks(20)
expect(getMainBufferSnapshot).not.toHaveBeenCalled()
expect(transport.serializeBuffer).not.toHaveBeenCalled()
expect(pane.terminal.write).toHaveBeenCalledWith(hidden)
expect(pane.terminal.write).toHaveBeenCalledWith(live, expect.any(Function))
expect(transport.serializeBuffer).toHaveBeenCalledWith({ scrollbackRows: 5000 })
expect(pane.terminal.write).not.toHaveBeenCalledWith(hidden)
expect(pane.terminal.write).toHaveBeenCalledWith(
expect.stringContaining('remote snapshot with hidden remote output'),
expect.any(Function)
)
disposable.dispose()
})
it('keeps inactive split-pane hidden output live instead of deferring snapshot restore', async () => {
it('defers inactive split-pane plain hidden output restore until the pane returns', async () => {
const { resetHiddenOutputRestoreSchedulerForTests } =
await import('./hidden-output-restore-scheduler')
let disposable: { dispose: () => void } | null = null
@@ -3452,9 +3460,12 @@ describe('connectPanePty', () => {
await new Promise((resolve) => setTimeout(resolve, 30))
await flushAsyncTicks(20)
expect(getMainBufferSnapshot).not.toHaveBeenCalled()
expect(pane.terminal.write).toHaveBeenCalledWith(hidden)
expect(pane.terminal.write).toHaveBeenCalledWith(live, expect.any(Function))
expect(getMainBufferSnapshot).toHaveBeenCalledWith('pty-id', { scrollbackRows: 5000 })
expect(pane.terminal.write).not.toHaveBeenCalledWith(hidden)
expect(pane.terminal.write).toHaveBeenCalledWith(
expect.stringContaining('inactive snapshot'),
expect.any(Function)
)
} finally {
disposable?.dispose()
resetHiddenOutputRestoreSchedulerForTests()
@@ -3519,7 +3530,7 @@ describe('connectPanePty', () => {
}
})
it('does not retry remote snapshots for ordinary hidden runtime output', async () => {
it('retries null remote snapshots for skipped plain hidden runtime output', async () => {
const { connectPanePty } = await import('./pty-connection')
const transport = createMockTransport('remote:env-1@@terminal-1')
const capturedDataCallback: {
@@ -3555,7 +3566,7 @@ describe('connectPanePty', () => {
})
await flushAsyncTicks(20)
expect(transport.serializeBuffer).not.toHaveBeenCalled()
expect(transport.serializeBuffer).toHaveBeenCalledTimes(1)
expect(pane.terminal.write).not.toHaveBeenCalledWith(
expect.stringContaining('Orca skipped hidden terminal output'),
expect.any(Function)
@@ -3568,8 +3579,11 @@ describe('connectPanePty', () => {
await new Promise((resolve) => setTimeout(resolve, 80))
await flushAsyncTicks(20)
expect(transport.serializeBuffer).not.toHaveBeenCalled()
expect(pane.terminal.write).toHaveBeenCalledWith(firstLive, expect.any(Function))
expect(transport.serializeBuffer).toHaveBeenCalledTimes(2)
expect(pane.terminal.write).toHaveBeenCalledWith(
expect.stringContaining('remote recovered snapshot'),
expect.any(Function)
)
disposable.dispose()
})
@@ -88,6 +88,7 @@ import {
normalizeAgentProviderSession
} from '../../../../shared/agent-session-resume'
import { isWslUncPath } from '../../../../shared/wsl-paths'
import { shouldSkipHiddenRendererOutput } from './hidden-renderer-skip-eligibility'
const pendingSpawnByPaneKey = new Map<string, Promise<string | null>>()
const SSH_SESSION_EXPIRED_ERROR = 'SSH_SESSION_EXPIRED'
@@ -622,6 +623,7 @@ export function connectPanePty(
let pendingTerminalBellNotification = false
let reattachIdleAgentCursorResetTimer: ReturnType<typeof setTimeout> | null = null
let synchronizedForegroundOutputActive = false
let synchronizedHiddenOutputActive = false
// Why: idle callbacks are registered before the deferred PTY output plumbing
// exists. Start with the shared scheduler, then switch to the PTY writer
// below so hidden-tab resets keep backlog-recovery callbacks and byte order.
@@ -2193,16 +2195,6 @@ export function connectPanePty(
}
}
function shouldSkipHiddenRendererOutput(foreground: boolean, data: string): boolean {
void foreground
void data
// Why: release correctness beats the hidden-output perf optimization.
// Real OpenCode tables still corrupt after workspace switching when PTY
// bytes bypass the renderer, so keep hidden panes on the live xterm path
// and leave snapshot skipping for a later perf branch.
return false
}
function skipHiddenRendererOutput(data: string): void {
respondToSkippedMode2031Subscribe(data)
markHiddenOutputRestoreNeeded()
@@ -2607,7 +2599,20 @@ export function connectPanePty(
const foreground = shouldWritePtyOutputForeground(deps.isVisibleRef.current)
const restoreAppliesToCurrentPty =
hiddenOutputRestorePtyId !== null && transport.getPtyId() === hiddenOutputRestorePtyId
if (shouldSkipHiddenRendererOutput(foreground, data)) {
const synchronizedHiddenOutput =
!foreground &&
(synchronizedHiddenOutputActive ||
containsSynchronizedOutputStart(data) ||
containsSynchronizedOutputEnd(data))
if (
shouldSkipHiddenRendererOutput({
foreground,
canRestoreHiddenOutput: canUseHiddenOutputSnapshot(transport.getPtyId()),
startupRendererQueryWindowActive: isHiddenStartupRendererQueryWindowActive(),
synchronizedOutputActive: synchronizedHiddenOutput,
data
})
) {
skipHiddenRendererOutput(data)
} else if (
(hiddenOutputRestoreNeeded || hiddenOutputRestoreInFlight) &&
@@ -2623,6 +2628,12 @@ export function connectPanePty(
} else {
writePtyOutputToXterm(data, foreground)
}
if (!foreground) {
synchronizedHiddenOutputActive = shouldSynchronizedOutputRemainActive(
data,
synchronizedHiddenOutputActive
)
}
schedulePendingStartupCommandDelivery()
}
@@ -1,8 +1,12 @@
import type { Page, TestInfo } from '@stablyai/playwright-test'
import { expect } from '@stablyai/playwright-test'
import { randomUUID } from 'node:crypto'
import { mkdirSync, rmSync, writeFileSync } from 'node:fs'
import { rmSync } from 'node:fs'
import path from 'node:path'
import {
type HiddenPressureOutputMode,
writePressureOutputScript
} from './artificial-opencode-hidden-pressure-script'
import {
ensureTerminalVisible,
getActiveWorktreeId,
@@ -77,38 +81,6 @@ type HiddenPressureAckGate = {
const MAX_HIDDEN_RESTORE_LATENCY_MS = 1_500
const MAIN_RENDERER_PRESSURE_TARGET_CHARS = 2 * 1024 * 1024
export function pressureOutputScript(runId: string): string {
return `
const paneIndex = process.argv[2] ?? '0'
const targetChars = Number(process.argv[3] ?? '0')
const delayMs = Number(process.argv[4] ?? '0')
const header = 'OPENCODE_PRESSURE_START_${runId}_' + paneIndex + '\\n'
const chunkBody = '#'.repeat(8192)
let written = 0
process.stdout.write(header)
function writeMore() {
let canContinue = true
while (canContinue && written < targetChars) {
const frame = String(written).padStart(8, '0')
const chunk = '\\x1b[?2026h\\x1b[1;1Hpressure pane=' + paneIndex + ' frame=' + frame + ' ' + chunkBody + '\\x1b[?2026l\\n'
written += chunk.length
canContinue = process.stdout.write(chunk)
}
if (written < targetChars) {
process.stdout.once('drain', writeMore)
return
}
process.stdout.write('OPENCODE_PRESSURE_DONE_${runId}_' + paneIndex + '\\n')
}
setTimeout(writeMore, Number.isFinite(delayMs) && delayMs > 0 ? delayMs : 0)
`
}
export function writePressureOutputScript(scriptPath: string, runId: string): void {
mkdirSync(path.dirname(scriptPath), { recursive: true })
writeFileSync(scriptPath, pressureOutputScript(runId))
}
export async function runHiddenRealPtyPressureScenario<
TMeasurement extends HiddenPressureMeasurement,
TDebug extends HiddenPressureDebug,
@@ -120,6 +92,7 @@ export async function runHiddenRealPtyPressureScenario<
annotationSuffix,
hiddenPaneCount,
pressureOutputChars,
pressureOutputMode = 'tui',
pressureStartDelayMs,
testInfo,
testRepoPath,
@@ -129,6 +102,7 @@ export async function runHiddenRealPtyPressureScenario<
annotationSuffix?: string
hiddenPaneCount: number
pressureOutputChars: number
pressureOutputMode?: HiddenPressureOutputMode
pressureStartDelayMs: number
testInfo: TestInfo
testRepoPath: string
@@ -158,7 +132,7 @@ export async function runHiddenRealPtyPressureScenario<
`.orca-opencode-hidden-pressure-load-${runId}.mjs`
)
deps.writeInteractivePromptScript(typingScriptPath, runId)
writePressureOutputScript(pressureScriptPath, runId)
writePressureOutputScript(pressureScriptPath, runId, pressureOutputMode)
await deps.resetTerminalPtyOutputDebug(orcaPage)
await deps.holdTerminalAckGate(
@@ -197,8 +171,13 @@ export async function runHiddenRealPtyPressureScenario<
ackGate
)
expect(debug?.hiddenRendererSkipCount ?? 0).toBe(0)
expect(debug?.hiddenRendererSkippedChars ?? 0).toBe(0)
if (pressureOutputMode === 'plain') {
expect(debug?.hiddenRendererSkipCount ?? 0).toBeGreaterThan(0)
expect(debug?.hiddenRendererSkippedChars ?? 0).toBeGreaterThan(0)
} else {
expect(debug?.hiddenRendererSkipCount ?? 0).toBe(0)
expect(debug?.hiddenRendererSkippedChars ?? 0).toBe(0)
}
expect(pressureBeforeTyping.peakPendingChars).toBeGreaterThan(0)
expect(pressureBeforeTyping.ackGatedFlushSkipCount).toBeGreaterThan(0)
expect(mainPressure?.peakRendererInFlightChars ?? 0).toBeGreaterThanOrEqual(
@@ -0,0 +1,46 @@
import { mkdirSync, writeFileSync } from 'node:fs'
import path from 'node:path'
export type HiddenPressureOutputMode = 'tui' | 'plain'
export function pressureOutputScript(runId: string, mode: HiddenPressureOutputMode): string {
const headerPrefix = mode === 'plain' ? '' : '\\x1b[0m'
const donePrefix = mode === 'plain' ? '' : '\\x1b[0m'
const chunkExpression =
mode === 'plain'
? "'plain pressure pane=' + paneIndex + ' frame=' + frame + ' ' + chunkBody + '\\n'"
: "'\\x1b[?2026h\\x1b[1;1Hpressure pane=' + paneIndex + ' frame=' + frame + ' ' + chunkBody + '\\x1b[?2026l\\n'"
return `
const paneIndex = process.argv[2] ?? '0'
const targetChars = Number(process.argv[3] ?? '0')
const delayMs = Number(process.argv[4] ?? '0')
const header = '${headerPrefix}OPENCODE_PRESSURE_START_${runId}_' + paneIndex + '\\n'
const chunkBody = '#'.repeat(8192)
let written = 0
process.stdout.write(header)
function writeMore() {
let canContinue = true
while (canContinue && written < targetChars) {
const frame = String(written).padStart(8, '0')
const chunk = ${chunkExpression}
written += chunk.length
canContinue = process.stdout.write(chunk)
}
if (written < targetChars) {
process.stdout.once('drain', writeMore)
return
}
process.stdout.write('${donePrefix}OPENCODE_PRESSURE_DONE_${runId}_' + paneIndex + '\\n')
}
setTimeout(writeMore, Number.isFinite(delayMs) && delayMs > 0 ? delayMs : 0)
`
}
export function writePressureOutputScript(
scriptPath: string,
runId: string,
mode: HiddenPressureOutputMode
): void {
mkdirSync(path.dirname(scriptPath), { recursive: true })
writeFileSync(scriptPath, pressureOutputScript(runId, mode))
}
@@ -727,7 +727,8 @@ test.describe('Artificial OpenCode terminal load', () => {
testRepoPath: string,
testInfo: TestInfo,
hiddenPaneCount: number,
annotationSuffix?: string
annotationSuffix?: string,
pressureOutputMode?: 'tui' | 'plain'
): Promise<void> {
await runHiddenRealPtyPressureScenario({
orcaPage,
@@ -735,6 +736,7 @@ test.describe('Artificial OpenCode terminal load', () => {
annotationSuffix,
hiddenPaneCount,
pressureOutputChars: PRESSURE_OUTPUT_CHARS,
pressureOutputMode,
pressureStartDelayMs: HIDDEN_PRESSURE_START_DELAY_MS,
testInfo,
deps: {
@@ -764,6 +766,19 @@ test.describe('Artificial OpenCode terminal load', () => {
HIDDEN_PRESSURE_PANES
)
})
test('skips renderer writes for plain hidden PTY output while preserving restore', async ({
orcaPage,
testRepoPath
}, testInfo) => {
await runConfiguredHiddenRealPtyPressureScenario(
orcaPage,
testRepoPath,
testInfo,
HIDDEN_PRESSURE_PANES,
'-plain',
'plain'
)
})
for (const paneCount of SCALE_HIDDEN_PRESSURE_PANES) {
test(`keeps hidden restore responsive with ${paneCount} ACK-backpressured real PTYs`, async ({
orcaPage,
@@ -84,7 +84,17 @@ async function resetHiddenDebug(page: Page): Promise<void> {
function writeHiddenFrameScript(scriptPath: string, runId: string): void {
const frames = Array.from({ length: 25 }, (_, frame) => tuiFrame(runId, frame))
writeFileSync(scriptPath, `process.stdout.write(${JSON.stringify(frames.join(''))})\n`)
writeFileSync(
scriptPath,
`setTimeout(() => process.stdout.write(${JSON.stringify(frames.join(''))}), 250)\n`
)
}
function writeLowRiskFrameScript(scriptPath: string, frame: string): void {
writeFileSync(
scriptPath,
`setTimeout(() => process.stdout.write(${JSON.stringify(frame)}), 250)\n`
)
}
async function writeHiddenFrames(page: Page, ptyId: string, scriptPath: string): Promise<void> {
@@ -229,13 +239,20 @@ test.describe('Hidden terminal TUI visual restore', () => {
writeHiddenFrameScript(scriptPath, runId)
await resetHiddenDebug(orcaPage)
await writeHiddenFrames(orcaPage, hiddenPane.ptyId, scriptPath)
await resetHiddenDebug(orcaPage)
await expect
.poll(async () => (await readHiddenDebug(orcaPage))?.hiddenRendererSkipCount ?? 0, {
timeout: 10_000,
message: 'visually rich hidden TUI output should stay on the live xterm path'
})
.toBe(0)
.toBeLessThanOrEqual(1)
await expect
.poll(async () => (await readHiddenDebug(orcaPage))?.hiddenRendererSkippedChars ?? 0, {
timeout: 10_000,
message: 'only incidental hidden shell prompt text may skip after the TUI exits'
})
.toBeLessThan(512)
await switchToWorktree(orcaPage, secondWorktreeId)
await ensureTerminalVisible(orcaPage)
@@ -273,8 +290,9 @@ test.describe('Hidden terminal TUI visual restore', () => {
rmSync(scriptPath, { force: true })
})
test('keeps newer live output correct after hidden output stayed live', async ({
orcaPage
test('keeps newer live output correct after plain hidden output restores', async ({
orcaPage,
testRepoPath
}, testInfo: TestInfo) => {
await waitForSessionReady(orcaPage)
const firstWorktreeId = await waitForActiveWorktree(orcaPage)
@@ -308,18 +326,18 @@ test.describe('Hidden terminal TUI visual restore', () => {
const hiddenFrame = lowRiskRestoreFrame(runId, 40)
const liveFrame = lowRiskRestoreFrame(runId, 41)
const finalMarker = `VISUAL_RESTORE_FINAL_${runId}_41`
const scriptPath = path.join(testRepoPath, `.orca-low-risk-hidden-${runId}.mjs`)
writeLowRiskFrameScript(scriptPath, hiddenFrame)
await resetHiddenDebug(orcaPage)
await sendToTerminal(orcaPage, hiddenPane.ptyId, `node ${JSON.stringify(scriptPath)}\r`)
await resetHiddenDebug(orcaPage)
await injectPaneData(orcaPage, paneKey, hiddenFrame, {
seq: hiddenFrame.length,
rawLength: hiddenFrame.length
})
await expect
.poll(async () => (await readHiddenDebug(orcaPage))?.hiddenRendererSkipCount ?? 0, {
timeout: 10_000,
message: 'hidden injected output should stay on the live xterm path for release'
message: 'plain hidden injected output should skip renderer writes'
})
.toBe(0)
.toBeGreaterThan(0)
await switchToWorktree(orcaPage, secondWorktreeId)
await ensureTerminalVisible(orcaPage)
@@ -332,7 +350,7 @@ test.describe('Hidden terminal TUI visual restore', () => {
await expect
.poll(() => getTerminalContent(orcaPage, 12_000), {
timeout: 10_000,
message: 'newer live TUI frame did not render after hidden output stayed live'
message: 'newer live TUI frame did not render after hidden output restored'
})
.toContain(finalMarker)
@@ -346,7 +364,7 @@ test.describe('Hidden terminal TUI visual restore', () => {
await expect
.poll(() => readTuiCursorState(orcaPage), {
timeout: 5_000,
message: 'live TUI cursor stayed hidden after hidden output stayed live'
message: 'live TUI cursor stayed hidden after hidden output restored'
})
.toMatchObject({
hidden: false,
@@ -358,9 +376,10 @@ test.describe('Hidden terminal TUI visual restore', () => {
path: screenshotPath,
contentType: 'image/png'
})
rmSync(scriptPath, { force: true })
})
test('keeps hidden terminal side effects live while hidden output stays live', async ({
test('keeps hidden terminal side effects live while hidden output may restore', async ({
orcaPage
}) => {
await waitForSessionReady(orcaPage)
@@ -396,12 +415,6 @@ test.describe('Hidden terminal TUI visual restore', () => {
await resetHiddenDebug(orcaPage)
await writeHiddenSideEffectBurst(orcaPage, hiddenPane.ptyId, hiddenTitle, marker)
await expect
.poll(async () => (await readHiddenDebug(orcaPage))?.hiddenRendererSkipCount ?? 0, {
timeout: 10_000,
message: 'hidden side-effect output should stay on the live xterm path for release'
})
.toBe(0)
await expect
.poll(() => getRuntimePaneTitle(orcaPage, hiddenSnapshot.tabId, hiddenPane.numericPaneId), {
timeout: 10_000,