fix(activity): keep badge in step with monitoring turns; drop dead cache branch (#19535)

Monitoring turns emit no working event (4b2e3dded0), so the titlebar
badge must not count them either, or it lights with no unread row to
clear. The build cache's cached-events ternary could never take its
cached path because the early return above already covers it.
This commit is contained in:
Jinjing
2026-09-07 22:28:23 -07:00
committed by GitHub
parent 990674f7e3
commit 3b00cfcb2d
3 changed files with 19 additions and 18 deletions
@@ -87,21 +87,19 @@ export function resolvePaneBuild(
return { events: cached.events, live: cached.live }
}
const events =
inputsUnchanged && liveMatchesCache
? cached.events
: buildPaneActivityEvents({
entry: rowEntry,
worktree: request.worktree,
repo: request.repo,
tab: request.tab,
agentType: request.agentType,
agentAlive: request.agentAlive,
acknowledgedAt: request.acknowledgedAt,
clearedAt: request.clearedAt,
liveState: request.liveState,
migrationUnsupportedPtyId: request.migrationUnsupportedPtyId
})
// The live turn is itself an event, so a live change always rebuilds the pane's events.
const events = buildPaneActivityEvents({
entry: rowEntry,
worktree: request.worktree,
repo: request.repo,
tab: request.tab,
agentType: request.agentType,
agentAlive: request.agentAlive,
acknowledgedAt: request.acknowledgedAt,
clearedAt: request.clearedAt,
liveState: request.liveState,
migrationUnsupportedPtyId: request.migrationUnsupportedPtyId
})
const live: ActivityLiveAgentSnapshot | null =
request.liveState === null
? null
@@ -114,13 +114,14 @@ describe('countActivityUnread source overlap', () => {
})
describe('countActivityUnread working turns', () => {
it('counts fresh working and monitoring, but not historical or retained working', () => {
it('counts fresh working, but not monitoring, historical, or retained working', () => {
const entry = makeEntry({
state: 'working',
stateHistory: [{ state: 'working', prompt: 'old', startedAt: 1_000 }]
})
expect(countActivityUnread(makeSource(entry), 2_000)).toBe(1)
expect(countActivityUnread(makeSource({ ...entry, workingMode: 'monitoring' }), 2_000)).toBe(1)
// Monitoring emits no unread event in the list (4b2e3dded0), so the badge must not count it.
expect(countActivityUnread(makeSource({ ...entry, workingMode: 'monitoring' }), 2_000)).toBe(0)
expect(
countActivityUnread(
{
@@ -39,9 +39,11 @@ export function countActivityUnread(source: ActivityUnreadCountSource, now = Dat
}
}
// Why: a session-boundary done is an idle connect (STA-3386), not an event to read.
// Why 'working' only: a monitoring turn surfaces through the live snapshot, never as an
// unread event, so counting it here would light the badge with no unread row to clear.
if (
(isHistoricalActivityState(entry.state) ||
(live && freshActivityLiveAgentState(entry, now) !== null)) &&
(live && freshActivityLiveAgentState(entry, now) === 'working')) &&
entry.sessionBoundary !== true &&
mutedAt < entry.stateStartedAt
) {