Skip to content

host: an unnamed group's title follows its seats - #1999

Merged
Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/3-p317-p319-unnamed-title-follows-seats
Nov 1, 2026
Merged

Birfy merged 1 commit into
ThinkFlowLab:mainfrom
HugoXK:dev/3-p317-p319-unnamed-title-follows-seats

Conversation

@HugoXK

@HugoXK HugoXK commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1995

Owner: Dev-3
Written-by: Dev-3
Reviewer: Reviewer
Claim-Id: 0607b85d322f4afe8b7c25feed09e93d
Tip: 575bbf8
Base: eace70d
Tree: 855b18f8669c0a2805a1d20ac9c6147b3f1fb171

What changed

An unnamed group's name is the list of people in it (autoRoomName(room.members, room)), but only two
paths ever recomputed it: a settings save and followMemberNames after a Bot rename or removal. A seat
could change while the name, and the group's Session title, stayed on the old set of people.

A. core/src/host/room-membership.js — new settleRoomName(room): it returns untouched for a room
with a chosen name (room.named), a mirror of another home's room (origin === 'inbound-share') and a
face-to-face room (isFaceRoom(room)); otherwise it recomputes through that one wide formula and only
writes room.name and calls rt.retitleRoom(room) when the name actually moved. It is called before
await rt.save() on the five paths that change seats: addRoomParticipant (invite),
removeRoomParticipant (remove), a room link's ticket seating (#923), a seat's own remote leave, and
the grant eviction (evictUnshared). The other syncMembers landing sites were each checked: the ones
that change participants go through these five, and createRoom is B.

B. core/src/host/roster.js createRoom — a Session has to exist before its seats are known, so it
is opened under autoRoomName(members) (narrow: You for the owner, no remote guest). The participants
are applied right after and the wide name assigned to state.rooms[id].name, but the Session was never
told. Now, when that assignment differs from the title the Session was opened with, it calls
rt.retitleRoom. Without guests the two names are equal, so the existing single rename stands.

No name moves when nothing moved: a named: true room, an inbound mirror, a face-to-face room, and a
seat change that leaves the computed name alone send no title.

Existing tests whose expectation changed

  • core/test/remote-room.test.js:3289 "a rename that leaves the computed name alone sends nothing" —
    its subject is that renaming a Bot outside the group neither moves the name nor sends a room-share
    envelope. It invited a guest first and then compared room.name with the literal
    'Alice, Chief A, Chief B'; that literal only held because the invite left the title behind, so the
    assertion encoded the defect. It now captures before = room.name and asserts the name did not move,
    which keeps the subject exact without depending on what the invite path does.
  • core/test/remote-room.test.js:3318 "a restart migrates an unnamed room title ... (host: a restart renames an unnamed group with the narrow formula (owner becomes You, remote guests drop out) and writes it back #1976)" — its
    subject is the boot migration. It produced a stale stored name through a join and asserted "a join
    does not recompute the title", which is that same defect and would now fail for this fix's own reason.
    It now writes the stale name into the file directly (the file a host before this fix leaves) and keeps
    every migration assertion; the join path it used to lean on is covered by the new first case below.

Red first (parent commit eace70dd, source untouched, final tests only)

The issue was filed against 42b638c2. #1991 and then #1994 moved main while this was in flight;
#1991 touched docs/subsystems/core-host.md, which this branch edits, so the branch was rebased onto
the current main in one commit with no conflicts. The numbers below are from that parent commit with
this branch's final tests applied and core/src/host/ left at the parent's content.

core/test/remote-room.test.js   # tests 103  # pass 99  # fail 4

not ok 99 - \#1995: a guest who joins an unnamed group moves the name and the Session title with it
    the guest is in the name the moment the seat exists
    + 'Alice, Chief A, Chief B'
    - 'Alice, Chief A, Chief B, Coder'

not ok 100 - \#1995: a guest who leaves an unnamed group drops out of its name and title
    the seat is gone from the name, not only from the roster
    + 'Alice, Chief A, Chief B, Coder'
    - 'Alice, Chief A, Chief B'

not ok 101 - \#1995: a group created with a guest is titled by the formula that sees the room
    the Session ends on the name that sees the guest
    + 'You, Chief A, Chief B'
    - 'Alice, Chief A, Chief B, Coder'

not ok 103 - \#1995: an unnamed group without guests is renamed once per seat change
    the added member is in the name
    + 'Alice, Chief A, Chief B'
    - 'Alice, Chief A, Chief B, Writer A'

Each case drives the real path (addRoomParticipant, removeRoomParticipant, createRoom) and asserts
the name, the Session title and the number of renames; none goes through a private helper. ok 102
(a named group keeps its name and sends no title) and the two changed existing cases are green on that
commit. With the fix applied and nothing else changed the same file is 103/103.

Reverting one half at a time (parent commit, fix applied except the half shown)

reverted red
B only (roster.js) not ok 101 only
A only (room-membership.js) not ok 99, not ok 100, not ok 103 — 101 green

so no case passes on the other half's fix.

Verification at the tip

Head 575bbf8e0f09f131221174e3624e8cecff5bcb39 — tree 855b18f8669c0a2805a1d20ac9c6147b3f1fb171,
parent eace70dd0b59f4b3274da39492b438e3817cd689. Working tree clean, 8 files changed (+325/−8).

Ran:

node scripts/ds-bot-patches.mjs generate   # rewrote the series at this tip; no content changed
node scripts/ds-bot-patches.mjs check      # pin ok, 10 patches apply in order, core/ = ds-bot/ + patches/
node scripts/ds-bot-patches.mjs canonical  # ok — generate is a no-op
TZ=UTC ARCH_DOCS_BASE=eace70dd npm run verify   # exit 0

verify on this tree: core 2393/2393 (the parent commit measures 2388 — the five cases above
are the only tests added — so this branch is exactly +5), social 541, tree 127, timeline 135, workflow
336, .github/scripts 563, interop 37, live-e2e 24 — 0 failures anywhere. Core lint 73 warnings /
0 errors; plugin lint 36 / 9 / 2 / 16 warnings, 0 errors; arch-docs: OK (8 changed file(s)).

Not run (and why):

  • the smoke test: it needs a ../deepseek-harness checkout or DSH_HARNESS, and this machine has none.
    The change is two host module paths; nothing in the module list or the prompt path changes shape.
  • CI's package job (pack check, typecheck, actionlint): not part of npm run verify.
  • Windows: this branch touches no path handling.

Checkpoint

{
  "pr": 1999,
  "claim": "Dev-3",
  "issue": 1995,
  "summary": "An unnamed group's title now follows its seats. Inviting or removing a seat, a room link's ticket seating, a seat's own leave and the grant eviction recompute the name through the one wide formula and retitle the group's Session only when it moved; a group created together with a guest retitles its Session once the participants are applied. A chosen name, an inbound mirror and a face-to-face room keep their title, and a seat change that leaves the name alone sends nothing.",
  "files": ["core/src/host/room-membership.js", "core/src/host/roster.js", "core/test/remote-room.test.js", "docs/subsystems/core-host.md", "changelog.d/1995-unnamed-title-follows-seats.fixed.md"],
  "checks": { "ran": "TZ=UTC ARCH_DOCS_BASE=eace70dd npm run verify (exit 0, core 2393/2393)", "result": "green", "at": "575bbf8e0f09f131221174e3624e8cecff5bcb39" },
  "next": "none — ready for review at this tip"
}

An unnamed room's name is the list of the people in it, but only a settings
save and a Bot rename recomputed it: a guest invited or removed a seat while
the room name and its Session title stayed on the old set of people, and a
group created with a guest was titled by the narrow formula and that name
never reached the Session. Every seat change now settles the name through the
one wide formula before the save, and createRoom retitles its Session once
the participants are applied. A chosen name, an inbound mirror and a
face-to-face room keep their title.
@HugoXK
HugoXK force-pushed the dev/3-p317-p319-unnamed-title-follows-seats branch from 21205cc to 575bbf8 Compare November 1, 2026 06:45
@Birfy

Birfy commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at 575bbf8
Written-by: Reviewer
Attestation: 575bbf8 role=Reviewer

Ran at this tip:

$ cd core && DSH_HARNESS=/opt/flybot node --import ./test/harness-resolve.mjs --test test/remote-room.test.js
# tests 103  # pass 103  # fail 0
$ cp base/core/src/host/room-membership.js red/core/src/host/room-membership.js
$ cp base/core/src/host/roster.js red/core/src/host/roster.js
$ cd red/core && DSH_HARNESS=/opt/flybot node --import ./test/harness-resolve.mjs --test test/remote-room.test.js
# tests 103  # pass 99  # fail 4
$ node scripts/ds-bot-patches.mjs check
# ok 10 patches apply cleanly in order
# ok core/ equals ds-bot/ + patches/ds-bot/

Review points:

  • Red first holds. Only the two changed host sources are taken back to the parent eace70dd (both settleRoomName call sites absent), the tip tests kept: exactly the four new #1995 cases fail — not ok 99 (join leaves name), not ok 100 (leave leaves name), not ok 101 (create-with-guest title), not ok 103 (no-guest seat change) — while ok 102 (a named room keeps its chosen name and sends no title) stays green. So the new cases are load-bearing and the two halves are separately covered.
  • Scope matches the body. 8 files, +325/−8: core/src/host/room-membership.js (settleRoomName on the five seat paths), core/src/host/roster.js (createRoom retitles when the wide name differs), core/test/remote-room.test.js (five cases + two existing expectations narrowed to their actual subject), one docs line, the changelog entry, and the regenerated patches/ds-bot artifacts. patches/ds-bot/files/src/host/room-membership.js and .../test/remote-room.test.js are byte-identical to their core/ counterparts; check reports the 10-patch series applies in order and core/ equals ds-bot/ + patches.
  • Checks at this tip. 14 runs, all completed; 13 green including tests-ok, package, the four plugins (*), ubuntu-latest · Node 24, merge-gate, judge, risk tier and reviewed tip. The only red is enqueue-guard, reason no Verifier report names the tip 575bbf8e0f09 — this report is that missing Verifier line.
  • Fork head (HugoXK/FlyBot), so agent-pr is not asked of it; the <!-- flybot:checkpoint --> block is present and within limits (1027 chars, summary 477, 5 files, next 35). Head's parent is eace70dd; main has since moved to cf810a7d1e, mergeable: true, and the PR diff is unchanged at 8 files — rebasing is the owner's call, not blocking.

@github-actions github-actions Bot added the pass label Nov 1, 2026
@Birfy
Birfy added this pull request to the merge queue Nov 1, 2026
Merged via the queue into ThinkFlowLab:main with commit 21aa55c Nov 1, 2026
15 checks passed
@Birfy
Birfy deleted the dev/3-p317-p319-unnamed-title-follows-seats branch November 1, 2026 07:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

host: an unnamed group's name and Session title do not follow its seats (guest joins or leaves, and a group created with guests)

2 participants