Skip to content

read_group_chat bypasses the join-floor clamp, so a Bot's floor above seq reads a full room as empty #2790

Closed

Description

@HugoXK

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

Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: 4bc854af8bdd4889a31174abc5395f83
Branch: dev/1-read-group-floor-clamp
Base: 74d08c5
At: 2026-11-10T07:56:41Z

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

Written-by: FlyBot Lead
Bot: FlyBot Dev-1

Problem

#2754 gave the host read paths a clamp: a reader whose joinedSeq sits above room.seq (a join that landed on a floor the room has not reached yet) is read against the room's actual floor instead of the stale one, once, with one warn — floorOf in core/src/host/room-membership.js, used by rt.linesVisibleTo and roomHistory (the pane and every other reader).

read_group_chat never goes through it. At core/src/host/groups.js:1044-1046 it takes the Bot's own participant record and filters the log directly:

const from = botPart?.joinedSeq ?? 0

So when a Bot's recorded floor is above room.seq, the filter keeps nothing and the tool answers "<room>" has no messages yet. — while the same room keeps its lines for every other reader (pane, read_own_chat, the human actor path). A Bot then decides nobody has said anything in a room that is full of messages.

read_own_chat's group branch (groups.js:972-980) is not this defect: it reads its own parts and never filters room.log, so there is no floor to clamp there.

Red first (on live main 74d08c5d)

With only core/test/room-read-floor-clamp.test.js on a clean 74d08c5d tree:

# tests 5 / # pass 2 / # fail 3
not ok 1 - ... a room with lines reads as empty: "Ops" has no messages yet.
not ok 2 - ... (same actual)
not ok 5 - ... (same actual)

The two guards are already green on base (a healthy floor is not clamped; an empty room still answers its own sentence), so the three reds sit exactly on the defect.

Expected

A Bot reading its own group must see what the same room shows everyone else: when its recorded floor is above the room's floor, the read clamps to the room's floor, once, with the existing single warn — the same semantics #2754 gave the other readers. A room that really has no lines still answers has no messages yet..

Scope

  • core/src/host/room-membership.js — extract the #2754 clamp as clampedFloorOf(room, record, reader) (memo, forget/rejoin, one warn per reader preserved; memo key gains a kind prefix so a human and a Bot with the same id do not share an entry); floorOf becomes a one-line call; add rt.seatFloor(room, seat) for the "read as my own seat" path. +7/−3.
  • core/src/host/groups.js — const from = rt.seatFloor?.(room, botPart) ?? botPart?.joinedSeq ?? 0 (fallback kept so a host without the plugin does not throw). +3/−1.
  • core/test/room-read-floor-clamp.test.js — new (111 lines, fixture modelled on room-read-honest-count.test.js): floor 9 / seq 5 returns the seq-5 line; a window that grows after the first read keeps both lines (memo semantics); a healthy floor 3/0 is untouched and emits no join floor above warn; an empty room keeps its sentence; a legacy room without seq clamps against the log's last seq.
  • docs/subsystems/core-host.md — one sentence saying the Bot's own read_group_chat goes through the same clamp, or a Docs-not-needed: trailer if the sentence would duplicate the existing paragraph.
  • One changelog fragment.
  • generate is required: groups.js and room-membership.js are upstream files carried in patches/ds-bot/ (0012-room-membership.patch already holds the read_group_chat hunk), so the PR must run generate + check + canonical and land the mirror in patches/ds-bot/files/.
  • Not this issue: #2754/#2759 (the clamp itself, human read path), #2780/#2783 (truncation counts), #2766/#2788 (per-line recompute), and the before window in read_group_chat (separate backlog item).

Acceptance

  1. The three red tests go green; the two guards stay green; core/test/room-*.test.js + group* + face-* neighbours stay green (254/254 read locally).
  2. core lint 0 errors (88 warnings are pre-existing on main), arch-docs: OK, changelog fragment well formed.
  3. generate is non-empty in patches/ds-bot/files/ and 0012 only changes if its own hunk changed; check prints the three ok lines; canonical reports generate is a no-op on the re-run.
  4. #2754's warn-once and rejoin-forgets-the-memo behaviour is unchanged for the human path (proved by the existing tests staying green).

Risk tier

T3 — core/src/host/** is a T3 paths row in .github/agent/risk-rules.json; the diff also carries patches/ds-bot/ output.

Dedup (checked when filed)

Live main 74d08c5d: floorOf is used only in room-membership.js; has no messages yet appears only at groups.js:1051 and in room-read-honest-count.test.js. GitHub search (no-cache) for "has no messages yet" → #2780, #2783, #101 all closed; joinedSeq → #2612, #2613, #2783, #2754, #82, #2759, #236, #2780 all closed; "join floor" → #2613, #2754, #2759, #2612, #2766, #683 all closed. No open issue or PR covers a Bot's own read_group_chat bypassing the clamp.

Bot: FlyBot Dev-1 discovered this (report P-676).

Activity

  1. HugoXK commented on Nov 10, 2026

    @HugoXK
    ContributorAuthor

    Claiming this for FlyBot Dev-1.

    Claim-Id: 4bc854af8bdd4889a31174abc5395f83
    Claimed-by: FlyBot Lead
    Branch: dev/1-read-group-floor-clamp
    Base: 74d08c5
    PR follows within 24h with Fixes #2790.

  2. HugoXK commented on Nov 10, 2026

    @HugoXK
    ContributorAuthor

    Release

    Written-by: FlyBot Lead
    Released: 4bc854af8bdd4889a31174abc5395f83
    Reason: merged as 2cd5c29 (PR #2791)
    At: 2026-11-10T08:44:02Z

  3. added a commit that references this issue on Nov 10, 2026
    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