Skip to content

room-share: a room whose stored joined floor is above its own seq shows nothing, and never heals #2754

Closed

Description

@HugoXK

Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.

Written-by: FlyBot Lead

Bot: FlyBot Dev-1 (found it; read-only reproduction against live main f2ef4dfa, two runs byte-identical)

What happens

A room whose stored membership floor is above its own room.seq renders no lines at all, and it never heals: every new line lands below the floor, so the history stays empty even as messages arrive.

#2612 / #2613 stopped new shares from storing the host's counter as the guest's floor, but a room that already carries such a value keeps showing nothing, because nothing clamps it: joinedSeqOf returns the stored value as-is and roomHistory filters with (line.seq ?? 0) >= from.

Reproduced on live main f2ef4dfa (read-only, two runs identical): room.seq = 2, log seq 1,2, participants and sharedFrom both joinedSeq = 202 → joinedSeqOf = 202 → roomHistory = 0 rows; after mirroring a line at seq 3 it is still 0 rows; warnings: [], no exception. Source core/src/host/room-membership.js:325-326 .filter(line => (line.seq ?? 0) >= from).

Priority, measured: a participant's joinedSeq wins; sharedFrom.joinedSeq only falls back when no participant carries one (A2 participants 202 / sharedFrom 0 → 202; A3 participants 0 / sharedFrom 202 → 0). So a fix that only touches sharedFrom does nothing.

Expected

The floor is clamped on the read path: when the computed floor is above room.seq, treat it as room.seq — the guest sees the line it joined at, plus everything that arrives later. The stored state object is not rewritten (rewriting would turn the clamp into a fact on disk).

Scope / acceptance

Binding shape, agreed 2026-11-09:

  • core/src/host/room-membership.js: module-level joinedSeqOf / linesVisibleTo stay pure (their unit test keeps 0/1/2/3 → 2/2/1/0); the instance level gets floorOf(room, actor) doing the clamp + memo + warn, and both read entries rt.linesVisibleTo (:448) and rt.roomHistory (:887) go through it.
  • Clamp target is room.seq, not 0: 0 would show the guest history from before it joined.
  • A (participants 202 / sharedFrom 202) asserts 1 row (seq 2). A2 (participants 202 / sharedFrom 0) also asserts 1 row — that is the case a sharedFrom-only fix misses, so it is asserted, not commented. A3 (participants 0 / sharedFrom 202) asserts 2 rows: the participant's value wins, the clamp does not fire, and it is the positive control that the priority rule was not inverted. After mirroring seq 3, A and A2 assert 2 rows.
  • Positive control: floor 0 → 2 rows, 1 → 2 rows, 2 → 1 row, 3 → 0 rows (do not clamp the healthy boundaries away).
  • warn once per room (not once per source), carrying the room id, the pre-clamp floor and room.seq; a healthy room produces no warning. The clamp value is memoised with the floor computed on the first read (that read's room.seq): recomputing room.seq on every read would push the clamp up and leave only the newest line. The memo may be keyed per (room, actor), but the warn dedup key must be the room id alone, so two readers still produce one warning.
  • Restart check: a fresh instance/store over the same fixture bytes still shows 1 row and warns exactly once (a second load on the same instance does not re-run — store.js:806 loaded ??=).
  • Memory only: state.json is not rewritten.

Dedup: #2612 (closed) and #2613 (merged) fixed the source; this is the existing-state half, which still reproduces on f2ef4dfa. guest floor / joinedSeq searches show no other open same-face issue.

Activity

  1. added 3 commits that reference this issue on Nov 10, 2026
    8f8aaaf
    74d08c5
    2cd5c29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions