Skip to content

rooms: a live member is shown working for the whole of its turn, and a reply that lands unseen is on the pill - #133

Merged
udaychandra merged 4 commits into
mainfrom
rooms/turn-began-and-unseen-reply
Oct 13, 2026
Merged

udaychandra merged 4 commits into
mainfrom
rooms/turn-began-and-unseen-reply

Conversation

@udaychandra

@udaychandra udaychandra commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Spec: mast-live-room-member. Closes what #132 left short of it. Sail's side is standardapplied/sail#310.

What was wrong

  • R4, scenario 6. A room showed nothing between a send and the first text or tool step on every turn after the first of a run. The typing row keys off the run's start, and a live member is one run across many turns. With a model that thinks before it writes, that is a dead room for as long as it thinks.
  • Nothing said a turn was still open. A draft is drawn like a message, so once it had text a reader could not tell "still working" from "done" until the Markdown render replaced it.
  • R2, scenario 14. A reader who scrolled away during a turn got no "N new" pill when its reply landed: the reply is drawn where its draft was, and only buffered messages counted.

What changed

  • agent_turn_began (sail#310) joins the live event types and opens the turn's draft with nothing in it. It rides the same list as the other three, so it is on the room stream's type= query and in the telemetry and non-record sets with no further change.
  • A draft draws the typing dots while its turn's end has not been told: alone when nothing is written yet, under the text and tool lines after. TypingRow and the draft share one TypingDots.
  • A stream gap says nothing of a member working: a draft that had written nothing is dropped, one with text loses its dots, and the turn's next event brings either back. Otherwise the dots would outlive a member that died during the gap.
  • A reply that takes a draft's place while the reader is away counts on the pill until they return (repliesUnseen), unless it was already drawn before they left. A turn behind the pill counts once it has written something.
  • The demo's scripted turn begins with agent_turn_began.

Against a box without sail#310

No agent_turn_began arrives, so the wait before the first text or tool step of a later turn is as it was. Everything else here works: the dots under an open draft, and the pill. Sail 0.47 ignores a name it does not know in type=.

Release order

Mast before sail. A Mast without this change treats agent_turn_began on the app-wide stream as an unknown type and refreshes the room once per turn. The same holds today for the released pair: Mast 0.1.96 does not know sail 0.47's three live types (#132 taught it), so it refreshes on every delta of a live turn until 0.1.97 ships.

Verification

  • bun run typecheck, bun test (1,394 pass, 0 fail), bun run build:tauri-web; CI verify green.
  • New tests: the reducer for a beginning (opens an empty draft, fills, blank end, named end, drops a prior error bubble, behind the pill when the reader is away, dropped by a gap and drawn again); the room for a later turn of the same run (nothing after the send, dots at the beginning, dots under text and a running tool, none once the end is told), a blank turn, a turn that failed before writing, a gap, the typing row yielding to a beginning, the pill for a reply landing unseen, for one already seen, for a turn that has written nothing, and its reset on return and on a room swap.
  • 23 mutants over the changed lines, all killed (one survived until its test was made to reach the line).
  • Three independent reads. The first found one medium (dots outliving a member that died during a gap) and two pill miscounts, all fixed; the second found nothing high or medium. A third commit that traded two cosmetic cases for two others was backed out, so the code merged is the code the second read passed.
  • Drawn in headless Chromium against the real component and CSS: dots alone at the beginning, under text and a running tool, gone when the reply takes the draft's place, nothing left after a blank turn. The follow-the-latest scenarios A to O from rooms: the agent's reply appears as it is written #132 were re-run on this branch's first commit and behave as before; no scroll code changed after it.
  • Not exercised: macOS WKWebView and a live box.

Small things left, in draft mast-draft-yields-to-its-own-reply

  • After a stream gap the dots stay off until the turn's next event.
  • A turn that streamed nothing shows a row with only the member's name between its end and its message arriving.
  • With the typing row showing and the reader scrolled away, a turn's beginning hides the row until the turn writes.

@udaychandra
udaychandra merged commit ad7dcca into main Oct 13, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant