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 }