fix(mobile): keep a hook status that postdates the shell title on the session tab strip (#33614)

The mobile session tab strip no longer shows Done while the workspace list shows Working: once the PTY-title renewal has kept a newer non-done status against the same clocked OSC title, the mobile projection no longer re-demotes it without the clock (seen on Windows ConPTY where the spawn-time cmd.exe title lingers).

Supersedes #32472

Co-authored-by: zhangxaochen <3416677+zhangxaochen@users.noreply.github.com>
This commit is contained in:
Neil
2026-10-25 12:39:50 -07:00
committed by GitHub
co-authored by zhangxaochen
parent c6ce72d0c2
commit e04f4dc8a9
2 changed files with 42 additions and 1 deletions
@@ -207,6 +207,40 @@ describe('mobile session tabs: live-title evidence vs published agent status', (
expect.objectContaining({ state: 'done', prompt: '' })
)
})
it('keeps a hook-backed working status that postdates an initial Windows ConPTY shell title', async () => {
vi.useFakeTimers()
try {
vi.setSystemTime(T0 - 1_000)
const runtime = await createRuntime()
runtime.onPtyData(PTY_ID, '\x1b]0;C:\\WINDOWS\\system32\\cmd.exe\x07', T0 - 1_000)
vi.setSystemTime(T0)
publishRendererWorkingPane(runtime, 'C:\\WINDOWS\\system32\\cmd.exe')
expect(await projectAgentStatus(runtime)).toEqual(
expect.objectContaining({
state: 'working',
prompt: 'Configurar y entender los comprobantes',
updatedAt: T0
})
)
// Once a newer shell title arrives after the hook, it retires the working status to done.
vi.setSystemTime(T0 + 1_000)
runtime.onPtyData(PTY_ID, '\x1b]0;C:\\WINDOWS\\system32\\cmd.exe\x07', T0 + 1_000)
expect(await projectAgentStatus(runtime)).toEqual(
expect.objectContaining({
state: 'done',
prompt: '',
updatedAt: T0 + 1_000
})
)
} finally {
vi.useRealTimers()
}
})
})
describe('mobile session tabs: identity-only fallback freshness', () => {
@@ -226,10 +226,17 @@ export function projectRuntimeMobileSessionTabs(
const hasLiveAgentSignal =
normalizedTabAgentStatus?.interactivePrompt != null ||
normalizedTabAgentStatus?.toolName != null
// A title renew already dated against the hook (e.g. ConPTY's spawn-time shell title) cannot re-demote it (#32467).
const hookOutlivedAdjudicatedTitle =
normalizedTabAgentStatus?.state !== 'done' &&
statusPty?.lastOscTitleEpochMs != null &&
liveTitleEvidence === (statusPty.lastOscTitle?.trim() || null)
// Only shell/management proves release; neutral Terminal/editor/cwd titles cannot justify done that fights clients' live status.
const keepFullAgentStatus =
normalizedTabAgentStatus &&
(!terminalTitleBlocksExplicitAgentStatus(liveTitleEvidence) || hasLiveAgentSignal)
(hookOutlivedAdjudicatedTitle ||
!terminalTitleBlocksExplicitAgentStatus(liveTitleEvidence) ||
hasLiveAgentSignal)
const agentStatus = keepFullAgentStatus
? { agentStatus: normalizedTabAgentStatus }
: // Idle titles drop stale working spinners but retain transcript identity for native chat.