Don't call a turn finished with a message still waiting behind it
A message written into the tail of a turn is read the moment that turn's `result` lands: the session reports idle and is running again in the same breath. The phone that sent it got "finished" in between -- seconds before anything it asked for had been done, which is the notification arriving to say the opposite of what is happening. `notification_for` now takes how many messages the session has been given and not started reading, and a turn ending with any of them waiting is not an ending. The count is kept in `pump`, from the recorded events, because that is the one place that sees all of them in transcript order: a `messageQueued` up, and the `userMessage` that resolves it or a `messageDropped` down. Asking the driver instead would answer about the moment the question was asked rather than the moment the status was written, which is the same class of mistake as reading a session's status to decide what a queue contains. It deliberately does not suppress *awaiting input*. A question is worth interrupting somebody for whatever is queued behind it -- the queue is precisely what will not move until it is answered. Tested both halves: the decision on the number, and the number itself, where an echo turn that reads its queued message before going idle still announces its finish. That last is the case a suppression written slightly wrong silences, and it is the common one.
This commit is contained in:
1 parent
bfaf5e6f38
commit
a1eedd7a78
2 files changed
+118
-15
No files matched your search
@@ -925,6 +925,19 @@ level: the session on screen is registered by the one composable that draws
|
||||
one, and "the app is up" *is* the banner queue being collected, since it
|
||||
collects only while it is on screen.
|
||||
|
||||
**What counts as finished** is decided in `notification_for`, and since
|
||||
2026-08-31 it takes the number of messages the session has been given and
|
||||
not started reading. With one waiting, a turn ending is not the work
|
||||
ending: a message written into the tail of a turn is read the moment that
|
||||
turn's `result` lands, so the session goes idle and immediately runs again
|
||||
-- and the phone that sent it was told its work had finished, seconds
|
||||
before any of it was done. The count is kept in `pump` from the recorded
|
||||
events (`MessageQueued` up, the `UserMessage` that resolves it or a
|
||||
`MessageDropped` down), because that is the one place that sees every event
|
||||
in transcript order. It does not suppress *awaiting input*: a question is
|
||||
worth saying whatever is queued behind it, and the queue is exactly what
|
||||
will not move until it is answered.
|
||||
|
||||
The alternative considered and rejected was giving the app its own
|
||||
connection to `/notifications` while it is in front. That is a second stream
|
||||
per device saying the same thing, and it puts the "which of these two shows
|
||||
|
||||
Reference in new issue
Block a user