From d84d9705f3d19e69c5f8d720ee080e6c60573396 Mon Sep 17 00:00:00 2001 From: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com> Date: Sun, 5 Jul 2026 04:10:52 -0400 Subject: [PATCH] fix(terminal): skip PSReadLine repaint nudge before shell-ready MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The form feed was written directly to the subprocess, bypassing Session write ordering. Routing it through write() would be worse — a queued form feed flushes after the buffered startup command at an arbitrary later moment, when the foreground/prompt gates no longer hold. The nudge is cosmetic, so skip it during the pre-ready window instead. --- src/main/daemon/session.test.ts | 14 ++++++++++++++ src/main/daemon/session.ts | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/src/main/daemon/session.test.ts b/src/main/daemon/session.test.ts index dec1f0df230..478b4ea99f0 100644 --- a/src/main/daemon/session.test.ts +++ b/src/main/daemon/session.test.ts @@ -477,6 +477,20 @@ describe('Session', () => { expect(subprocess.written).toEqual([]) }) + it('does not send or queue a form feed before shell-ready', async () => { + createSession({ shellReadySupported: true }) + subprocess.foregroundProcess = 'powershell.exe' + subprocess.simulateData('PS C:\\Users\\me> ') + await vi.advanceTimersByTimeAsync(10) + // Why: a queued form feed would flush after the startup command at an + // arbitrary later moment, when the prompt gates no longer hold. + withPlatform('win32', () => session.clearScrollback()) + expect(subprocess.written).toEqual([]) + subprocess.simulateData('\x1b]777;orca-shell-ready\x07\r\nPS C:\\Users\\me> ') + await vi.advanceTimersByTimeAsync(10) + expect(subprocess.written).toEqual([]) + }) + it('does not send a form feed at a PowerShell continuation prompt', async () => { createSession() subprocess.foregroundProcess = 'powershell.exe' diff --git a/src/main/daemon/session.ts b/src/main/daemon/session.ts index 02ef167a80d..d156aeb4802 100644 --- a/src/main/daemon/session.ts +++ b/src/main/daemon/session.ts @@ -305,6 +305,13 @@ export class Session { if (process.platform !== 'win32') { return } + // Why: before shell-ready, write() would queue the form feed behind the + // buffered startup command and deliver it at an arbitrary later moment, + // when the foreground/prompt gates below no longer hold. The nudge is + // cosmetic — skip it rather than defer it. + if (this._shellState === 'pending' || this.postReadyFlushGate.isPending) { + return + } if (!isPowerShellProcess(this.subprocess.getForegroundProcess())) { return }