feat(service): the planning conversation's held read is woken by its mark over Neon Realtime
Stacked on #3267 (luke/neon-realtime-planning-conversation), which stacks on #3266, #3232 and #3217. This is the second planning-conversation PR in the series moving Luke's reads onto Neon Realtime.
What changes
#3267 moved the hold for a desktop that follows the conversation's mark into the host. The service's own held read of /api/plans/{id}/messages?after= is still used by older desktops. That read still looked again every 250 ms.
brainPagePast now waits with #3266's lookedUntil and takes the conversation's mark statement from planConversationLiveStatements (added in #3267) as its live statement:
- It looks again whenever the mark changes over Realtime, and every 5 s as a safety check. There is no
BRAIN_POLLfallback.
The /messages route passes the mark. A read with hold=none is unchanged.
Tests
task-work.test.tsscripts aLiveWake. A held read on a running turn is answered as soon as the watch fires after the turn settles, even thoughTestClocknever moves, and it watched exactly the mark's statement. On the old poll, that read would wait for the clock.- The existing held-read tests provide a scripted wake and drive the safety beat.
pnpm check:affectedpasses exceptapps/desktop/src/main/app-menu.test.ts, which fails in the sandbox because Electron can't install there.
Made with Luke
Summary by cubic
Wakes the planning conversation's held message reads on the conversation's mark over Neon Realtime instead of polling every 250 ms.
brainPagePastnow waits vialookedUntilon the mark statement, so a held read looks again as soon as the mark changes, plus a 5 s safety check.- Where Realtime is unavailable it falls back to
BRAIN_POLLexactly as before. - The
/messagesroute passes the mark along; reads withhold=noneare unchanged. - Adds a test that a held read hears a settling turn when the mark fires even though
TestClocknever moves.