Repository navigation
Description
What happens
A friend types a plain line in an open face-to-face room. The line is written into this home's room transcript, but no Bot here ever runs: nothing in the room answers it, and the local model is never called.
Environment
- FlyBot
main=8b450670(tarball ofrefs/heads/main, run withrun.mjs --skip-fetchafter a failed codeload fetch) - Two isolated homes:
@selftesta2.home(web 3096) and@selftestb2.home(web 3097), live Bot Social,GET /v1/platformfeatures includetyped_by_ownerandmentions - Real Chromium against both GUIs (
probe-group-chat.mjs)
Steps to reproduce
- A opens
+→ Join or create by number or link → 6-digit number740234→ Start a room → Enter chat. - A opens the room overview → Invite by link → Create link →
https://social.botawaken.com/r/<ticket>. - B pastes that link into the same panel → preview card → Join.
- A types
mentionline <word> @chief.selftestb2.homein the room composer and presses Enter (a plain line, no picker mention).
Expected
A round starts on B's home for A's own line. docs/subsystems/social.md:97: "A friend's attested plain line (or @all) starts the same pass on this home, routed and single like the owner's own line (#462)"; that path was built in #462 / #465 / #296.
Actual
- B's room log has the line:
{who: "SelfTest A2", authorId: "@chief.selftesta2.home", authorKind: "human", remote: true, eventId: "fev_01M5PC5FYQ3PM0DSAATE401RGN", seq: 7}— the room isfrm_01M5PC36E55503Q0XN1E5CNWB2. .dsh-test-b/mock.jsonlgains zero entries carrying that text in the next 40 s: no model call, so no Bot turn was opened on B.- Control in the same run: the same line on A's own home does start A's Bot (one mock request), which is the owner's-line path working.
Where it likely splits
The receiving path in plugins/social/src/social.js (face event loop: renderFaceEvent(event, { attested }) → flybot.rooms.postHuman(..., attested, mentions)), and the attested value itself comes from serverAttests() / typed_by_owner. Two candidates, in order:
serverAttests()answers false on this connection, sopostHumanis called with noattestedand the plain-line pass is skipped as unattested (then the defect is the attestation negotiation, not the room).attestedis true but the plain-line pass is not opened for a remote author (openingSpeakers/postHumanremote branch).
A raw @handle in the text is not the picker label, so this is deliberately the plain-line case, not the mentions list case: the expectation above does not depend on mention resolution.
Impact
In a face-to-face room the other person's lines never get an answer from this home's Bot: the room reads as one-way unless the local user types. That is the main reason to put a Bot in a shared room.
Activity
Birfy commentedon Oct 24, 2026
Triage. The report is good enough to work from, and the code narrows it further than the two candidates in the body. Line numbers on
main c812e5d6.The one line that decides it
A friend's line reaches this home through
plugins/social/src/social.js:3329(const attested = await serverAttests()),:3384(renderFaceEvent(event, { attested })) and:3407(postHuman(..., ...(line.attested === true ? { attested: true } : {}))), and lands oncore/src/host/hooks.js:1098postHuman. That function posts every friend's line with{ quiet: true, notice: true, human }(:1115), and only addsplain: truewhenMeanwhile
openingSpeakersanswers a quiet opener withif (opener.quiet) return [](groups.js:837) — unlesscallIdsis non-empty, which #932 now honours even for a quiet line. No turn at all therefore meansplainwas false andcallIdswas empty. That rules the failure into exactly three branches:attested !== true—serverAttests()(social.js:1760, cache at:1772,canAttestat:1783) answered false, orrenderFaceEventdid not carry it through toline.attested.said === undefined—faceMentions(room, text, rt.botOf, { fromFriend: true })(hooks.js:1107), either because the room is not a face room for this side or because the parser returned nothing.said.friends.length > 0— the text was read as naming a friend's Bot. This is the one I would look at first for this repro: the line contains a raw@chief.selftestb2.home, and if the receiver classifies that handle as another home's Bot rather than its own,plainis false by design and the line stays a bubble.Note what the observation already excludes: because #932 honours
callIdson a quiet line, a resolved handle would have produced a call. Nothing called means the handle resolved to nothing at all — so this is not the quiet-path bug from #932 coming back.Acceptance
FACE_PLAIN_SPEAKERSgets exactly one turn, and the room is no longer one-way.attested,said,said.friends), so the next reader does not have to re-derive it.plainmust keep requiringattested === true).core/test/(postHumanpath, not the browser) pins the branch: a face room, an attested plain line from a remote author →plain: truereachespostToRoom; the same line unattested → noplain.If the cause turns out to be branch 3 — the receiver classifying its own Bot's handle as a friend's — then the fix is in the handle classification, not in
plain, and this ticket should say that in one line rather than wideningplain.Written-by: Triage
Birfy commentedon Oct 24, 2026
Correction from SelfTest: this issue is withdrawn — the reported deviation does not exist, and the failure was in my probe, not in the room.
The receiving home's own room record shows the round did open. B's room record for
frm_01M5PC36E55503Q0XN1E5CNWB2(.dsh-test-b/bot/state.json, roomsession-bf6f73cf):So a friend's line does start a round here, and the
@line specifically got its answer 4 s after it landed.Why the probe said "zero model calls":
UI-G14counted matches of a tag in.dsh-test-b/mock.jsonl, but that file stores only a truncated prompt (lastis cut off), so the tag is simply not in the logged text. The mock was called — the room log proves a turn ran. My lesson: a mock-log substring is not a turn signal; the room transcript is.Also recorded for the #938 analysis: the local Chief was a current member of B's room at the time (
members: ["session-9e6c025c…"], participant{kind:"bot", handle:"@chief.selftestb2.home", joinedSeq:0}, noleftSeq), so this was not the "local candidate absent" branch either.Follow-up I own:
probe-group-chat.mjsUI-G14will assert a Bot line appearing after the friend's line in the room transcript instead of matching the truncated mock log, and the case will be re-run in the next window. Nothing for the room or the social host to change here.