From 014a4ef5e217550cf77a304e4b435113a4ea3ca0 Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Sun, 23 Aug 2026 18:00:06 -0700 Subject: [PATCH] fix(agent-status): avoid bare-name identity guesses --- src/shared/agent-title-evidence.test.ts | 7 ++++-- src/shared/agent-title-evidence.ts | 32 +++++++++++++++++++++---- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/shared/agent-title-evidence.test.ts b/src/shared/agent-title-evidence.test.ts index 68735fa996f..e01778da781 100644 --- a/src/shared/agent-title-evidence.test.ts +++ b/src/shared/agent-title-evidence.test.ts @@ -132,7 +132,10 @@ describe('collectAgentTitleEvidence', () => { it.each([ '◐ DaemonConnectionLostError with 70 Codex agents', 'Fix the grok hook', - 'Debug the cursor sidecar' + 'Debug the cursor sidecar', + 'grok', + '⠋ grok', + '⠋ codex' ])('declines %j', (title) => { expect(agentFor(title)).toBeNull() expect(reasonFor(title)).toBe('free-text-only') @@ -174,7 +177,7 @@ describe('collectAgentTitleEvidence', () => { }) it('does not duplicate an anchored token as free text', () => { - expect(collectAgentTitleEvidence('Codex').freeTextNames).toEqual([]) + expect(collectAgentTitleEvidence('codex.exe').freeTextNames).toEqual([]) expect(collectAgentTitleEvidence('Claude Agent Teams').freeTextNames).toEqual([]) }) diff --git a/src/shared/agent-title-evidence.ts b/src/shared/agent-title-evidence.ts index c74aa7aaff9..c454865b6fb 100644 --- a/src/shared/agent-title-evidence.ts +++ b/src/shared/agent-title-evidence.ts @@ -165,6 +165,22 @@ function agentForBareName(text: string): TuiAgent | null { return names.length === 1 && /^[\p{L}\p{N}]+$/u.test(bareToken) ? names[0] : null } +function agentForWholeTitle(text: string): TuiAgent | null { + const trimmed = text.trim() + if (!trimmed || /[\\/]/.test(trimmed)) { + return null + } + const stripped = stripBareNameDecoration(trimmed) + const label = DISPLAY_LABELS.find(([text]) => text === stripped.toLowerCase()) + if (label) { + return label[1] + } + if (!WINDOWS_LAUNCHER_SUFFIX_RE.test(stripped)) { + return null + } + return agentForBareName(stripped) +} + function agentForOwnerSuffix(text: string): TuiAgent | null { const normalized = text.toLowerCase() return ALL_TUI_AGENTS.find((agent) => agent === normalized) ?? agentForBareName(text) @@ -178,11 +194,13 @@ function agentForSyntheticTitle(text: string): TuiAgent | null { const normalized = trimmed.replace(/^[^\p{L}\p{N}]+/u, '').toLowerCase() for (const agent of SYNTHETIC_AGENT_TITLE_AGENTS) { const profile = SYNTHETIC_AGENT_TITLE_PROFILES[agent] + const emittedLabels = [profile.permissionLabel, profile.idleLabel] + if (profile.synthesizeWorkingTitle !== false) { + emittedLabels.push(profile.workingLabel) + } if ( profile.synthesizeTerminalTitle !== false && - [profile.workingLabel, profile.permissionLabel, profile.idleLabel].some( - (label) => normalized === label.toLowerCase() - ) + emittedLabels.some((label) => normalized === label.toLowerCase()) ) { return agent } @@ -254,10 +272,16 @@ function collectAnchoredNames(segments: readonly string[]): TuiAgent[] { const withoutSigil = segment.startsWith(`${CLAUDE_IDLE} `) ? segment.slice(CLAUDE_IDLE.length) : segment - const bare = agentForBareName(withoutSigil) + const bare = agentForWholeTitle(withoutSigil) if (bare) { anchored.add(bare) } + if (segment.startsWith(`${CLAUDE_IDLE} `)) { + const sigilClaim = agentForBareName(withoutSigil) + if (sigilClaim) { + anchored.add(sigilClaim) + } + } const synthetic = agentForSyntheticTitle(segment) if (synthetic) { anchored.add(synthetic)