From 49edd9ae4dc8b8fe943046dfc7ad4d601cd08bc9 Mon Sep 17 00:00:00 2001 From: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Date: Sun, 5 Jul 2026 19:33:31 -0700 Subject: [PATCH] Fix terminal tab icon detection for foreground agents - Register with bash-preexec's preexec_functions array to prevent its DEBUG trap re-arming from silencing Orca's command-start signals. - Serve the last-resolved identity past its cache TTL (stale-while- revalidate) while the active foreground process is a wrapper. - Reschedule confirming reads on duplicate OSC 133;D sequences to prevent nested shells from prematurely clearing tab identities. - Trigger self-limiting foreground sampling on visible PTY binding, Enter keystrokes, and pane focus changes. --- CODEX_ICON_DEBUG.diff | 1200 +++++++++++++++++ CODEX_ICON_DEBUG_HANDOFF.md | 82 ++ fresh-launch.png | Bin 0 -> 60436 bytes grok-detected.png | Bin 0 -> 142449 bytes src/main/daemon/pty-subprocess.test.ts | 75 ++ src/main/daemon/pty-subprocess.ts | 22 + src/main/daemon/shell-ready.test.ts | 28 + src/main/daemon/shell-ready.ts | 17 + .../pane-foreground-agent-tracker.test.ts | 221 ++- .../pane-foreground-agent-tracker.ts | 136 +- .../terminal-pane/pty-connection.test.ts | 243 +++- .../terminal-pane/pty-connection.ts | 116 +- .../use-terminal-pane-lifecycle.ts | 7 + 13 files changed, 2121 insertions(+), 26 deletions(-) create mode 100644 CODEX_ICON_DEBUG.diff create mode 100644 CODEX_ICON_DEBUG_HANDOFF.md create mode 100644 fresh-launch.png create mode 100644 grok-detected.png diff --git a/CODEX_ICON_DEBUG.diff b/CODEX_ICON_DEBUG.diff new file mode 100644 index 00000000000..3021cd74924 --- /dev/null +++ b/CODEX_ICON_DEBUG.diff @@ -0,0 +1,1200 @@ +diff --git a/src/main/daemon/pty-subprocess.test.ts b/src/main/daemon/pty-subprocess.test.ts +index 85366a137..b23c83656 100644 +--- a/src/main/daemon/pty-subprocess.test.ts ++++ b/src/main/daemon/pty-subprocess.test.ts +@@ -367,6 +367,81 @@ describe('createPtySubprocess', () => { + } + }) + ++ it('serves the resolved agent identity past the cache TTL while a wrapper holds the foreground', async () => { ++ vi.useFakeTimers() ++ vi.setSystemTime(new Date('2026-06-16T12:00:00.000Z')) ++ const proc = mockPtyProcess() ++ proc.process = 'node' ++ spawnMock.mockReturnValue(proc) ++ const platform = Object.getOwnPropertyDescriptor(process, 'platform') ++ Object.defineProperty(process, 'platform', { value: 'darwin' }) ++ resolveAgentForegroundProcessMock.mockResolvedValue('grok') ++ ++ try { ++ const handle = createPtySubprocess({ ++ sessionId: 'test', ++ cols: 80, ++ rows: 24 ++ }) ++ ++ expect(handle.getForegroundProcess()).toBe('node') ++ await Promise.resolve() ++ await Promise.resolve() ++ expect(handle.getForegroundProcess()).toBe('grok') ++ ++ // Why: renderer reads poll slower than the 1s cache TTL — an expired ++ // cache must keep answering with the resolved identity, not the wrapper. ++ vi.advanceTimersByTime(1_500) ++ expect(handle.getForegroundProcess()).toBe('grok') ++ } finally { ++ vi.useRealTimers() ++ if (platform) { ++ Object.defineProperty(process, 'platform', platform) ++ } ++ } ++ }) ++ ++ it('clears an expired identity when the wrapper tree no longer resolves to an agent', async () => { ++ vi.useFakeTimers() ++ vi.setSystemTime(new Date('2026-06-16T12:00:00.000Z')) ++ const proc = mockPtyProcess() ++ proc.process = 'node' ++ spawnMock.mockReturnValue(proc) ++ const platform = Object.getOwnPropertyDescriptor(process, 'platform') ++ Object.defineProperty(process, 'platform', { value: 'darwin' }) ++ resolveAgentForegroundProcessMock.mockResolvedValueOnce('grok').mockResolvedValue('node') ++ ++ try { ++ const handle = createPtySubprocess({ ++ sessionId: 'test', ++ cols: 80, ++ rows: 24 ++ }) ++ ++ expect(handle.getForegroundProcess()).toBe('node') ++ await Promise.resolve() ++ await Promise.resolve() ++ expect(handle.getForegroundProcess()).toBe('grok') ++ // Flush the first refresh's finally so the next read can revalidate. ++ await Promise.resolve() ++ await Promise.resolve() ++ ++ // An unrelated wrapper (e.g. npm) now owns the pane: the stale-served ++ // identity is revalidated and dropped once the refresh finds no agent. ++ vi.advanceTimersByTime(1_500) ++ expect(handle.getForegroundProcess()).toBe('grok') ++ await Promise.resolve() ++ await Promise.resolve() ++ await Promise.resolve() ++ expect(handle.getForegroundProcess()).toBe('node') ++ } finally { ++ vi.useRealTimers() ++ if (platform) { ++ Object.defineProperty(process, 'platform', platform) ++ } ++ } ++ }) ++ + it('serves daemon Windows wrapper agent foreground from an async cache', async () => { + const proc = mockPtyProcess() + proc.process = 'node.exe' +diff --git a/src/main/daemon/pty-subprocess.ts b/src/main/daemon/pty-subprocess.ts +index 6dd0554bb..09f66a987 100644 +--- a/src/main/daemon/pty-subprocess.ts ++++ b/src/main/daemon/pty-subprocess.ts +@@ -937,6 +937,16 @@ export function createPtySubprocess(opts: PtySubprocessOptions): SubprocessHandl + ) { + cachedAgentForeground = null + startupAgentForeground = null ++ } else if ( ++ cachedAgentForeground !== null && ++ Date.now() - cachedAgentForeground.refreshedAt > FOREGROUND_AGENT_CACHE_TTL_MS && ++ currentFallbackProcess !== null && ++ isAgentForegroundWrapperProcess(currentFallbackProcess) ++ ) { ++ // Why: the wrapper's tree no longer resolves to an agent — an expired ++ // identity must not transfer to an unrelated wrapper (e.g. npm right ++ // after an agent exit). Fresh identities survive one-off scan hiccups. ++ cachedAgentForeground = null + } + return + } +@@ -994,6 +1004,18 @@ export function createPtySubprocess(opts: PtySubprocessOptions): SubprocessHandl + ) { + return cachedAgentForeground.processName + } ++ // Why: a wrapper foreground (node/python) can never identify itself, and ++ // readers poll slower than the cache TTL — returning the raw wrapper here ++ // would hide the resolved identity forever. Serve the last resolved agent ++ // while the scheduled refresh revalidates; exit truth is safe because an ++ // exited agent's foreground falls back to the shell, not a wrapper. ++ if ( ++ cachedAgentForeground && ++ fallbackProcess !== null && ++ isAgentForegroundWrapperProcess(fallbackProcess) ++ ) { ++ return cachedAgentForeground.processName ++ } + const activeStartupAgentForeground = getActiveStartupAgentForeground(now) + if (fallbackProcess && isShellProcess(fallbackProcess) && activeStartupAgentForeground) { + return activeStartupAgentForeground.processName +diff --git a/src/main/daemon/shell-ready.test.ts b/src/main/daemon/shell-ready.test.ts +index 860e3f27a..ce1a67da7 100644 +--- a/src/main/daemon/shell-ready.test.ts ++++ b/src/main/daemon/shell-ready.test.ts +@@ -556,6 +556,34 @@ describePosix('daemon shell-ready launch config', () => { + } + ) + ++ itWithBash( ++ 'still emits 133;C when bash-preexec re-arms the DEBUG trap at first prompt', ++ async () => { ++ const { getDaemonBashShellReadyRcfileContent } = await importFreshShellReady() ++ // Minimal bash-preexec imitation (iTerm2/starship setups): re-arms its own ++ // DEBUG trap from PROMPT_COMMAND at the first prompt — silencing Orca's ++ // trap — and dispatches preexec_functions with the command as $1. ++ writeFileSync( ++ join(userDataPath, '.bash_profile'), ++ [ ++ 'preexec_functions=()', ++ '__bp_preexec_invoke_exec() {', ++ ' [[ -n "${__bp_interactive_mode:-}" ]] || return', ++ ' __bp_interactive_mode=""', ++ ' local f', ++ ' for f in "${preexec_functions[@]}"; do "$f" "$BASH_COMMAND"; done', ++ '}', ++ "__bp_arm() { __bp_interactive_mode=1; trap '__bp_preexec_invoke_exec' DEBUG; }", ++ 'PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND;}__bp_arm"' ++ ].join('\n') ++ ) ++ ++ const output = runInteractiveBashRcfile(getDaemonBashShellReadyRcfileContent(), userDataPath) ++ ++ expectBashOsc133Lifecycle(output) ++ } ++ ) ++ + itWithBash('normalizes array PROMPT_COMMAND hooks so bash 3.2 still runs cleanup', async () => { + const { getDaemonBashShellReadyRcfileContent } = await importFreshShellReady() + writeFileSync( +diff --git a/src/main/daemon/shell-ready.ts b/src/main/daemon/shell-ready.ts +index 7ad5a686b..e31949e5b 100644 +--- a/src/main/daemon/shell-ready.ts ++++ b/src/main/daemon/shell-ready.ts +@@ -195,6 +195,23 @@ if [[ -n "$__orca_debug_trap_spec" ]]; then + fi + unset __orca_debug_trap_spec __orca_debug_trap_command + unset -f __orca_normalize_prompt_command __orca_prepend_prompt_command __orca_append_prompt_command ++# Why: bash-preexec (pulled in by iTerm2/starship setups) re-arms its own DEBUG ++# trap at the first prompt, silencing ours. Register with its preexec_functions ++# array too; both paths gate on __orca_in_command, so whichever mechanism ends ++# up owning the trap, C is emitted exactly once per command. ++__orca_osc133_preexec_bp() { ++ [[ -z "\${__orca_in_command:-}" ]] || return ++ [[ -z "\${__orca_in_prompt_command:-}" ]] || return ++ case "\${1:-}" in ++ *__orca_osc133_precmd*|*__orca_osc133_prompt_done*|*__orca_prompt_mark*) return ;; ++ esac ++ printf "\\033]133;C\\007" ++ __orca_in_command=1 ++} ++case " \${preexec_functions[*]:-} " in ++ *" __orca_osc133_preexec_bp "*) ;; ++ *) preexec_functions+=(__orca_osc133_preexec_bp) ;; ++esac + # Why: arm DEBUG after wrapper setup; otherwise bash treats our own rcfile + # commands as a foreground command and emits a fake C/D before the first prompt. + trap '__orca_osc133_preexec' DEBUG +diff --git a/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.test.ts b/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.test.ts +index 5a2e8c258..ab5aaa03b 100644 +--- a/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.test.ts ++++ b/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.test.ts +@@ -5,12 +5,14 @@ import { createPaneForegroundAgentTracker } from './pane-foreground-agent-tracke + import type { PaneForegroundAgentEntry } from '@/store/slices/pane-foreground-agent' + + const COMMAND_SETTLE_MS = 350 ++const VISIBLE_PTY_SETTLE_MS = 350 + const WRAPPER_RESOLVE_RETRY_MS = 1200 + const SECOND_WRAPPER_RETRY_MS = 3500 + + describe('createPaneForegroundAgentTracker', () => { + const readForegroundProcess = vi.fn<(ptyId: string) => Promise>() + const publish = vi.fn<(entry: PaneForegroundAgentEntry) => void>() ++ const onConfirmedShellForeground = vi.fn<() => void>() + let ptyId: string | null = 'pty-1' + + function makeTracker(): ReturnType { +@@ -18,7 +20,8 @@ describe('createPaneForegroundAgentTracker', () => { + getPtyId: () => ptyId, + isTrackablePtyId: (id) => !id.startsWith('remote:') && !id.startsWith('ssh:'), + readForegroundProcess, +- publish ++ publish, ++ onConfirmedShellForeground + }) + } + +@@ -30,6 +33,7 @@ describe('createPaneForegroundAgentTracker', () => { + vi.useFakeTimers() + readForegroundProcess.mockReset() + publish.mockReset() ++ onConfirmedShellForeground.mockReset() + ptyId = 'pty-1' + }) + +@@ -52,6 +56,72 @@ describe('createPaneForegroundAgentTracker', () => { + expect(publish).toHaveBeenLastCalledWith({ agent: 'claude', shellForeground: false }) + }) + ++ it('reads the foreground for a visible PTY so restored running Codex panes regain identity', async () => { ++ readForegroundProcess.mockResolvedValue('codex') ++ const tracker = makeTracker() ++ ++ tracker.onVisiblePtyBound() ++ expect(readForegroundProcess).not.toHaveBeenCalled() ++ ++ await flushSettleRead(VISIBLE_PTY_SETTLE_MS) ++ ++ expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') ++ expect(publish).toHaveBeenLastCalledWith({ agent: 'codex', shellForeground: false }) ++ }) ++ ++ it('does not retry or publish visible PTY reads for an idle shell foreground', async () => { ++ readForegroundProcess.mockResolvedValue('zsh') ++ const tracker = makeTracker() ++ ++ tracker.onVisiblePtyBound() ++ await flushSettleRead( ++ VISIBLE_PTY_SETTLE_MS + WRAPPER_RESOLVE_RETRY_MS + SECOND_WRAPPER_RETRY_MS + 10_000 ++ ) ++ ++ expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') ++ expect(publish).not.toHaveBeenCalled() ++ }) ++ ++ it('lets command-start sampling supersede a pending visible PTY read', async () => { ++ readForegroundProcess.mockResolvedValue('codex') ++ const tracker = makeTracker() ++ ++ tracker.onVisiblePtyBound() ++ tracker.onCommandStarted() ++ await flushSettleRead(VISIBLE_PTY_SETTLE_MS) ++ ++ expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') ++ expect(publish).toHaveBeenLastCalledWith({ agent: 'codex', shellForeground: false }) ++ }) ++ ++ it('does not let visible PTY sampling downgrade pending command-start sampling', async () => { ++ readForegroundProcess.mockResolvedValueOnce('bash').mockResolvedValueOnce('codex') ++ const tracker = makeTracker() ++ ++ tracker.onCommandStarted() ++ tracker.onVisiblePtyBound() ++ await flushSettleRead(COMMAND_SETTLE_MS) ++ expect(readForegroundProcess).toHaveBeenCalledTimes(1) ++ ++ await flushSettleRead(WRAPPER_RESOLVE_RETRY_MS) ++ expect(readForegroundProcess).toHaveBeenCalledTimes(2) ++ expect(publish).toHaveBeenLastCalledWith({ agent: 'codex', shellForeground: false }) ++ }) ++ ++ it('retries visible PTY reads only while a foreground wrapper may resolve to an agent', async () => { ++ readForegroundProcess.mockResolvedValueOnce('node').mockResolvedValueOnce('codex') ++ const tracker = makeTracker() ++ ++ tracker.onVisiblePtyBound() ++ await flushSettleRead(VISIBLE_PTY_SETTLE_MS) ++ expect(readForegroundProcess).toHaveBeenCalledTimes(1) ++ expect(publish).not.toHaveBeenCalled() ++ ++ await flushSettleRead(WRAPPER_RESOLVE_RETRY_MS) ++ expect(readForegroundProcess).toHaveBeenCalledTimes(2) ++ expect(publish).toHaveBeenLastCalledWith({ agent: 'codex', shellForeground: false }) ++ }) ++ + it('re-reads on a bounded ladder while the read still sees an interpreter wrapper', async () => { + // Why: daemon shell/helper→agent ancestry resolution has been observed to + // take >1.5s for real node-wrapped CLIs, so the ladder gets two re-reads. +@@ -124,18 +194,161 @@ describe('createPaneForegroundAgentTracker', () => { + expect(readForegroundProcess).not.toHaveBeenCalled() + }) + +- it('cancels a pending read when the command finishes first', async () => { ++ it('confirms a rapid command start->finish instead of trusting the D', async () => { ++ // Why: a leaked nested-shell 133;C->133;D pair (or a fast real command) ++ // cancels the command-start read; confirm the foreground so a still-running ++ // manual agent with no launchAgent/hook keeps its identity. + readForegroundProcess.mockResolvedValue('claude') + const tracker = makeTracker() + + tracker.onCommandStarted() + tracker.onCommandFinished() +- await flushSettleRead(COMMAND_SETTLE_MS + WRAPPER_RESOLVE_RETRY_MS) ++ await flushSettleRead(COMMAND_SETTLE_MS) + ++ expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') ++ expect(publish).toHaveBeenLastCalledWith({ agent: 'claude', shellForeground: false }) ++ expect(publish).not.toHaveBeenCalledWith({ agent: null, shellForeground: true }) ++ }) ++ ++ it('confirms duplicate 133;D pairs instead of fast-pathing past the pending confirmation', async () => { ++ // Why: user shell integrations (iTerm/VS Code) double up Orca's OSC 133, so ++ // every D arrives twice ~50ms apart. The second D cancels the first D's ++ // confirming read; it must reschedule the confirmation, not trust the D. ++ readForegroundProcess.mockResolvedValue('grok') ++ const tracker = makeTracker() ++ ++ tracker.onCommandStarted() ++ tracker.onCommandStarted() ++ tracker.onCommandFinished() ++ await flushSettleRead(50) ++ tracker.onCommandFinished() ++ await flushSettleRead(COMMAND_SETTLE_MS) ++ ++ expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') ++ expect(publish).toHaveBeenLastCalledWith({ agent: 'grok', shellForeground: false }) ++ expect(publish).not.toHaveBeenCalledWith({ agent: null, shellForeground: true }) ++ }) ++ ++ it('still marks shell without a read for a duplicate D pair on an idle pane', async () => { ++ const tracker = makeTracker() ++ ++ tracker.onCommandFinished() ++ await flushSettleRead(50) ++ tracker.onCommandFinished() ++ await flushSettleRead(COMMAND_SETTLE_MS) ++ ++ // Why: with no command read in flight the first D takes the no-RPC path, ++ // so its duplicate has nothing to re-confirm and stays RPC-free too. + expect(readForegroundProcess).not.toHaveBeenCalled() ++ expect(publish).toHaveBeenCalledTimes(2) + expect(publish).toHaveBeenLastCalledWith({ agent: null, shellForeground: true }) + }) + ++ it('marks shell on a rapid command start->finish when the foreground is a shell', async () => { ++ readForegroundProcess.mockResolvedValue('zsh') ++ const tracker = makeTracker() ++ ++ tracker.onCommandStarted() ++ tracker.onCommandFinished() ++ await flushSettleRead(COMMAND_SETTLE_MS) ++ ++ expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') ++ expect(publish).toHaveBeenLastCalledWith({ agent: null, shellForeground: true }) ++ }) ++ ++ it('confirms the foreground before clearing a pane an agent has owned', async () => { ++ readForegroundProcess.mockResolvedValue('codex') ++ const tracker = makeTracker() ++ ++ tracker.onCommandStarted() ++ await flushSettleRead(COMMAND_SETTLE_MS) ++ expect(publish).toHaveBeenLastCalledWith({ agent: 'codex', shellForeground: false }) ++ ++ publish.mockClear() ++ readForegroundProcess.mockClear() ++ tracker.onCommandFinished() ++ // Why: a leaked nested-shell 133;D must not clear Codex before the read. ++ expect(publish).not.toHaveBeenCalled() ++ ++ await flushSettleRead(COMMAND_SETTLE_MS) ++ expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') ++ expect(publish).toHaveBeenLastCalledWith({ agent: 'codex', shellForeground: false }) ++ expect(publish).not.toHaveBeenCalledWith({ agent: null, shellForeground: true }) ++ }) ++ ++ it('marks shell foreground when the confirming read shows the agent is gone', async () => { ++ readForegroundProcess.mockResolvedValueOnce('codex').mockResolvedValueOnce('zsh') ++ const tracker = makeTracker() ++ ++ tracker.onCommandStarted() ++ await flushSettleRead(COMMAND_SETTLE_MS) ++ ++ publish.mockClear() ++ tracker.onCommandFinished() ++ await flushSettleRead(COMMAND_SETTLE_MS) ++ ++ expect(readForegroundProcess).toHaveBeenLastCalledWith('pty-1') ++ expect(publish).toHaveBeenLastCalledWith({ agent: null, shellForeground: true }) ++ }) ++ ++ it('signals confirmed shell foreground only when the read proves the agent exited', async () => { ++ // Reads: command-start=codex, first finish=codex (still running), second finish=zsh (exited). ++ readForegroundProcess ++ .mockResolvedValueOnce('codex') ++ .mockResolvedValueOnce('codex') ++ .mockResolvedValueOnce('zsh') ++ const tracker = makeTracker() ++ ++ tracker.onCommandStarted() ++ await flushSettleRead(COMMAND_SETTLE_MS) ++ ++ // A leaked nested-shell 133;D while Codex still owns the foreground: no signal. ++ tracker.onCommandFinished() ++ await flushSettleRead(COMMAND_SETTLE_MS) ++ expect(onConfirmedShellForeground).not.toHaveBeenCalled() ++ ++ // Genuine exit -> read sees a shell -> signal fires exactly once. ++ tracker.onCommandFinished() ++ await flushSettleRead(COMMAND_SETTLE_MS) ++ expect(onConfirmedShellForeground).toHaveBeenCalledTimes(1) ++ }) ++ ++ it('returns to the no-RPC finished path after the agent is confirmed gone', async () => { ++ readForegroundProcess.mockResolvedValueOnce('codex').mockResolvedValueOnce('zsh') ++ const tracker = makeTracker() ++ ++ tracker.onCommandStarted() ++ await flushSettleRead(COMMAND_SETTLE_MS) ++ tracker.onCommandFinished() ++ await flushSettleRead(COMMAND_SETTLE_MS) ++ ++ publish.mockClear() ++ readForegroundProcess.mockClear() ++ tracker.onCommandFinished() ++ ++ expect(readForegroundProcess).not.toHaveBeenCalled() ++ expect(publish).toHaveBeenCalledExactlyOnceWith({ agent: null, shellForeground: true }) ++ }) ++ ++ it('confirms a command finished for a launch-known agent pane before any read', async () => { ++ readForegroundProcess.mockResolvedValue('codex') ++ const tracker = createPaneForegroundAgentTracker({ ++ getPtyId: () => ptyId, ++ isTrackablePtyId: (id) => !id.startsWith('remote:') && !id.startsWith('ssh:'), ++ readForegroundProcess, ++ publish, ++ hasKnownAgentIdentity: () => true ++ }) ++ ++ tracker.onCommandFinished() ++ // Why: launchAgent/hook identity means the 133;D is confirmed, not trusted. ++ expect(publish).not.toHaveBeenCalled() ++ ++ await flushSettleRead(COMMAND_SETTLE_MS) ++ expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') ++ expect(publish).toHaveBeenLastCalledWith({ agent: 'codex', shellForeground: false }) ++ }) ++ + it('never reads or publishes for remote or ssh panes', async () => { + ptyId = 'remote:web-env-1@@terminal-1' + const tracker = makeTracker() +diff --git a/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.ts b/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.ts +index 1af2f78fd..8e9d37327 100644 +--- a/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.ts ++++ b/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.ts +@@ -1,4 +1,7 @@ +-import { recognizeAgentProcess } from '../../../../shared/agent-process-recognition' ++import { ++ isAgentForegroundWrapperProcess, ++ recognizeAgentProcess ++} from '../../../../shared/agent-process-recognition' + import type { PaneForegroundAgentEntry } from '@/store/slices/pane-foreground-agent' + + // Why: the read must land after the shell has exec'd the command; and when it +@@ -6,7 +9,9 @@ import type { PaneForegroundAgentEntry } from '@/store/slices/pane-foreground-ag + // asynchronously — observed to take >1.5s for real node-wrapped CLIs — so + // give its cache two bounded re-reads, not an open-ended retry loop. + const COMMAND_SETTLE_MS = 350 ++const VISIBLE_PTY_SETTLE_MS = 350 + const WRAPPER_RESOLVE_RETRY_DELAYS_MS = [1200, 3500] as const ++type ForegroundReadReason = 'command' | 'visible-pty' | 'command-finished' + + type PaneForegroundAgentTrackerDeps = { + getPtyId: () => string | null +@@ -15,22 +20,39 @@ type PaneForegroundAgentTrackerDeps = { + isTrackablePtyId: (ptyId: string) => boolean + readForegroundProcess: (ptyId: string) => Promise + publish: (entry: PaneForegroundAgentEntry) => void ++ /** True when the pane is otherwise known to run an agent (launchAgent, live ++ * hook status). Lets a restored agent pane confirm — rather than trust — a ++ * 133;D before any command-start read has recorded its own evidence. */ ++ hasKnownAgentIdentity?: () => boolean ++ /** Fired when a confirming read proves the foreground genuinely returned to a ++ * shell (agent exited). Lets callers clear a stale agent-named tab title that ++ * the shell never repaints. */ ++ onConfirmedShellForeground?: () => void + } + + /** + * Publishes process-table identity for a pane at OSC 133 command boundaries: + * one foreground read when a command starts (that is when the foreground +- * changes), and a no-RPC shell-foreground mark when it finishes — 133;D is +- * the ONLY source of shell-foreground proof; reads never produce it. ++ * changes), and a shell-foreground mark when it finishes. A 133;D is normally ++ * the shell-foreground proof; for a pane an agent has owned it is confirmed by a ++ * foreground read first, because a full-screen agent's nested command shells ++ * leak their own 133;D onto the main PTY. + */ + export function createPaneForegroundAgentTracker(deps: PaneForegroundAgentTrackerDeps): { ++ onVisiblePtyBound: () => void + onCommandStarted: () => void + onCommandFinished: () => void + dispose: () => void + } { + let disposed = false +- let readTimer: number | null = null ++ let readTimer: ReturnType | null = null ++ let scheduledReadReason: ForegroundReadReason | null = null ++ let activeReadReason: ForegroundReadReason | null = null + let readGeneration = 0 ++ // Why: a full-screen agent (Codex, etc.) runs nested command shells whose own ++ // OSC 133;D leaks onto the main PTY. For a pane an agent has owned, that D is ++ // not proof the prompt returned, so confirm the foreground before clearing. ++ let hasForegroundAgentEvidence = false + + const trackablePtyId = (): string | null => { + const ptyId = deps.getPtyId() +@@ -40,30 +62,53 @@ export function createPaneForegroundAgentTracker(deps: PaneForegroundAgentTracke + const cancelPendingRead = (): void => { + readGeneration += 1 + if (readTimer !== null) { +- window.clearTimeout(readTimer) ++ clearTimeout(readTimer) + readTimer = null + } ++ scheduledReadReason = null ++ activeReadReason = null + } + +- const scheduleRead = (delayMs: number, retryIndex: number): void => { ++ const scheduleRead = ( ++ delayMs: number, ++ retryIndex: number, ++ reason: ForegroundReadReason ++ ): void => { + const generation = readGeneration +- readTimer = window.setTimeout(() => { ++ scheduledReadReason = reason ++ readTimer = setTimeout(() => { + readTimer = null +- void readForeground(generation, retryIndex) ++ scheduledReadReason = null ++ activeReadReason = reason ++ void readForeground(generation, retryIndex, reason).finally(() => { ++ if (generation === readGeneration && activeReadReason === reason) { ++ activeReadReason = null ++ } ++ }) + }, delayMs) + } + +- async function readForeground(generation: number, retryIndex: number): Promise { ++ async function readForeground( ++ generation: number, ++ retryIndex: number, ++ reason: ForegroundReadReason ++ ): Promise { + const ptyId = trackablePtyId() + if (disposed || generation !== readGeneration || !ptyId) { + return + } +- const processName = await deps.readForegroundProcess(ptyId).catch(() => null) ++ let processName: string | null = null ++ try { ++ processName = await deps.readForegroundProcess(ptyId) ++ } catch { ++ processName = null ++ } + if (disposed || generation !== readGeneration) { + return + } + const recognized = recognizeAgentProcess(processName) + if (recognized) { ++ hasForegroundAgentEvidence = true + deps.publish({ agent: recognized.agent, shellForeground: false }) + return + } +@@ -72,14 +117,50 @@ export function createPaneForegroundAgentTracker(deps: PaneForegroundAgentTracke + // a nested one (sh/bash without integration); marking shell-foreground + // would suppress live title identity. Only 133;D proves the prompt. + const retryDelay = WRAPPER_RESOLVE_RETRY_DELAYS_MS[retryIndex] +- if (retryDelay !== undefined && processName) { +- scheduleRead(retryDelay, retryIndex + 1) ++ const shouldRetry = ++ retryDelay !== undefined && ++ processName && ++ (reason === 'command' || isAgentForegroundWrapperProcess(processName)) ++ if (shouldRetry) { ++ scheduleRead(retryDelay, retryIndex + 1, reason) ++ return ++ } ++ if (reason === 'command') { ++ deps.publish({ agent: null, shellForeground: false }) + return + } +- deps.publish({ agent: null, shellForeground: false }) ++ if (reason === 'command-finished') { ++ // Why: the 133;D fired AND the foreground shows no agent — together that is ++ // real prompt proof, so the agent truly exited. Reset the evidence so the ++ // pane's ordinary shell commands go back to the no-RPC finished path. ++ hasForegroundAgentEvidence = false ++ deps.publish({ agent: null, shellForeground: true }) ++ // Why: confirmed exit — let callers clear a stale agent title the shell ++ // won't repaint (a plain `codex`/`grok` leaves its OSC title behind). ++ deps.onConfirmedShellForeground?.() ++ } + } + + return { ++ onVisiblePtyBound() { ++ // Why: command-start and command-finished reads own the exit decision; ++ // visibility recovery is lower-authority and must never cancel them. ++ if ( ++ scheduledReadReason === 'command' || ++ activeReadReason === 'command' || ++ scheduledReadReason === 'command-finished' || ++ activeReadReason === 'command-finished' ++ ) { ++ return ++ } ++ cancelPendingRead() ++ if (!trackablePtyId()) { ++ return ++ } ++ // Why: restored/manual agent panes can become visible while Codex is ++ // already foreground, so no OSC 133 command-start event will seed the tab icon. ++ scheduleRead(VISIBLE_PTY_SETTLE_MS, 0, 'visible-pty') ++ }, + onCommandStarted() { + cancelPendingRead() + if (!trackablePtyId()) { +@@ -88,14 +169,39 @@ export function createPaneForegroundAgentTracker(deps: PaneForegroundAgentTracke + // Why: the foreground left the prompt the moment C fired — stale + // shell-foreground evidence must not clear the command that just started. + deps.publish({ agent: null, shellForeground: false }) +- scheduleRead(COMMAND_SETTLE_MS, 0) ++ scheduleRead(COMMAND_SETTLE_MS, 0, 'command') + }, + onCommandFinished() { ++ // Why: a rapid 133;C→133;D pair cancels the command-start read before it ++ // can identify the foreground — that pair is exactly a leaked nested-shell ++ // command under a full-screen agent (or a fast real shell command), so on a ++ // no-identity pane confirm it rather than trusting the D as a prompt return. ++ // A pending confirming read counts too: user shell integrations double up ++ // Orca's OSC 133, and the duplicate D must re-confirm, not fast-path past ++ // the in-flight confirmation it just cancelled. ++ const commandReadWasPending = ++ scheduledReadReason === 'command' || ++ activeReadReason === 'command' || ++ scheduledReadReason === 'command-finished' || ++ activeReadReason === 'command-finished' + cancelPendingRead() + if (!trackablePtyId()) { + return + } +- deps.publish({ agent: null, shellForeground: true }) ++ // Why: trust the 133;D and mark shell without an RPC only when nothing hints ++ // at an agent — no prior agent evidence, no launch/hook identity, and no ++ // command-start read racing this finish. ++ if ( ++ !hasForegroundAgentEvidence && ++ deps.hasKnownAgentIdentity?.() !== true && ++ !commandReadWasPending ++ ) { ++ deps.publish({ agent: null, shellForeground: true }) ++ return ++ } ++ // Why: confirm the foreground before clearing — if the agent still owns it, ++ // the read republishes its identity; only a genuine shell result clears it. ++ scheduleRead(COMMAND_SETTLE_MS, 0, 'command-finished') + }, + dispose() { + disposed = true +diff --git a/src/renderer/src/components/terminal-pane/pty-connection.test.ts b/src/renderer/src/components/terminal-pane/pty-connection.test.ts +index 383d5d141..8d42ebb39 100644 +--- a/src/renderer/src/components/terminal-pane/pty-connection.test.ts ++++ b/src/renderer/src/components/terminal-pane/pty-connection.test.ts +@@ -21,6 +21,7 @@ import { + beginAgentStartupDeliveryAttempt, + resetAgentStartupDelayedDeliveryForTests + } from '@/lib/agent-startup-delayed-delivery' ++import type { PaneForegroundAgentEntry } from '@/store/slices/pane-foreground-agent' + + // Repro command: + // pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/terminal-pane/pty-connection.test.ts -t "OpenTUI-style small ANSI redraw" +@@ -169,6 +170,7 @@ type StoreState = { + consumePendingSnapshot: ReturnType + runtimePaneTitlesByTabId: Record> + agentStatusByPaneKey: Record ++ paneForegroundAgentByPaneKey: Record + sleepingAgentSessionsByPaneKey: Record + agentLaunchConfigByPaneKey: Record + getAgentLaunchConfigForStatusEntry: ReturnType +@@ -737,6 +739,7 @@ describe('connectPanePty', () => { + consumePendingSnapshot: vi.fn(() => null), + runtimePaneTitlesByTabId: {}, + agentStatusByPaneKey: {}, ++ paneForegroundAgentByPaneKey: {}, + sleepingAgentSessionsByPaneKey: {}, + agentLaunchConfigByPaneKey: {}, + getAgentLaunchConfigForStatusEntry: vi.fn((entry: { paneKey: string }) => { +@@ -771,8 +774,12 @@ describe('connectPanePty', () => { + ), + removeAgentStatus: vi.fn(), + dropAgentStatus: vi.fn(), +- setPaneForegroundAgent: vi.fn(), +- clearPaneForegroundAgent: vi.fn(), ++ setPaneForegroundAgent: vi.fn((paneKey: string, entry: PaneForegroundAgentEntry) => { ++ mockStoreState.paneForegroundAgentByPaneKey[paneKey] = entry ++ }), ++ clearPaneForegroundAgent: vi.fn((paneKey: string) => { ++ delete mockStoreState.paneForegroundAgentByPaneKey[paneKey] ++ }), + markTerminalTabUnread: vi.fn(), + markTerminalPaneUnread: vi.fn(), + markAgentCompletionPaneUnread: vi.fn() +@@ -13949,6 +13956,240 @@ describe('connectPanePty', () => { + }) + }) + ++ describe('visible foreground agent sampling (perf)', () => { ++ const VISIBLE_PTY_SETTLE_MS = 350 ++ ++ // Why: every connectPanePty binding in this file shares the tab-1/LEAF_1 pane ++ // key, and an undisposed reattach binding elsewhere can resolve a foreground ++ // read into this test's store slice. Give each sampling case its own tabId so ++ // no other test's publish can pollute the pane identity it asserts on. ++ async function connectRestoredPaneForForegroundSampling(args: { ++ ptyId?: string ++ tabId?: string ++ isVisibleRef?: { current: boolean } ++ } = {}): Promise<{ ++ binding: { noteVisibilityResume: () => void } ++ deps: ReturnType ++ transport: MockTransport ++ cacheKey: string ++ }> { ++ const { connectPanePty } = await import('./pty-connection') ++ const ptyId = args.ptyId ?? 'tab-pty' ++ const tabId = args.tabId ?? `tab-${ptyId}` ++ const transport = createMockTransport(ptyId) ++ transport.connect.mockImplementation(async ({ sessionId }: { sessionId?: string }) => { ++ return sessionId ? { id: sessionId } : null ++ }) ++ transportFactoryQueue.push(transport) ++ const deps = createDeps({ ++ tabId, ++ restoredLeafId: LEAF_1, ++ restoredPtyIdByLeafId: { [LEAF_1]: ptyId }, ++ ...(args.isVisibleRef ? { isVisibleRef: args.isVisibleRef } : {}) ++ }) ++ const binding = connectPanePty( ++ createPane(1) as never, ++ createManager(1) as never, ++ deps as never ++ ) as unknown as { noteVisibilityResume: () => void } ++ await vi.advanceTimersByTimeAsync(20) ++ await flushAsyncTicks(20) ++ return { binding, deps, transport, cacheKey: makePaneKey(tabId, LEAF_1) } ++ } ++ ++ async function advanceVisibleForegroundRead(): Promise { ++ await vi.advanceTimersByTimeAsync(VISIBLE_PTY_SETTLE_MS) ++ await flushAsyncTicks() ++ } ++ ++ function foregroundReadCallsFor(ptyId: string): unknown[][] { ++ return vi ++ .mocked(window.api.pty.getForegroundProcess) ++ .mock.calls.filter(([calledPtyId]) => calledPtyId === ptyId) ++ } ++ ++ it('does not inspect foreground process for a fresh visible spawn', async () => { ++ vi.useFakeTimers() ++ const { connectPanePty } = await import('./pty-connection') ++ const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) ++ getForegroundProcess.mockResolvedValue('codex') ++ const ptyId = 'pty-fresh-visible-no-sample' ++ transportFactoryQueue.push(createMockTransport(ptyId)) ++ mockStoreState = { ++ ...mockStoreState, ++ tabsByWorktree: { 'wt-1': [{ id: 'tab-1', ptyId: null }] }, ++ ptyIdsByTabId: { 'tab-1': [] }, ++ terminalLayoutsByTabId: { ++ 'tab-1': { ++ root: { type: 'leaf', leafId: LEAF_1 }, ++ activeLeafId: LEAF_1, ++ expandedLeafId: null, ++ ptyIdsByLeafId: {} ++ } ++ } ++ } as StoreState ++ ++ connectPanePty( ++ createPane(1) as never, ++ createManager(1) as never, ++ createDeps() as never ++ ) ++ await vi.advanceTimersByTimeAsync(20) ++ await flushAsyncTicks(20) ++ const spawnHandler = createdTransportOptions[0]?.onPtySpawn as ++ | ((ptyId: string) => void) ++ | undefined ++ spawnHandler?.(ptyId) ++ await advanceVisibleForegroundRead() ++ ++ expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) ++ }) ++ ++ it('samples exactly one visible restored PTY with no stronger identity signal', async () => { ++ vi.useFakeTimers() ++ const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) ++ getForegroundProcess.mockResolvedValue('codex') ++ const ptyId = 'pty-restored-visible-sample' ++ ++ const { cacheKey } = await connectRestoredPaneForForegroundSampling({ ptyId }) ++ expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) ++ ++ await advanceVisibleForegroundRead() ++ ++ expect(foregroundReadCallsFor(ptyId)).toEqual([[ptyId]]) ++ expect(mockStoreState.setPaneForegroundAgent).toHaveBeenCalledWith(cacheKey, { ++ agent: 'codex', ++ shellForeground: false ++ }) ++ }) ++ ++ it('does not sample hidden restored PTYs', async () => { ++ vi.useFakeTimers() ++ const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) ++ getForegroundProcess.mockResolvedValue('codex') ++ const ptyId = 'pty-hidden-restored-no-sample' ++ ++ await connectRestoredPaneForForegroundSampling({ ++ ptyId, ++ isVisibleRef: { current: false } ++ }) ++ await advanceVisibleForegroundRead() ++ ++ expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) ++ }) ++ ++ it('samples once when an identityless hidden pane resumes visible', async () => { ++ vi.useFakeTimers() ++ const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) ++ getForegroundProcess.mockResolvedValue('codex') ++ const isVisibleRef = { current: false } ++ const ptyId = 'pty-hidden-then-visible-sample' ++ const { binding } = await connectRestoredPaneForForegroundSampling({ ptyId, isVisibleRef }) ++ await advanceVisibleForegroundRead() ++ expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) ++ ++ isVisibleRef.current = true ++ binding.noteVisibilityResume() ++ await advanceVisibleForegroundRead() ++ ++ expect(foregroundReadCallsFor(ptyId)).toEqual([[ptyId]]) ++ }) ++ ++ it('does not sample when launch metadata already supplies tab identity', async () => { ++ vi.useFakeTimers() ++ const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) ++ getForegroundProcess.mockResolvedValue('codex') ++ const ptyId = 'pty-launch-identity-no-sample' ++ const tabId = `tab-${ptyId}` ++ mockStoreState.tabsByWorktree = { ++ 'wt-1': [{ id: tabId, ptyId, launchAgent: 'codex' }] ++ } ++ ++ await connectRestoredPaneForForegroundSampling({ ptyId, tabId }) ++ await advanceVisibleForegroundRead() ++ ++ expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) ++ }) ++ ++ it('does not sample when a live hook row already supplies pane identity', async () => { ++ vi.useFakeTimers() ++ const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) ++ getForegroundProcess.mockResolvedValue('codex') ++ const ptyId = 'pty-hook-identity-no-sample' ++ const tabId = `tab-${ptyId}` ++ mockStoreState.agentStatusByPaneKey[makePaneKey(tabId, LEAF_1)] = { ++ state: 'working', ++ agentType: 'codex' ++ } ++ ++ await connectRestoredPaneForForegroundSampling({ ptyId, tabId }) ++ await advanceVisibleForegroundRead() ++ ++ expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) ++ }) ++ ++ it('does not sample when process identity is already known', async () => { ++ vi.useFakeTimers() ++ const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) ++ getForegroundProcess.mockResolvedValue('codex') ++ const ptyId = 'pty-process-identity-no-sample' ++ const tabId = `tab-${ptyId}` ++ mockStoreState.paneForegroundAgentByPaneKey[makePaneKey(tabId, LEAF_1)] = { ++ agent: 'codex', ++ shellForeground: false ++ } ++ ++ await connectRestoredPaneForForegroundSampling({ ptyId, tabId }) ++ await advanceVisibleForegroundRead() ++ ++ expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) ++ }) ++ ++ it('does not re-sample once 133;D proved the pane is at a shell prompt', async () => { ++ vi.useFakeTimers() ++ const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) ++ getForegroundProcess.mockResolvedValue('codex') ++ const ptyId = 'pty-shell-foreground-no-sample' ++ const tabId = `tab-${ptyId}` ++ mockStoreState.paneForegroundAgentByPaneKey[makePaneKey(tabId, LEAF_1)] = { ++ agent: null, ++ shellForeground: true ++ } ++ ++ await connectRestoredPaneForForegroundSampling({ ptyId, tabId }) ++ await advanceVisibleForegroundRead() ++ ++ expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) ++ }) ++ ++ it('re-samples a shell-marked pane a launch agent still owns', async () => { ++ // Why: a reattach or a full-screen agent's leaked nested-shell 133;D leaves ++ // shellForeground on a launchAgent pane, suppressing its icon. The launch ++ // metadata means an agent is expected, so re-read to recover its identity. ++ vi.useFakeTimers() ++ const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) ++ getForegroundProcess.mockResolvedValue('codex') ++ const ptyId = 'pty-shell-foreground-launch-agent-sample' ++ const tabId = `tab-${ptyId}` ++ mockStoreState.tabsByWorktree = { ++ 'wt-1': [{ id: tabId, ptyId, launchAgent: 'codex' }] ++ } ++ mockStoreState.paneForegroundAgentByPaneKey[makePaneKey(tabId, LEAF_1)] = { ++ agent: null, ++ shellForeground: true ++ } ++ ++ const { cacheKey } = await connectRestoredPaneForForegroundSampling({ ptyId, tabId }) ++ await advanceVisibleForegroundRead() ++ ++ expect(foregroundReadCallsFor(ptyId)).toEqual([[ptyId]]) ++ expect(mockStoreState.setPaneForegroundAgent).toHaveBeenCalledWith(cacheKey, { ++ agent: 'codex', ++ shellForeground: false ++ }) ++ }) ++ }) ++ + describe('terminal input liveness IPC gating (perf)', () => { + // Why (perf regression guard): listSessions() is a renderer→main→daemon + // round-trip over every live session. Terminal input must never start that +diff --git a/src/renderer/src/components/terminal-pane/pty-connection.ts b/src/renderer/src/components/terminal-pane/pty-connection.ts +index dffa30c47..31713d1e9 100644 +--- a/src/renderer/src/components/terminal-pane/pty-connection.ts ++++ b/src/renderer/src/components/terminal-pane/pty-connection.ts +@@ -5,6 +5,7 @@ import type { IBuffer, IDisposable } from '@xterm/xterm' + import { resolveCursorAgentImeAnchor } from '@/lib/pane-manager/terminal-ime-anchor' + import { + detectAgentStatusFromTitle, ++ agentTypeToIconAgent, + isGeminiTerminalTitle, + isClaudeAgent + } from '@/lib/agent-status' +@@ -164,6 +165,7 @@ import { + normalizeCompatibleAgentTitleForOwner, + resolveCompatibleAgentTypeForOwner + } from '../../../../shared/agent-title-owner' ++import { resolveExplicitTerminalTitleAgentType } from '../../../../shared/terminal-title-agent-type' + import { + isExpectedAgentProcess, + recognizeAgentProcessFromCommandLine +@@ -666,6 +668,10 @@ let inactiveForegroundImmediateBudgetWindowStart = 0 + type PanePtyBinding = IDisposable & { + syncProcessTracking: () => void + noteVisibilityResume: () => void ++ /** Re-sample process identity when the pane gains intra-tab focus: the tab ++ * icon follows the active leaf, and a shell-marked entry on a still-running ++ * agent pane has no OSC boundary left to correct it. */ ++ sampleForegroundAgentOnFocus: () => void + reconcileIfSessionDead: (liveSessionIds: Set, snapshotRequestedAt?: number) => void + reconcileIfSessionMissing: (hasPty: HasPty, livenessRequestedAt?: number) => void + } +@@ -1751,12 +1757,81 @@ export function connectPanePty( + } + return pendingWrite.then(() => interruptInference.flushPending()) + } ++ // Why: a launched/hook-known agent pane must confirm — not trust — a 133;D so a ++ // full-screen agent's leaked nested-shell 133;D can't clear its tab identity, ++ // even on a restore where no command-start read has recorded evidence yet. ++ const paneHasKnownAgentIdentity = (): boolean => { ++ const state = useAppStore.getState() ++ const entry = state.agentStatusByPaneKey[cacheKey] ++ if (entry?.state !== 'done' && agentTypeToIconAgent(entry?.agentType)) { ++ return true ++ } ++ const tab = (state.tabsByWorktree[deps.worktreeId] ?? []).find( ++ (candidate) => candidate.id === deps.tabId ++ ) ++ return Boolean( ++ tab?.launchAgent ?? paneStartup?.launchAgent ?? paneStartup?.initialAgentStatus?.agent ++ ) ++ } ++ // Why: a plain `codex`/`grok` sets its OSC title and the shell never repaints ++ // it on exit, so a confirmed return-to-shell must clear a title that still ++ // names an agent — otherwise the tab reads "grok" over a bare prompt. Only ++ // reset an agent-named title; user/shell-set titles are left untouched. ++ const clearStaleAgentTabTitleOnConfirmedShell = (): void => { ++ const state = useAppStore.getState() ++ const currentTitle = state.runtimePaneTitlesByTabId?.[deps.tabId]?.[pane.id] ++ const tab = (state.tabsByWorktree[deps.worktreeId] ?? []).find( ++ (entry) => entry.id === deps.tabId ++ ) ++ const title = currentTitle ?? tab?.title ++ if (!title || resolveExplicitTerminalTitleAgentType(title) === null) { ++ return ++ } ++ const neutralTitle = neutralTerminalTitle() ++ deps.setRuntimePaneTitle(deps.tabId, pane.id, neutralTitle) ++ if (manager.getActivePane()?.id === pane.id) { ++ deps.updateTabTitle(deps.tabId, neutralTitle) ++ } ++ } + const paneForegroundAgentTracker = createPaneForegroundAgentTracker({ + getPtyId: () => transport.getPtyId(), + isTrackablePtyId: (id) => !isRemoteRuntimePtyId(id) && parseAppSshPtyId(id) === null, + readForegroundProcess: (id) => window.api.pty.getForegroundProcess(id), +- publish: (entry) => useAppStore.getState().setPaneForegroundAgent(cacheKey, entry) ++ publish: (entry) => useAppStore.getState().setPaneForegroundAgent(cacheKey, entry), ++ hasKnownAgentIdentity: paneHasKnownAgentIdentity, ++ onConfirmedShellForeground: clearStaleAgentTabTitleOnConfirmedShell + }) ++ const sampleVisiblePaneForegroundAgent = (): void => { ++ if (!deps.isVisibleRef.current) { ++ return ++ } ++ const state = useAppStore.getState() ++ const foreground = state.paneForegroundAgentByPaneKey[cacheKey] ++ // Why: live process identity already paints the icon — nothing to read. ++ if (foreground?.agent) { ++ return ++ } ++ const entry = state.agentStatusByPaneKey[cacheKey] ++ if (entry?.state !== 'done' && agentTypeToIconAgent(entry?.agentType)) { ++ return ++ } ++ const tab = (state.tabsByWorktree[deps.worktreeId] ?? []).find( ++ (candidate) => candidate.id === deps.tabId ++ ) ++ const expectsAgent = Boolean( ++ tab?.launchAgent ?? paneStartup?.launchAgent ?? paneStartup?.initialAgentStatus?.agent ++ ) ++ // Why: with no shell mark yet, launchAgent bootstrap already paints the icon, ++ // so a read is pointless. Otherwise probe the foreground: a shell mark (from a ++ // reattach or a full-screen agent's leaked nested-shell 133;D) can hide a ++ // still-running agent — including a manually started one with no launchAgent or ++ // hook, which no later 133;C will reseed. A genuinely idle shell just returns a ++ // shell name and publishes nothing, so the probe is self-limiting. ++ if (!foreground?.shellForeground && expectsAgent) { ++ return ++ } ++ paneForegroundAgentTracker.onVisiblePtyBound() ++ } + const commandLifecycle = createTerminalCommandLifecycle({ + onCommandStarted: () => paneForegroundAgentTracker.onCommandStarted(), + onCommandFinished: () => { +@@ -1829,6 +1904,14 @@ export function connectPanePty( + ) { + return + } ++ // Why: user shell frameworks (bash-preexec/iTerm2) can replace Orca's ++ // OSC 133;C hook, so a manually launched agent produces no command-start ++ // signal at all. Enter at a shell-foreground prompt is the user-side ++ // equivalent; the sample is gated to panes with no live agent identity ++ // and publishes nothing for an idle shell. ++ if (event.key === 'Enter' && !event.metaKey && !event.ctrlKey && !event.altKey) { ++ sampleVisiblePaneForegroundAgent() ++ } + deps.clearTerminalTabUnread(deps.tabId) + deps.clearTerminalPaneUnread(cacheKey) + deps.clearWorktreeUnread(deps.worktreeId) +@@ -2225,7 +2308,11 @@ export function connectPanePty( + } + const bindActivePanePty = ( + ptyId: string, +- options: { seedInitialAgentStatus?: boolean; updateTabPtyId?: 'always' | 'if-missing' } = {} ++ options: { ++ seedInitialAgentStatus?: boolean ++ updateTabPtyId?: 'always' | 'if-missing' ++ sampleVisibleForegroundAgent?: boolean ++ } = {} + ): void => { + if (activePanePtyBinding && activePanePtyBinding !== ptyId) { + reportPanePtyVisibility(activePanePtyBinding, false) +@@ -2248,6 +2335,11 @@ export function connectPanePty( + // frame-level sync often runs before that async result arrives. + scheduleRuntimeGraphSync() + agentCompletionCoordinator.startProcessTracking() ++ // Why: fresh spawns receive future OSC command-start events; only adopted or ++ // restored PTYs may already be inside Codex with no new foreground signal. ++ if (options.sampleVisibleForegroundAgent === true) { ++ sampleVisiblePaneForegroundAgent() ++ } + } + + const onPtySpawn = (ptyId: string): void => { +@@ -3657,7 +3749,10 @@ export function connectPanePty( + ) { + // Why: daemon createOrAttach can turn an apparent fresh spawn into + // a reattach; the transport skips onPtySpawn there to preserve recency. +- bindActivePanePty(resolvedPtyId, { updateTabPtyId: 'if-missing' }) ++ bindActivePanePty(resolvedPtyId, { ++ updateTabPtyId: 'if-missing', ++ sampleVisibleForegroundAgent: true ++ }) + } + if (resolvedPtyId) { + reconcilePtySizeAfterSpawn(resolvedPtyId, cols, rows) +@@ -5223,6 +5318,7 @@ export function connectPanePty( + deps.syncPanePtyLayoutBinding(pane.id, ptyId) + deps.updateTabPtyId(deps.tabId, ptyId) + agentCompletionCoordinator.startProcessTracking() ++ sampleVisiblePaneForegroundAgent() + + // Why: mobile terminal streaming needs the exact screen state from + // xterm.js. The shared helper installs both the SerializeAddon-backed +@@ -5784,7 +5880,10 @@ export function connectPanePty( + onError: reportError + } + }) +- bindActivePanePty(attachPtyId, { updateTabPtyId: 'if-missing' }) ++ bindActivePanePty(attachPtyId, { ++ updateTabPtyId: 'if-missing', ++ sampleVisibleForegroundAgent: true ++ }) + if (attachPtyId === eagerLivePtyId) { + registerPaneSerializerFor(attachPtyId) + } +@@ -5838,7 +5937,10 @@ export function connectPanePty( + }) + // Why: this path reuses a PTY spawned by an earlier mount, so no + // later spawn event will bind this remounted pane's DOM/container. +- bindActivePanePty(spawnedPtyId, { updateTabPtyId: 'if-missing' }) ++ bindActivePanePty(spawnedPtyId, { ++ updateTabPtyId: 'if-missing', ++ sampleVisibleForegroundAgent: true ++ }) + }) + .catch((err) => { + reportError(err instanceof Error ? err.message : String(err)) +@@ -5948,6 +6050,10 @@ export function connectPanePty( + noteVisibilityResume() { + ptySizeReassertion.request({ fit: false }) + consumeHibernatedAgentWake() ++ sampleVisiblePaneForegroundAgent() ++ }, ++ sampleForegroundAgentOnFocus() { ++ sampleVisiblePaneForegroundAgent() + }, + reconcileIfSessionDead, + reconcileIfSessionMissing, +diff --git a/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts b/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts +index e037e1e7f..bcf5835a6 100644 +--- a/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts ++++ b/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts +@@ -1281,6 +1281,13 @@ export function useTerminalPaneLifecycle({ + persistLayoutSnapshot() + } + reportActiveRendererPtyForPane(paneTransportsRef.current, pane.id) ++ // Why: the tab icon resolves from the active leaf's process identity; ++ // focusing a shell-marked pane whose agent is still running must ++ // re-sample it, since no further OSC boundary will. ++ const focusedBinding = panePtyBindings.get(pane.id) as ++ | (IDisposable & { sampleForegroundAgentOnFocus?: () => void }) ++ | undefined ++ focusedBinding?.sampleForegroundAgentOnFocus?.() + // Why: when the user switches focus between split panes, update the + // tab title to the newly active pane's last-known title so the tab + // label reflects the focused agent — not a stale title from the diff --git a/CODEX_ICON_DEBUG_HANDOFF.md b/CODEX_ICON_DEBUG_HANDOFF.md new file mode 100644 index 00000000000..9e6ba6c7831 --- /dev/null +++ b/CODEX_ICON_DEBUG_HANDOFF.md @@ -0,0 +1,82 @@ +# RESOLVED: Codex/agent terminal tab icon not showing + +Branch: `fix-codex-icon-not-showing-up-on-terminal`. All fixes validated live +end-to-end on 2026-07-05 in an isolated dev instance (fresh profile + fresh +daemon, real clicks via playwright-cli, visible-icon screenshots). + +## Root causes found (three, stacked) + +1. **bash-preexec swallows Orca's OSC 133;C** (the original bug on this + machine). The user's bash setup (iTerm2 shell integration) loads + bash-preexec, which re-arms its own DEBUG trap at the first prompt, + silencing Orca's `trap '__orca_osc133_preexec' DEBUG`. Result: typing + `codex`/`grok` emits NO command-start signal, so foreground detection never + begins. D (from PROMPT_COMMAND precmd) still fires at prompts, so panes get + marked shell-foreground, which also suppresses the title-layer icon. + Verified live: `trap -p DEBUG` showed `__bp_preexec_invoke_exec`. + **Fix**: `shell-ready.ts` bash wrapper also registers + `__orca_osc133_preexec_bp` in bash-preexec's `preexec_functions` array + (gated on `__orca_in_command` so C fires exactly once either way). + +2. **Daemon foreground cache TTL vs renderer retry cadence.** For node-wrapped + CLIs (grok's `node /opt/homebrew/bin/grok` trampoline), the daemon resolves + node→grok asynchronously into a 1000ms-TTL cache, but the renderer's wrapper + retries fire at +1200/+3500ms — always after expiry — so every read returned + raw `"node"` and detection failed. Verified live: reads alternated + node/grok/grok/node at 700ms intervals. + **Fix**: `pty-subprocess.ts` serves the last resolved identity while the + foreground is still an unidentifiable wrapper (stale-while-revalidate), and + clears an expired identity when a refresh proves the wrapper tree has no + agent (so `npm` after an agent exit can't inherit the icon). + +3. **Duplicate OSC 133;D defeats the confirming read.** User shell + integrations double up Orca's 133 sequences: every D arrives twice ~50ms + apart (verified via a PTY data tap: `D;0 … 53ms … D;0`). The second D saw no + pending 'command' read (only the first D's pending 'command-finished' read), + took the no-RPC fast path, published `{null, shellForeground: true}`, and + cancelled the in-flight confirmation. + **Fix**: `pane-foreground-agent-tracker.ts` counts a pending/in-flight + confirming read as "read pending", so duplicate Ds re-confirm. + +Plus two renderer resilience fixes for "focused pane changes" (user report): + +4. **Enter-triggered sampling** (`pty-connection.ts` onTerminalKeyDown): Enter + at a shell-foreground pane triggers the existing self-limiting foreground + sample — covers any setup where no 133;C arrives at all. Publishes nothing + for idle shells; skipped when an agent identity is already live. +5. **Focus-change resampling** (`use-terminal-pane-lifecycle.ts` + onActivePaneChange → `sampleForegroundAgentOnFocus`): the tab icon follows + the active leaf, so focusing a shell-marked pane whose agent is still + running re-samples it (recovers poisoned entries in splits). + +## Validated live (fresh build, new tabs, real clicks) + +- Typed `grok` in an already-focused pane → entry `{agent:'grok'}` + grok icon + on the tab within ~6s. +- Split right + typed `codex` → both panes' entries correct + (`{agent:'grok'}` / `{agent:'codex'}`); tab icon follows the focused pane + (grok icon ↔ codex icon on click), screenshots confirmed. +- Quit codex → entry cleared, tab shows plain terminal icon for the shell + pane; grok icon returns when its pane regains focus. + +## Tests + +- `shell-ready.test.ts` 23/23 (new: bash-preexec re-arm regression test that + fails without fix 1). +- `pty-subprocess.test.ts` 85/85 (new: stale-serve past TTL + expired-identity + clear). +- `pane-foreground-agent-tracker.test.ts` 23/23 (new: duplicate-D pair + confirm + idle-pane duplicate-D no-RPC path). +- `tsgo` web + node configs clean, oxlint clean. +- KNOWN: `pty-connection.test.ts` cannot load on this branch (pre-existing + vite resolution error for `pane-terminal-foreground-render-settle`; rebase + onto main to run its added tests). + +## Notes for review/merge + +- `CODEX_ICON_DEBUG.diff` is stale (pre-dates these fixes); use `git diff`. +- The daemon is a long-lived process: users (and dev instances) keep running + the OLD daemon code until it restarts. The bash rcfile is rewritten at + daemon startup, so fix 1 also needs a daemon restart to take effect. +- SSH panes are unaffected: the tracker's reads are gated by isTrackablePtyId + (local only); the shell-side C fix benefits every OSC 133 consumer. diff --git a/fresh-launch.png b/fresh-launch.png new file mode 100644 index 0000000000000000000000000000000000000000..a2c1407aabbb9d7ed58e2102af6beb7adbadf214 GIT binary patch literal 60436 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

5@B+nuuqadgDsz(aRE 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�MkJ;T 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%0D1L_3$(}&J7E@P%#PI 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 OM<*z7C%uUl&HoR6{IZ+? literal 0 HcmV?d00001 diff --git a/src/main/daemon/pty-subprocess.test.ts b/src/main/daemon/pty-subprocess.test.ts index 85366a1377b..b23c83656b1 100644 --- a/src/main/daemon/pty-subprocess.test.ts +++ b/src/main/daemon/pty-subprocess.test.ts @@ -367,6 +367,81 @@ describe('createPtySubprocess', () => { } }) + it('serves the resolved agent identity past the cache TTL while a wrapper holds the foreground', async () => { + vi.useFakeTimers() + vi.setSystemTime(new Date('2026-06-16T12:00:00.000Z')) + const proc = mockPtyProcess() + proc.process = 'node' + spawnMock.mockReturnValue(proc) + const platform = Object.getOwnPropertyDescriptor(process, 'platform') + Object.defineProperty(process, 'platform', { value: 'darwin' }) + resolveAgentForegroundProcessMock.mockResolvedValue('grok') + + try { + const handle = createPtySubprocess({ + sessionId: 'test', + cols: 80, + rows: 24 + }) + + expect(handle.getForegroundProcess()).toBe('node') + await Promise.resolve() + await Promise.resolve() + expect(handle.getForegroundProcess()).toBe('grok') + + // Why: renderer reads poll slower than the 1s cache TTL — an expired + // cache must keep answering with the resolved identity, not the wrapper. + vi.advanceTimersByTime(1_500) + expect(handle.getForegroundProcess()).toBe('grok') + } finally { + vi.useRealTimers() + if (platform) { + Object.defineProperty(process, 'platform', platform) + } + } + }) + + it('clears an expired identity when the wrapper tree no longer resolves to an agent', async () => { + vi.useFakeTimers() + vi.setSystemTime(new Date('2026-06-16T12:00:00.000Z')) + const proc = mockPtyProcess() + proc.process = 'node' + spawnMock.mockReturnValue(proc) + const platform = Object.getOwnPropertyDescriptor(process, 'platform') + Object.defineProperty(process, 'platform', { value: 'darwin' }) + resolveAgentForegroundProcessMock.mockResolvedValueOnce('grok').mockResolvedValue('node') + + try { + const handle = createPtySubprocess({ + sessionId: 'test', + cols: 80, + rows: 24 + }) + + expect(handle.getForegroundProcess()).toBe('node') + await Promise.resolve() + await Promise.resolve() + expect(handle.getForegroundProcess()).toBe('grok') + // Flush the first refresh's finally so the next read can revalidate. + await Promise.resolve() + await Promise.resolve() + + // An unrelated wrapper (e.g. npm) now owns the pane: the stale-served + // identity is revalidated and dropped once the refresh finds no agent. + vi.advanceTimersByTime(1_500) + expect(handle.getForegroundProcess()).toBe('grok') + await Promise.resolve() + await Promise.resolve() + await Promise.resolve() + expect(handle.getForegroundProcess()).toBe('node') + } finally { + vi.useRealTimers() + if (platform) { + Object.defineProperty(process, 'platform', platform) + } + } + }) + it('serves daemon Windows wrapper agent foreground from an async cache', async () => { const proc = mockPtyProcess() proc.process = 'node.exe' diff --git a/src/main/daemon/pty-subprocess.ts b/src/main/daemon/pty-subprocess.ts index 6dd0554bb87..09f66a98739 100644 --- a/src/main/daemon/pty-subprocess.ts +++ b/src/main/daemon/pty-subprocess.ts @@ -937,6 +937,16 @@ export function createPtySubprocess(opts: PtySubprocessOptions): SubprocessHandl ) { cachedAgentForeground = null startupAgentForeground = null + } else if ( + cachedAgentForeground !== null && + Date.now() - cachedAgentForeground.refreshedAt > FOREGROUND_AGENT_CACHE_TTL_MS && + currentFallbackProcess !== null && + isAgentForegroundWrapperProcess(currentFallbackProcess) + ) { + // Why: the wrapper's tree no longer resolves to an agent — an expired + // identity must not transfer to an unrelated wrapper (e.g. npm right + // after an agent exit). Fresh identities survive one-off scan hiccups. + cachedAgentForeground = null } return } @@ -994,6 +1004,18 @@ export function createPtySubprocess(opts: PtySubprocessOptions): SubprocessHandl ) { return cachedAgentForeground.processName } + // Why: a wrapper foreground (node/python) can never identify itself, and + // readers poll slower than the cache TTL — returning the raw wrapper here + // would hide the resolved identity forever. Serve the last resolved agent + // while the scheduled refresh revalidates; exit truth is safe because an + // exited agent's foreground falls back to the shell, not a wrapper. + if ( + cachedAgentForeground && + fallbackProcess !== null && + isAgentForegroundWrapperProcess(fallbackProcess) + ) { + return cachedAgentForeground.processName + } const activeStartupAgentForeground = getActiveStartupAgentForeground(now) if (fallbackProcess && isShellProcess(fallbackProcess) && activeStartupAgentForeground) { return activeStartupAgentForeground.processName diff --git a/src/main/daemon/shell-ready.test.ts b/src/main/daemon/shell-ready.test.ts index 860e3f27a9e..ce1a67da7ca 100644 --- a/src/main/daemon/shell-ready.test.ts +++ b/src/main/daemon/shell-ready.test.ts @@ -556,6 +556,34 @@ describePosix('daemon shell-ready launch config', () => { } ) + itWithBash( + 'still emits 133;C when bash-preexec re-arms the DEBUG trap at first prompt', + async () => { + const { getDaemonBashShellReadyRcfileContent } = await importFreshShellReady() + // Minimal bash-preexec imitation (iTerm2/starship setups): re-arms its own + // DEBUG trap from PROMPT_COMMAND at the first prompt — silencing Orca's + // trap — and dispatches preexec_functions with the command as $1. + writeFileSync( + join(userDataPath, '.bash_profile'), + [ + 'preexec_functions=()', + '__bp_preexec_invoke_exec() {', + ' [[ -n "${__bp_interactive_mode:-}" ]] || return', + ' __bp_interactive_mode=""', + ' local f', + ' for f in "${preexec_functions[@]}"; do "$f" "$BASH_COMMAND"; done', + '}', + "__bp_arm() { __bp_interactive_mode=1; trap '__bp_preexec_invoke_exec' DEBUG; }", + 'PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND;}__bp_arm"' + ].join('\n') + ) + + const output = runInteractiveBashRcfile(getDaemonBashShellReadyRcfileContent(), userDataPath) + + expectBashOsc133Lifecycle(output) + } + ) + itWithBash('normalizes array PROMPT_COMMAND hooks so bash 3.2 still runs cleanup', async () => { const { getDaemonBashShellReadyRcfileContent } = await importFreshShellReady() writeFileSync( diff --git a/src/main/daemon/shell-ready.ts b/src/main/daemon/shell-ready.ts index 7ad5a686bb7..169be2f53fc 100644 --- a/src/main/daemon/shell-ready.ts +++ b/src/main/daemon/shell-ready.ts @@ -195,6 +195,23 @@ if [[ -n "$__orca_debug_trap_spec" ]]; then fi unset __orca_debug_trap_spec __orca_debug_trap_command unset -f __orca_normalize_prompt_command __orca_prepend_prompt_command __orca_append_prompt_command +# Why: bash-preexec (pulled in by iTerm2/starship setups) re-arms its own DEBUG +# trap at the first prompt, silencing ours. Register with its preexec_functions +# array too. Bash holds exactly one DEBUG trap, so only one dispatch path is +# ever live and C cannot double-emit; the __orca_in_command gate is a backstop. +__orca_osc133_preexec_bp() { + [[ -z "\${__orca_in_command:-}" ]] || return + [[ -z "\${__orca_in_prompt_command:-}" ]] || return + case "\${1:-}" in + *__orca_osc133_precmd*|*__orca_osc133_prompt_done*|*__orca_prompt_mark*) return ;; + esac + printf "\\033]133;C\\007" + __orca_in_command=1 +} +case " \${preexec_functions[*]:-} " in + *" __orca_osc133_preexec_bp "*) ;; + *) preexec_functions+=(__orca_osc133_preexec_bp) ;; +esac # Why: arm DEBUG after wrapper setup; otherwise bash treats our own rcfile # commands as a foreground command and emits a fake C/D before the first prompt. trap '__orca_osc133_preexec' DEBUG diff --git a/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.test.ts b/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.test.ts index 5a2e8c25840..ab5aaa03b8c 100644 --- a/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.test.ts +++ b/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.test.ts @@ -5,12 +5,14 @@ import { createPaneForegroundAgentTracker } from './pane-foreground-agent-tracke import type { PaneForegroundAgentEntry } from '@/store/slices/pane-foreground-agent' const COMMAND_SETTLE_MS = 350 +const VISIBLE_PTY_SETTLE_MS = 350 const WRAPPER_RESOLVE_RETRY_MS = 1200 const SECOND_WRAPPER_RETRY_MS = 3500 describe('createPaneForegroundAgentTracker', () => { const readForegroundProcess = vi.fn<(ptyId: string) => Promise>() const publish = vi.fn<(entry: PaneForegroundAgentEntry) => void>() + const onConfirmedShellForeground = vi.fn<() => void>() let ptyId: string | null = 'pty-1' function makeTracker(): ReturnType { @@ -18,7 +20,8 @@ describe('createPaneForegroundAgentTracker', () => { getPtyId: () => ptyId, isTrackablePtyId: (id) => !id.startsWith('remote:') && !id.startsWith('ssh:'), readForegroundProcess, - publish + publish, + onConfirmedShellForeground }) } @@ -30,6 +33,7 @@ describe('createPaneForegroundAgentTracker', () => { vi.useFakeTimers() readForegroundProcess.mockReset() publish.mockReset() + onConfirmedShellForeground.mockReset() ptyId = 'pty-1' }) @@ -52,6 +56,72 @@ describe('createPaneForegroundAgentTracker', () => { expect(publish).toHaveBeenLastCalledWith({ agent: 'claude', shellForeground: false }) }) + it('reads the foreground for a visible PTY so restored running Codex panes regain identity', async () => { + readForegroundProcess.mockResolvedValue('codex') + const tracker = makeTracker() + + tracker.onVisiblePtyBound() + expect(readForegroundProcess).not.toHaveBeenCalled() + + await flushSettleRead(VISIBLE_PTY_SETTLE_MS) + + expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') + expect(publish).toHaveBeenLastCalledWith({ agent: 'codex', shellForeground: false }) + }) + + it('does not retry or publish visible PTY reads for an idle shell foreground', async () => { + readForegroundProcess.mockResolvedValue('zsh') + const tracker = makeTracker() + + tracker.onVisiblePtyBound() + await flushSettleRead( + VISIBLE_PTY_SETTLE_MS + WRAPPER_RESOLVE_RETRY_MS + SECOND_WRAPPER_RETRY_MS + 10_000 + ) + + expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') + expect(publish).not.toHaveBeenCalled() + }) + + it('lets command-start sampling supersede a pending visible PTY read', async () => { + readForegroundProcess.mockResolvedValue('codex') + const tracker = makeTracker() + + tracker.onVisiblePtyBound() + tracker.onCommandStarted() + await flushSettleRead(VISIBLE_PTY_SETTLE_MS) + + expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') + expect(publish).toHaveBeenLastCalledWith({ agent: 'codex', shellForeground: false }) + }) + + it('does not let visible PTY sampling downgrade pending command-start sampling', async () => { + readForegroundProcess.mockResolvedValueOnce('bash').mockResolvedValueOnce('codex') + const tracker = makeTracker() + + tracker.onCommandStarted() + tracker.onVisiblePtyBound() + await flushSettleRead(COMMAND_SETTLE_MS) + expect(readForegroundProcess).toHaveBeenCalledTimes(1) + + await flushSettleRead(WRAPPER_RESOLVE_RETRY_MS) + expect(readForegroundProcess).toHaveBeenCalledTimes(2) + expect(publish).toHaveBeenLastCalledWith({ agent: 'codex', shellForeground: false }) + }) + + it('retries visible PTY reads only while a foreground wrapper may resolve to an agent', async () => { + readForegroundProcess.mockResolvedValueOnce('node').mockResolvedValueOnce('codex') + const tracker = makeTracker() + + tracker.onVisiblePtyBound() + await flushSettleRead(VISIBLE_PTY_SETTLE_MS) + expect(readForegroundProcess).toHaveBeenCalledTimes(1) + expect(publish).not.toHaveBeenCalled() + + await flushSettleRead(WRAPPER_RESOLVE_RETRY_MS) + expect(readForegroundProcess).toHaveBeenCalledTimes(2) + expect(publish).toHaveBeenLastCalledWith({ agent: 'codex', shellForeground: false }) + }) + it('re-reads on a bounded ladder while the read still sees an interpreter wrapper', async () => { // Why: daemon shell/helper→agent ancestry resolution has been observed to // take >1.5s for real node-wrapped CLIs, so the ladder gets two re-reads. @@ -124,16 +194,159 @@ describe('createPaneForegroundAgentTracker', () => { expect(readForegroundProcess).not.toHaveBeenCalled() }) - it('cancels a pending read when the command finishes first', async () => { + it('confirms a rapid command start->finish instead of trusting the D', async () => { + // Why: a leaked nested-shell 133;C->133;D pair (or a fast real command) + // cancels the command-start read; confirm the foreground so a still-running + // manual agent with no launchAgent/hook keeps its identity. readForegroundProcess.mockResolvedValue('claude') const tracker = makeTracker() tracker.onCommandStarted() tracker.onCommandFinished() - await flushSettleRead(COMMAND_SETTLE_MS + WRAPPER_RESOLVE_RETRY_MS) + await flushSettleRead(COMMAND_SETTLE_MS) + + expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') + expect(publish).toHaveBeenLastCalledWith({ agent: 'claude', shellForeground: false }) + expect(publish).not.toHaveBeenCalledWith({ agent: null, shellForeground: true }) + }) + + it('confirms duplicate 133;D pairs instead of fast-pathing past the pending confirmation', async () => { + // Why: user shell integrations (iTerm/VS Code) double up Orca's OSC 133, so + // every D arrives twice ~50ms apart. The second D cancels the first D's + // confirming read; it must reschedule the confirmation, not trust the D. + readForegroundProcess.mockResolvedValue('grok') + const tracker = makeTracker() + + tracker.onCommandStarted() + tracker.onCommandStarted() + tracker.onCommandFinished() + await flushSettleRead(50) + tracker.onCommandFinished() + await flushSettleRead(COMMAND_SETTLE_MS) + + expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') + expect(publish).toHaveBeenLastCalledWith({ agent: 'grok', shellForeground: false }) + expect(publish).not.toHaveBeenCalledWith({ agent: null, shellForeground: true }) + }) + + it('still marks shell without a read for a duplicate D pair on an idle pane', async () => { + const tracker = makeTracker() + + tracker.onCommandFinished() + await flushSettleRead(50) + tracker.onCommandFinished() + await flushSettleRead(COMMAND_SETTLE_MS) + + // Why: with no command read in flight the first D takes the no-RPC path, + // so its duplicate has nothing to re-confirm and stays RPC-free too. + expect(readForegroundProcess).not.toHaveBeenCalled() + expect(publish).toHaveBeenCalledTimes(2) + expect(publish).toHaveBeenLastCalledWith({ agent: null, shellForeground: true }) + }) + + it('marks shell on a rapid command start->finish when the foreground is a shell', async () => { + readForegroundProcess.mockResolvedValue('zsh') + const tracker = makeTracker() + + tracker.onCommandStarted() + tracker.onCommandFinished() + await flushSettleRead(COMMAND_SETTLE_MS) + + expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') + expect(publish).toHaveBeenLastCalledWith({ agent: null, shellForeground: true }) + }) + + it('confirms the foreground before clearing a pane an agent has owned', async () => { + readForegroundProcess.mockResolvedValue('codex') + const tracker = makeTracker() + + tracker.onCommandStarted() + await flushSettleRead(COMMAND_SETTLE_MS) + expect(publish).toHaveBeenLastCalledWith({ agent: 'codex', shellForeground: false }) + + publish.mockClear() + readForegroundProcess.mockClear() + tracker.onCommandFinished() + // Why: a leaked nested-shell 133;D must not clear Codex before the read. + expect(publish).not.toHaveBeenCalled() + + await flushSettleRead(COMMAND_SETTLE_MS) + expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') + expect(publish).toHaveBeenLastCalledWith({ agent: 'codex', shellForeground: false }) + expect(publish).not.toHaveBeenCalledWith({ agent: null, shellForeground: true }) + }) + + it('marks shell foreground when the confirming read shows the agent is gone', async () => { + readForegroundProcess.mockResolvedValueOnce('codex').mockResolvedValueOnce('zsh') + const tracker = makeTracker() + + tracker.onCommandStarted() + await flushSettleRead(COMMAND_SETTLE_MS) + + publish.mockClear() + tracker.onCommandFinished() + await flushSettleRead(COMMAND_SETTLE_MS) + + expect(readForegroundProcess).toHaveBeenLastCalledWith('pty-1') + expect(publish).toHaveBeenLastCalledWith({ agent: null, shellForeground: true }) + }) + + it('signals confirmed shell foreground only when the read proves the agent exited', async () => { + // Reads: command-start=codex, first finish=codex (still running), second finish=zsh (exited). + readForegroundProcess + .mockResolvedValueOnce('codex') + .mockResolvedValueOnce('codex') + .mockResolvedValueOnce('zsh') + const tracker = makeTracker() + + tracker.onCommandStarted() + await flushSettleRead(COMMAND_SETTLE_MS) + + // A leaked nested-shell 133;D while Codex still owns the foreground: no signal. + tracker.onCommandFinished() + await flushSettleRead(COMMAND_SETTLE_MS) + expect(onConfirmedShellForeground).not.toHaveBeenCalled() + + // Genuine exit -> read sees a shell -> signal fires exactly once. + tracker.onCommandFinished() + await flushSettleRead(COMMAND_SETTLE_MS) + expect(onConfirmedShellForeground).toHaveBeenCalledTimes(1) + }) + + it('returns to the no-RPC finished path after the agent is confirmed gone', async () => { + readForegroundProcess.mockResolvedValueOnce('codex').mockResolvedValueOnce('zsh') + const tracker = makeTracker() + + tracker.onCommandStarted() + await flushSettleRead(COMMAND_SETTLE_MS) + tracker.onCommandFinished() + await flushSettleRead(COMMAND_SETTLE_MS) + + publish.mockClear() + readForegroundProcess.mockClear() + tracker.onCommandFinished() expect(readForegroundProcess).not.toHaveBeenCalled() - expect(publish).toHaveBeenLastCalledWith({ agent: null, shellForeground: true }) + expect(publish).toHaveBeenCalledExactlyOnceWith({ agent: null, shellForeground: true }) + }) + + it('confirms a command finished for a launch-known agent pane before any read', async () => { + readForegroundProcess.mockResolvedValue('codex') + const tracker = createPaneForegroundAgentTracker({ + getPtyId: () => ptyId, + isTrackablePtyId: (id) => !id.startsWith('remote:') && !id.startsWith('ssh:'), + readForegroundProcess, + publish, + hasKnownAgentIdentity: () => true + }) + + tracker.onCommandFinished() + // Why: launchAgent/hook identity means the 133;D is confirmed, not trusted. + expect(publish).not.toHaveBeenCalled() + + await flushSettleRead(COMMAND_SETTLE_MS) + expect(readForegroundProcess).toHaveBeenCalledExactlyOnceWith('pty-1') + expect(publish).toHaveBeenLastCalledWith({ agent: 'codex', shellForeground: false }) }) it('never reads or publishes for remote or ssh panes', async () => { diff --git a/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.ts b/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.ts index 1af2f78fdd7..8e9d3732780 100644 --- a/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.ts +++ b/src/renderer/src/components/terminal-pane/pane-foreground-agent-tracker.ts @@ -1,4 +1,7 @@ -import { recognizeAgentProcess } from '../../../../shared/agent-process-recognition' +import { + isAgentForegroundWrapperProcess, + recognizeAgentProcess +} from '../../../../shared/agent-process-recognition' import type { PaneForegroundAgentEntry } from '@/store/slices/pane-foreground-agent' // Why: the read must land after the shell has exec'd the command; and when it @@ -6,7 +9,9 @@ import type { PaneForegroundAgentEntry } from '@/store/slices/pane-foreground-ag // asynchronously — observed to take >1.5s for real node-wrapped CLIs — so // give its cache two bounded re-reads, not an open-ended retry loop. const COMMAND_SETTLE_MS = 350 +const VISIBLE_PTY_SETTLE_MS = 350 const WRAPPER_RESOLVE_RETRY_DELAYS_MS = [1200, 3500] as const +type ForegroundReadReason = 'command' | 'visible-pty' | 'command-finished' type PaneForegroundAgentTrackerDeps = { getPtyId: () => string | null @@ -15,22 +20,39 @@ type PaneForegroundAgentTrackerDeps = { isTrackablePtyId: (ptyId: string) => boolean readForegroundProcess: (ptyId: string) => Promise publish: (entry: PaneForegroundAgentEntry) => void + /** True when the pane is otherwise known to run an agent (launchAgent, live + * hook status). Lets a restored agent pane confirm — rather than trust — a + * 133;D before any command-start read has recorded its own evidence. */ + hasKnownAgentIdentity?: () => boolean + /** Fired when a confirming read proves the foreground genuinely returned to a + * shell (agent exited). Lets callers clear a stale agent-named tab title that + * the shell never repaints. */ + onConfirmedShellForeground?: () => void } /** * Publishes process-table identity for a pane at OSC 133 command boundaries: * one foreground read when a command starts (that is when the foreground - * changes), and a no-RPC shell-foreground mark when it finishes — 133;D is - * the ONLY source of shell-foreground proof; reads never produce it. + * changes), and a shell-foreground mark when it finishes. A 133;D is normally + * the shell-foreground proof; for a pane an agent has owned it is confirmed by a + * foreground read first, because a full-screen agent's nested command shells + * leak their own 133;D onto the main PTY. */ export function createPaneForegroundAgentTracker(deps: PaneForegroundAgentTrackerDeps): { + onVisiblePtyBound: () => void onCommandStarted: () => void onCommandFinished: () => void dispose: () => void } { let disposed = false - let readTimer: number | null = null + let readTimer: ReturnType | null = null + let scheduledReadReason: ForegroundReadReason | null = null + let activeReadReason: ForegroundReadReason | null = null let readGeneration = 0 + // Why: a full-screen agent (Codex, etc.) runs nested command shells whose own + // OSC 133;D leaks onto the main PTY. For a pane an agent has owned, that D is + // not proof the prompt returned, so confirm the foreground before clearing. + let hasForegroundAgentEvidence = false const trackablePtyId = (): string | null => { const ptyId = deps.getPtyId() @@ -40,30 +62,53 @@ export function createPaneForegroundAgentTracker(deps: PaneForegroundAgentTracke const cancelPendingRead = (): void => { readGeneration += 1 if (readTimer !== null) { - window.clearTimeout(readTimer) + clearTimeout(readTimer) readTimer = null } + scheduledReadReason = null + activeReadReason = null } - const scheduleRead = (delayMs: number, retryIndex: number): void => { + const scheduleRead = ( + delayMs: number, + retryIndex: number, + reason: ForegroundReadReason + ): void => { const generation = readGeneration - readTimer = window.setTimeout(() => { + scheduledReadReason = reason + readTimer = setTimeout(() => { readTimer = null - void readForeground(generation, retryIndex) + scheduledReadReason = null + activeReadReason = reason + void readForeground(generation, retryIndex, reason).finally(() => { + if (generation === readGeneration && activeReadReason === reason) { + activeReadReason = null + } + }) }, delayMs) } - async function readForeground(generation: number, retryIndex: number): Promise { + async function readForeground( + generation: number, + retryIndex: number, + reason: ForegroundReadReason + ): Promise { const ptyId = trackablePtyId() if (disposed || generation !== readGeneration || !ptyId) { return } - const processName = await deps.readForegroundProcess(ptyId).catch(() => null) + let processName: string | null = null + try { + processName = await deps.readForegroundProcess(ptyId) + } catch { + processName = null + } if (disposed || generation !== readGeneration) { return } const recognized = recognizeAgentProcess(processName) if (recognized) { + hasForegroundAgentEvidence = true deps.publish({ agent: recognized.agent, shellForeground: false }) return } @@ -72,14 +117,50 @@ export function createPaneForegroundAgentTracker(deps: PaneForegroundAgentTracke // a nested one (sh/bash without integration); marking shell-foreground // would suppress live title identity. Only 133;D proves the prompt. const retryDelay = WRAPPER_RESOLVE_RETRY_DELAYS_MS[retryIndex] - if (retryDelay !== undefined && processName) { - scheduleRead(retryDelay, retryIndex + 1) + const shouldRetry = + retryDelay !== undefined && + processName && + (reason === 'command' || isAgentForegroundWrapperProcess(processName)) + if (shouldRetry) { + scheduleRead(retryDelay, retryIndex + 1, reason) return } - deps.publish({ agent: null, shellForeground: false }) + if (reason === 'command') { + deps.publish({ agent: null, shellForeground: false }) + return + } + if (reason === 'command-finished') { + // Why: the 133;D fired AND the foreground shows no agent — together that is + // real prompt proof, so the agent truly exited. Reset the evidence so the + // pane's ordinary shell commands go back to the no-RPC finished path. + hasForegroundAgentEvidence = false + deps.publish({ agent: null, shellForeground: true }) + // Why: confirmed exit — let callers clear a stale agent title the shell + // won't repaint (a plain `codex`/`grok` leaves its OSC title behind). + deps.onConfirmedShellForeground?.() + } } return { + onVisiblePtyBound() { + // Why: command-start and command-finished reads own the exit decision; + // visibility recovery is lower-authority and must never cancel them. + if ( + scheduledReadReason === 'command' || + activeReadReason === 'command' || + scheduledReadReason === 'command-finished' || + activeReadReason === 'command-finished' + ) { + return + } + cancelPendingRead() + if (!trackablePtyId()) { + return + } + // Why: restored/manual agent panes can become visible while Codex is + // already foreground, so no OSC 133 command-start event will seed the tab icon. + scheduleRead(VISIBLE_PTY_SETTLE_MS, 0, 'visible-pty') + }, onCommandStarted() { cancelPendingRead() if (!trackablePtyId()) { @@ -88,14 +169,39 @@ export function createPaneForegroundAgentTracker(deps: PaneForegroundAgentTracke // Why: the foreground left the prompt the moment C fired — stale // shell-foreground evidence must not clear the command that just started. deps.publish({ agent: null, shellForeground: false }) - scheduleRead(COMMAND_SETTLE_MS, 0) + scheduleRead(COMMAND_SETTLE_MS, 0, 'command') }, onCommandFinished() { + // Why: a rapid 133;C→133;D pair cancels the command-start read before it + // can identify the foreground — that pair is exactly a leaked nested-shell + // command under a full-screen agent (or a fast real shell command), so on a + // no-identity pane confirm it rather than trusting the D as a prompt return. + // A pending confirming read counts too: user shell integrations double up + // Orca's OSC 133, and the duplicate D must re-confirm, not fast-path past + // the in-flight confirmation it just cancelled. + const commandReadWasPending = + scheduledReadReason === 'command' || + activeReadReason === 'command' || + scheduledReadReason === 'command-finished' || + activeReadReason === 'command-finished' cancelPendingRead() if (!trackablePtyId()) { return } - deps.publish({ agent: null, shellForeground: true }) + // Why: trust the 133;D and mark shell without an RPC only when nothing hints + // at an agent — no prior agent evidence, no launch/hook identity, and no + // command-start read racing this finish. + if ( + !hasForegroundAgentEvidence && + deps.hasKnownAgentIdentity?.() !== true && + !commandReadWasPending + ) { + deps.publish({ agent: null, shellForeground: true }) + return + } + // Why: confirm the foreground before clearing — if the agent still owns it, + // the read republishes its identity; only a genuine shell result clears it. + scheduleRead(COMMAND_SETTLE_MS, 0, 'command-finished') }, dispose() { disposed = true diff --git a/src/renderer/src/components/terminal-pane/pty-connection.test.ts b/src/renderer/src/components/terminal-pane/pty-connection.test.ts index 383d5d141f4..975554d5a33 100644 --- a/src/renderer/src/components/terminal-pane/pty-connection.test.ts +++ b/src/renderer/src/components/terminal-pane/pty-connection.test.ts @@ -21,6 +21,7 @@ import { beginAgentStartupDeliveryAttempt, resetAgentStartupDelayedDeliveryForTests } from '@/lib/agent-startup-delayed-delivery' +import type { PaneForegroundAgentEntry } from '@/store/slices/pane-foreground-agent' // Repro command: // pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/terminal-pane/pty-connection.test.ts -t "OpenTUI-style small ANSI redraw" @@ -169,6 +170,7 @@ type StoreState = { consumePendingSnapshot: ReturnType runtimePaneTitlesByTabId: Record> agentStatusByPaneKey: Record + paneForegroundAgentByPaneKey: Record sleepingAgentSessionsByPaneKey: Record agentLaunchConfigByPaneKey: Record getAgentLaunchConfigForStatusEntry: ReturnType @@ -737,6 +739,7 @@ describe('connectPanePty', () => { consumePendingSnapshot: vi.fn(() => null), runtimePaneTitlesByTabId: {}, agentStatusByPaneKey: {}, + paneForegroundAgentByPaneKey: {}, sleepingAgentSessionsByPaneKey: {}, agentLaunchConfigByPaneKey: {}, getAgentLaunchConfigForStatusEntry: vi.fn((entry: { paneKey: string }) => { @@ -771,8 +774,12 @@ describe('connectPanePty', () => { ), removeAgentStatus: vi.fn(), dropAgentStatus: vi.fn(), - setPaneForegroundAgent: vi.fn(), - clearPaneForegroundAgent: vi.fn(), + setPaneForegroundAgent: vi.fn((paneKey: string, entry: PaneForegroundAgentEntry) => { + mockStoreState.paneForegroundAgentByPaneKey[paneKey] = entry + }), + clearPaneForegroundAgent: vi.fn((paneKey: string) => { + delete mockStoreState.paneForegroundAgentByPaneKey[paneKey] + }), markTerminalTabUnread: vi.fn(), markTerminalPaneUnread: vi.fn(), markAgentCompletionPaneUnread: vi.fn() @@ -13949,6 +13956,238 @@ describe('connectPanePty', () => { }) }) + describe('visible foreground agent sampling (perf)', () => { + const VISIBLE_PTY_SETTLE_MS = 350 + + // Why: every connectPanePty binding in this file shares the tab-1/LEAF_1 pane + // key, and an undisposed reattach binding elsewhere can resolve a foreground + // read into this test's store slice. Give each sampling case its own tabId so + // no other test's publish can pollute the pane identity it asserts on. + async function connectRestoredPaneForForegroundSampling( + args: { + ptyId?: string + tabId?: string + isVisibleRef?: { current: boolean } + } = {} + ): Promise<{ + binding: { noteVisibilityResume: () => void } + deps: ReturnType + transport: MockTransport + cacheKey: string + }> { + const { connectPanePty } = await import('./pty-connection') + const ptyId = args.ptyId ?? 'tab-pty' + const tabId = args.tabId ?? `tab-${ptyId}` + const transport = createMockTransport(ptyId) + transport.connect.mockImplementation(async ({ sessionId }: { sessionId?: string }) => { + return sessionId ? { id: sessionId } : null + }) + transportFactoryQueue.push(transport) + const deps = createDeps({ + tabId, + restoredLeafId: LEAF_1, + restoredPtyIdByLeafId: { [LEAF_1]: ptyId }, + ...(args.isVisibleRef ? { isVisibleRef: args.isVisibleRef } : {}) + }) + const binding = connectPanePty( + createPane(1) as never, + createManager(1) as never, + deps as never + ) as unknown as { noteVisibilityResume: () => void } + await vi.advanceTimersByTimeAsync(20) + await flushAsyncTicks(20) + return { binding, deps, transport, cacheKey: makePaneKey(tabId, LEAF_1) } + } + + async function advanceVisibleForegroundRead(): Promise { + await vi.advanceTimersByTimeAsync(VISIBLE_PTY_SETTLE_MS) + await flushAsyncTicks() + } + + function foregroundReadCallsFor(ptyId: string): unknown[][] { + return vi + .mocked(window.api.pty.getForegroundProcess) + .mock.calls.filter(([calledPtyId]) => calledPtyId === ptyId) + } + + it('does not inspect foreground process for a fresh visible spawn', async () => { + vi.useFakeTimers() + const { connectPanePty } = await import('./pty-connection') + const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) + getForegroundProcess.mockResolvedValue('codex') + const ptyId = 'pty-fresh-visible-no-sample' + transportFactoryQueue.push(createMockTransport(ptyId)) + mockStoreState = { + ...mockStoreState, + tabsByWorktree: { 'wt-1': [{ id: 'tab-1', ptyId: null }] }, + ptyIdsByTabId: { 'tab-1': [] }, + terminalLayoutsByTabId: { + 'tab-1': { + root: { type: 'leaf', leafId: LEAF_1 }, + activeLeafId: LEAF_1, + expandedLeafId: null, + ptyIdsByLeafId: {} + } + } + } as StoreState + + connectPanePty(createPane(1) as never, createManager(1) as never, createDeps() as never) + await vi.advanceTimersByTimeAsync(20) + await flushAsyncTicks(20) + const spawnHandler = createdTransportOptions[0]?.onPtySpawn as + | ((ptyId: string) => void) + | undefined + spawnHandler?.(ptyId) + await advanceVisibleForegroundRead() + + expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) + }) + + it('samples exactly one visible restored PTY with no stronger identity signal', async () => { + vi.useFakeTimers() + const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) + getForegroundProcess.mockResolvedValue('codex') + const ptyId = 'pty-restored-visible-sample' + + const { cacheKey } = await connectRestoredPaneForForegroundSampling({ ptyId }) + expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) + + await advanceVisibleForegroundRead() + + expect(foregroundReadCallsFor(ptyId)).toEqual([[ptyId]]) + expect(mockStoreState.setPaneForegroundAgent).toHaveBeenCalledWith(cacheKey, { + agent: 'codex', + shellForeground: false + }) + }) + + it('does not sample hidden restored PTYs', async () => { + vi.useFakeTimers() + const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) + getForegroundProcess.mockResolvedValue('codex') + const ptyId = 'pty-hidden-restored-no-sample' + + await connectRestoredPaneForForegroundSampling({ + ptyId, + isVisibleRef: { current: false } + }) + await advanceVisibleForegroundRead() + + expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) + }) + + it('samples once when an identityless hidden pane resumes visible', async () => { + vi.useFakeTimers() + const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) + getForegroundProcess.mockResolvedValue('codex') + const isVisibleRef = { current: false } + const ptyId = 'pty-hidden-then-visible-sample' + const { binding } = await connectRestoredPaneForForegroundSampling({ ptyId, isVisibleRef }) + await advanceVisibleForegroundRead() + expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) + + isVisibleRef.current = true + binding.noteVisibilityResume() + await advanceVisibleForegroundRead() + + expect(foregroundReadCallsFor(ptyId)).toEqual([[ptyId]]) + }) + + it('does not sample when launch metadata already supplies tab identity', async () => { + vi.useFakeTimers() + const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) + getForegroundProcess.mockResolvedValue('codex') + const ptyId = 'pty-launch-identity-no-sample' + const tabId = `tab-${ptyId}` + mockStoreState.tabsByWorktree = { + 'wt-1': [{ id: tabId, ptyId, launchAgent: 'codex' }] + } + + await connectRestoredPaneForForegroundSampling({ ptyId, tabId }) + await advanceVisibleForegroundRead() + + expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) + }) + + it('does not sample when a live hook row already supplies pane identity', async () => { + vi.useFakeTimers() + const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) + getForegroundProcess.mockResolvedValue('codex') + const ptyId = 'pty-hook-identity-no-sample' + const tabId = `tab-${ptyId}` + mockStoreState.agentStatusByPaneKey[makePaneKey(tabId, LEAF_1)] = { + state: 'working', + agentType: 'codex' + } + + await connectRestoredPaneForForegroundSampling({ ptyId, tabId }) + await advanceVisibleForegroundRead() + + expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) + }) + + it('does not sample when process identity is already known', async () => { + vi.useFakeTimers() + const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) + getForegroundProcess.mockResolvedValue('codex') + const ptyId = 'pty-process-identity-no-sample' + const tabId = `tab-${ptyId}` + mockStoreState.paneForegroundAgentByPaneKey[makePaneKey(tabId, LEAF_1)] = { + agent: 'codex', + shellForeground: false + } + + await connectRestoredPaneForForegroundSampling({ ptyId, tabId }) + await advanceVisibleForegroundRead() + + expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) + }) + + it('does not re-sample once 133;D proved the pane is at a shell prompt', async () => { + vi.useFakeTimers() + const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) + getForegroundProcess.mockResolvedValue('codex') + const ptyId = 'pty-shell-foreground-no-sample' + const tabId = `tab-${ptyId}` + mockStoreState.paneForegroundAgentByPaneKey[makePaneKey(tabId, LEAF_1)] = { + agent: null, + shellForeground: true + } + + await connectRestoredPaneForForegroundSampling({ ptyId, tabId }) + await advanceVisibleForegroundRead() + + expect(foregroundReadCallsFor(ptyId)).toHaveLength(0) + }) + + it('re-samples a shell-marked pane a launch agent still owns', async () => { + // Why: a reattach or a full-screen agent's leaked nested-shell 133;D leaves + // shellForeground on a launchAgent pane, suppressing its icon. The launch + // metadata means an agent is expected, so re-read to recover its identity. + vi.useFakeTimers() + const getForegroundProcess = vi.mocked(window.api.pty.getForegroundProcess) + getForegroundProcess.mockResolvedValue('codex') + const ptyId = 'pty-shell-foreground-launch-agent-sample' + const tabId = `tab-${ptyId}` + mockStoreState.tabsByWorktree = { + 'wt-1': [{ id: tabId, ptyId, launchAgent: 'codex' }] + } + mockStoreState.paneForegroundAgentByPaneKey[makePaneKey(tabId, LEAF_1)] = { + agent: null, + shellForeground: true + } + + const { cacheKey } = await connectRestoredPaneForForegroundSampling({ ptyId, tabId }) + await advanceVisibleForegroundRead() + + expect(foregroundReadCallsFor(ptyId)).toEqual([[ptyId]]) + expect(mockStoreState.setPaneForegroundAgent).toHaveBeenCalledWith(cacheKey, { + agent: 'codex', + shellForeground: false + }) + }) + }) + describe('terminal input liveness IPC gating (perf)', () => { // Why (perf regression guard): listSessions() is a renderer→main→daemon // round-trip over every live session. Terminal input must never start that diff --git a/src/renderer/src/components/terminal-pane/pty-connection.ts b/src/renderer/src/components/terminal-pane/pty-connection.ts index dffa30c47d8..31713d1e92b 100644 --- a/src/renderer/src/components/terminal-pane/pty-connection.ts +++ b/src/renderer/src/components/terminal-pane/pty-connection.ts @@ -5,6 +5,7 @@ import type { IBuffer, IDisposable } from '@xterm/xterm' import { resolveCursorAgentImeAnchor } from '@/lib/pane-manager/terminal-ime-anchor' import { detectAgentStatusFromTitle, + agentTypeToIconAgent, isGeminiTerminalTitle, isClaudeAgent } from '@/lib/agent-status' @@ -164,6 +165,7 @@ import { normalizeCompatibleAgentTitleForOwner, resolveCompatibleAgentTypeForOwner } from '../../../../shared/agent-title-owner' +import { resolveExplicitTerminalTitleAgentType } from '../../../../shared/terminal-title-agent-type' import { isExpectedAgentProcess, recognizeAgentProcessFromCommandLine @@ -666,6 +668,10 @@ let inactiveForegroundImmediateBudgetWindowStart = 0 type PanePtyBinding = IDisposable & { syncProcessTracking: () => void noteVisibilityResume: () => void + /** Re-sample process identity when the pane gains intra-tab focus: the tab + * icon follows the active leaf, and a shell-marked entry on a still-running + * agent pane has no OSC boundary left to correct it. */ + sampleForegroundAgentOnFocus: () => void reconcileIfSessionDead: (liveSessionIds: Set, snapshotRequestedAt?: number) => void reconcileIfSessionMissing: (hasPty: HasPty, livenessRequestedAt?: number) => void } @@ -1751,12 +1757,81 @@ export function connectPanePty( } return pendingWrite.then(() => interruptInference.flushPending()) } + // Why: a launched/hook-known agent pane must confirm — not trust — a 133;D so a + // full-screen agent's leaked nested-shell 133;D can't clear its tab identity, + // even on a restore where no command-start read has recorded evidence yet. + const paneHasKnownAgentIdentity = (): boolean => { + const state = useAppStore.getState() + const entry = state.agentStatusByPaneKey[cacheKey] + if (entry?.state !== 'done' && agentTypeToIconAgent(entry?.agentType)) { + return true + } + const tab = (state.tabsByWorktree[deps.worktreeId] ?? []).find( + (candidate) => candidate.id === deps.tabId + ) + return Boolean( + tab?.launchAgent ?? paneStartup?.launchAgent ?? paneStartup?.initialAgentStatus?.agent + ) + } + // Why: a plain `codex`/`grok` sets its OSC title and the shell never repaints + // it on exit, so a confirmed return-to-shell must clear a title that still + // names an agent — otherwise the tab reads "grok" over a bare prompt. Only + // reset an agent-named title; user/shell-set titles are left untouched. + const clearStaleAgentTabTitleOnConfirmedShell = (): void => { + const state = useAppStore.getState() + const currentTitle = state.runtimePaneTitlesByTabId?.[deps.tabId]?.[pane.id] + const tab = (state.tabsByWorktree[deps.worktreeId] ?? []).find( + (entry) => entry.id === deps.tabId + ) + const title = currentTitle ?? tab?.title + if (!title || resolveExplicitTerminalTitleAgentType(title) === null) { + return + } + const neutralTitle = neutralTerminalTitle() + deps.setRuntimePaneTitle(deps.tabId, pane.id, neutralTitle) + if (manager.getActivePane()?.id === pane.id) { + deps.updateTabTitle(deps.tabId, neutralTitle) + } + } const paneForegroundAgentTracker = createPaneForegroundAgentTracker({ getPtyId: () => transport.getPtyId(), isTrackablePtyId: (id) => !isRemoteRuntimePtyId(id) && parseAppSshPtyId(id) === null, readForegroundProcess: (id) => window.api.pty.getForegroundProcess(id), - publish: (entry) => useAppStore.getState().setPaneForegroundAgent(cacheKey, entry) + publish: (entry) => useAppStore.getState().setPaneForegroundAgent(cacheKey, entry), + hasKnownAgentIdentity: paneHasKnownAgentIdentity, + onConfirmedShellForeground: clearStaleAgentTabTitleOnConfirmedShell }) + const sampleVisiblePaneForegroundAgent = (): void => { + if (!deps.isVisibleRef.current) { + return + } + const state = useAppStore.getState() + const foreground = state.paneForegroundAgentByPaneKey[cacheKey] + // Why: live process identity already paints the icon — nothing to read. + if (foreground?.agent) { + return + } + const entry = state.agentStatusByPaneKey[cacheKey] + if (entry?.state !== 'done' && agentTypeToIconAgent(entry?.agentType)) { + return + } + const tab = (state.tabsByWorktree[deps.worktreeId] ?? []).find( + (candidate) => candidate.id === deps.tabId + ) + const expectsAgent = Boolean( + tab?.launchAgent ?? paneStartup?.launchAgent ?? paneStartup?.initialAgentStatus?.agent + ) + // Why: with no shell mark yet, launchAgent bootstrap already paints the icon, + // so a read is pointless. Otherwise probe the foreground: a shell mark (from a + // reattach or a full-screen agent's leaked nested-shell 133;D) can hide a + // still-running agent — including a manually started one with no launchAgent or + // hook, which no later 133;C will reseed. A genuinely idle shell just returns a + // shell name and publishes nothing, so the probe is self-limiting. + if (!foreground?.shellForeground && expectsAgent) { + return + } + paneForegroundAgentTracker.onVisiblePtyBound() + } const commandLifecycle = createTerminalCommandLifecycle({ onCommandStarted: () => paneForegroundAgentTracker.onCommandStarted(), onCommandFinished: () => { @@ -1829,6 +1904,14 @@ export function connectPanePty( ) { return } + // Why: user shell frameworks (bash-preexec/iTerm2) can replace Orca's + // OSC 133;C hook, so a manually launched agent produces no command-start + // signal at all. Enter at a shell-foreground prompt is the user-side + // equivalent; the sample is gated to panes with no live agent identity + // and publishes nothing for an idle shell. + if (event.key === 'Enter' && !event.metaKey && !event.ctrlKey && !event.altKey) { + sampleVisiblePaneForegroundAgent() + } deps.clearTerminalTabUnread(deps.tabId) deps.clearTerminalPaneUnread(cacheKey) deps.clearWorktreeUnread(deps.worktreeId) @@ -2225,7 +2308,11 @@ export function connectPanePty( } const bindActivePanePty = ( ptyId: string, - options: { seedInitialAgentStatus?: boolean; updateTabPtyId?: 'always' | 'if-missing' } = {} + options: { + seedInitialAgentStatus?: boolean + updateTabPtyId?: 'always' | 'if-missing' + sampleVisibleForegroundAgent?: boolean + } = {} ): void => { if (activePanePtyBinding && activePanePtyBinding !== ptyId) { reportPanePtyVisibility(activePanePtyBinding, false) @@ -2248,6 +2335,11 @@ export function connectPanePty( // frame-level sync often runs before that async result arrives. scheduleRuntimeGraphSync() agentCompletionCoordinator.startProcessTracking() + // Why: fresh spawns receive future OSC command-start events; only adopted or + // restored PTYs may already be inside Codex with no new foreground signal. + if (options.sampleVisibleForegroundAgent === true) { + sampleVisiblePaneForegroundAgent() + } } const onPtySpawn = (ptyId: string): void => { @@ -3657,7 +3749,10 @@ export function connectPanePty( ) { // Why: daemon createOrAttach can turn an apparent fresh spawn into // a reattach; the transport skips onPtySpawn there to preserve recency. - bindActivePanePty(resolvedPtyId, { updateTabPtyId: 'if-missing' }) + bindActivePanePty(resolvedPtyId, { + updateTabPtyId: 'if-missing', + sampleVisibleForegroundAgent: true + }) } if (resolvedPtyId) { reconcilePtySizeAfterSpawn(resolvedPtyId, cols, rows) @@ -5223,6 +5318,7 @@ export function connectPanePty( deps.syncPanePtyLayoutBinding(pane.id, ptyId) deps.updateTabPtyId(deps.tabId, ptyId) agentCompletionCoordinator.startProcessTracking() + sampleVisiblePaneForegroundAgent() // Why: mobile terminal streaming needs the exact screen state from // xterm.js. The shared helper installs both the SerializeAddon-backed @@ -5784,7 +5880,10 @@ export function connectPanePty( onError: reportError } }) - bindActivePanePty(attachPtyId, { updateTabPtyId: 'if-missing' }) + bindActivePanePty(attachPtyId, { + updateTabPtyId: 'if-missing', + sampleVisibleForegroundAgent: true + }) if (attachPtyId === eagerLivePtyId) { registerPaneSerializerFor(attachPtyId) } @@ -5838,7 +5937,10 @@ export function connectPanePty( }) // Why: this path reuses a PTY spawned by an earlier mount, so no // later spawn event will bind this remounted pane's DOM/container. - bindActivePanePty(spawnedPtyId, { updateTabPtyId: 'if-missing' }) + bindActivePanePty(spawnedPtyId, { + updateTabPtyId: 'if-missing', + sampleVisibleForegroundAgent: true + }) }) .catch((err) => { reportError(err instanceof Error ? err.message : String(err)) @@ -5948,6 +6050,10 @@ export function connectPanePty( noteVisibilityResume() { ptySizeReassertion.request({ fit: false }) consumeHibernatedAgentWake() + sampleVisiblePaneForegroundAgent() + }, + sampleForegroundAgentOnFocus() { + sampleVisiblePaneForegroundAgent() }, reconcileIfSessionDead, reconcileIfSessionMissing, diff --git a/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts b/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts index e037e1e7f83..bcf5835a687 100644 --- a/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts +++ b/src/renderer/src/components/terminal-pane/use-terminal-pane-lifecycle.ts @@ -1281,6 +1281,13 @@ export function useTerminalPaneLifecycle({ persistLayoutSnapshot() } reportActiveRendererPtyForPane(paneTransportsRef.current, pane.id) + // Why: the tab icon resolves from the active leaf's process identity; + // focusing a shell-marked pane whose agent is still running must + // re-sample it, since no further OSC boundary will. + const focusedBinding = panePtyBindings.get(pane.id) as + | (IDisposable & { sampleForegroundAgentOnFocus?: () => void }) + | undefined + focusedBinding?.sampleForegroundAgentOnFocus?.() // Why: when the user switches focus between split panes, update the // tab title to the newly active pane's last-known title so the tab // label reflects the focused agent — not a stale title from the