fix(agent-hooks): carry evidenceObservedAt into the status snapshot

The fleet liveness projection reads getStatusSnapshot(), whose sole builder
dropped the observation clock, so every worker fell back to the delivery clock
and an hour-stale replayed agent read live.
This commit is contained in:
Jinwoo-H
2026-09-04 03:00:28 -04:00
parent e426592e5d
commit f067ab45e4
2 changed files with 19 additions and 0 deletions
@@ -72,6 +72,22 @@ describe('the observation clock a relay replay must not restamp', () => {
expect(replayed.evidenceObservedAt).toBe(T0)
})
it('carries the observation time out of getStatusSnapshot, not just the listener', () => {
ingest(server, { hook_event_name: 'UserPromptSubmit', prompt: 'do the thing' })
vi.setSystemTime(T0 + 25 * 60 * 1000)
server.clearStatusEntriesForConnection(CONNECTION)
ingest(
server,
{ hook_event_name: 'UserPromptSubmit', prompt: 'do the thing' },
{ isReplay: true }
)
// The fleet projection reads this snapshot, not the listener payload.
const row = server.getStatusSnapshot().find((entry) => entry.paneKey === PANE)!
expect(row.receivedAt).toBeGreaterThan(T0 + 25 * 60 * 1000 - 1)
expect(row.evidenceObservedAt).toBe(T0)
})
it('lets a live event restamp the observation time after a replay', () => {
ingest(server, { hook_event_name: 'UserPromptSubmit', prompt: 'do the thing' })
vi.setSystemTime(T0 + 25 * 60 * 1000)
@@ -59,6 +59,9 @@ export function toAgentStatusIpcPayload(
worktreeId: entry.worktreeId,
connectionId: entry.connectionId,
receivedAt: entry.receivedAt,
...(entry.evidenceObservedAt !== undefined
? { evidenceObservedAt: entry.evidenceObservedAt }
: {}),
stateStartedAt: entry.stateStartedAt,
...(entry.providerSession ? { providerSession: entry.providerSession } : {}),
...(entry.providerSessionOnly ? { providerSessionOnly: true } : {}),