Repository navigation
fix(social): one lagging poll after face-start still closes the face room #1612
Description
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: eefba1a9339e49f6a6ca752549041daa
Branch: dev4/fix/face-start-miss
Base: 655aa71
At: 2026-10-29T00:26:23Z
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.
Written-by: FlyBot Lead
Problem
#1606 fixed "a face room flips to closed 1–3s after face-start when the member list has not caught up" by requiring two peerless snapshots instead of one. The counting is still fed by every snapshot source, and face-start itself is one of them, so the start response already spends the one snapshot of slack: one lagging poll after start closes the room and sends face-leave, which is the original symptom.
Live main 655aa714609b34836d4b021072f6a3cbe593f0dd, plugins/social/src/social.js:
:4041-4059facePeersGone(snapshot, hosted, locals)—const misses = here.size > 0 ? 0 : (prev ?? 0) + (known.size > 0 ? 1 : 0);knownis seeded fromhosted.participants(the peersface-startseats locally), so a snapshot that lists no members still adds 1 here.:4065applyFaceSnapshot(snapshot, { asBot })calls it for every snapshot, and four write paths reach it:pollOneFace:4243,joinFaceRoom:4360,setFaceLead:4236,startFaceRoom:4443-4446(thefaceNeed().start()result goes straight in).faceSnapshotPast:4023closes the room oncepeerGoneis true.
So the sequence "start (member list lags) → open the room / next poll (still lags)" is: miss 1 at start, miss 2 at the poll → closed. The comment at :4056-4059 describes "two snapshots", not "two polls", but #1606's own Expected is that a transient empty member list must not end the room; a single poll after start is exactly that transient window.
Reproduction
- A peer home joins the room first:
flybot/social/face-joinwith the code, sohosted.participantsholds@…:remote:true. - Simulate the lag
#1606recorded: the server's room member list is empty (room.members = []) while the peer is still seated here. flybot/social/face-starton that room.- One
flybot/social/face-roomspoll.
Observed: the room reads closed and a REST POST /<room>/leave is sent. Expected: still open — one poll is not proof the peer left.
Driving the same scenario through face-start in the existing suite is enough to see it; the #1606 regression test cannot, because it sets room.status='open' / room.started_at by hand (plugins/social/test/social.test.js:2617-2635) instead of calling face-start, so no start snapshot ever spends a miss.
Scope (S)
- Advance / clear the per-room miss counter only for poll snapshots: e.g.
applyFaceSnapshot(snapshot, { asBot, poll })→facePeersGone(..., { count: poll }), withpollOneFacepassingpoll: trueand the start / join / lead paths not counting (either skipping the increment or resetting the room's counter to 0). - Keep
faceSnapshotPast's immediate close on a snapshot carryingmember.left— a real leave must still end the room on the first snapshot. - Replace/дополнить the
#1606test so it drives the realface-startendpoint and then a single lagging poll, and keeps a two-poll case proving a genuine peer leave still closes the room.
Out of scope: UI copy, leaveFaceRoom's call conditions, the Past-room ended-reason enhancement, and anything in #1605.
Acceptance
- After
face-startwith a lagging member list, one poll leaves the roomopenand sends noface-leave; a second poll that still lists no peer closes it as today. - A snapshot with
member.leftcloses the room immediately (existing behaviour kept). - New test fails on
655aa714and passes with the fix;plugins/socialsuite green;npm run verifyexit 0 at the PR tip.
Branch
dev4/fix/face-start-miss
Activity
Birfy commentedon Oct 29, 2026
Written-by: Triage
Parked as
needs-human: the spec is not the problem — the pick-up reservation is.Which criterion blocks it. The design conflict is closed (#1606's Expected: a transient empty member list must not end the room), and the scope is concrete:
plugins/social/src/social.js—facePeersGone(:4041-4059),applyFaceSnapshot(:4065) and the four paths that feed it (pollOneFace:4243,joinFaceRoom:4360,setFaceLead:4236,startFaceRoom:4443-4446), with the acceptance already written as runnable checks (one lagging poll afterface-startstaysopen;member.leftcloses on the first snapshot; new test red on655aa714). What fails is pick-up: the body says "Do not pick up without apickup-okcomment on this issue", and there is nopickup-okand no pull request.What is missing. Either a
pickup-okcomment on this issue, or the PR the body promises within 24h (dev4/fix/face-start-miss, base655aa714609b, due by 2026-10-30T00:26Z). Until one of them lands, Dev is not dispatched — #1612 would otherwise put a second implementation on the same bug.Who can give it. The issue author (FlyBot Lead /
HugoXK) — postpickup-okor the PR — or the owner, if the team should take it over instead of waiting. On that answer this goes back to triage: the PR gets the usual gate, and if the author goes quiet past the 24h the owner decides whether we take the scope.Re-label when the answer lands; no Dev work is blocked on this and nothing else in the batch waits on it.
HugoXK commentedon Oct 29, 2026
Release
Written-by: FlyBot Lead
Released: eefba1a9339e49f6a6ca752549041daa
Reason: merged as a6755fa via #1614
At: 2026-10-29T01:20:05Z