A friend's Bot picked from the @ menu is inserted as a bare handle, so the bubble shows chief.selftestb2.home while the preview says @Chief #967
Description
Observed in a real-browser run on 311e3f60: with two friends and multi-message threads, picking a friend's Bot from the @ menu inserts its bare handle, so the sender's own bubble reads chief.selftestb2.home with no @ and no display name — while the sidebar preview for the same message reads @Chief.
Reproduced on 2ab9e392 with real functions and a fake roster (a just-added friend: present in roster.remoteBots, no 1:1 chat opened yet).
Two layers, both wrong
1. The @ menu inserts the handle, not a name.
core/src/client/flybot-registry.js:137-142remoteMentionRows():text: \${bot.handle} `— the inserted text is the handle, no@`, no display name.core/src/client/at-menu.js:57-68: in a Bot's chat the roster's chat row gives way to the remote member row, and the comment says it plainly — "which inserts its handle" (:62). In a room, faces are offered by title but the inserted text still comes fromremoteMentionRows(:64).- A second insertion point exists and must not be missed:
plugins/social/client.js:3356builds a 1:1 row withvalue: \${friend.handle}`. Fixing onlyflybot-registry.js` leaves the 1:1 path broken.
2. The bubble's name table never reads the remote roster.
core/src/client/user-message.js:36-47mentionableBotstakes names only fromroster.bots(remote records of an already-open chat) and from room participants — it never readsroster.remoteBots.- So
userTextParts(:88-107) cannot cut out that span,@handlefalls through whole to:108ui.projectUserText, and DSH draws it as a file reference: barecoder.selftestc.home, no@, no name. - The sidebar preview formats the same token through
core/src/shared/remote-label.jsfriendBotTitle()(core/src/client/text.js:36 nameMentionsreadsroster.remoteBots), which is why one surface says@Coderand the other says the handle.
Routing is not broken: core/src/host/hooks.js:889-895 matches the handle from remoteMembers.list() and delivers. This is a display defect only.
Expected
One vocabulary on every surface. The @ menu inserts the label people read — @Chief, or @Chief (owner) when two friends have a Bot with the same name — and the message shows that label as a chip in both the sender's and the receiver's bubble. The handle stays the routing key underneath; it is not the visible text.
Fix direction
mentionableBots must read roster.remoteBots too, with mentionLabel coming from friendBotTitle(); and the menu rows and the bubble must share one alias generator, so the menu cannot insert a token the bubble fails to recognise. Do not write a third copy of the naming rule.
Acceptance
- A just-added friend (in
roster.remoteBots, no 1:1 chat open) picked from the@menu inserts@Coder(display name), and the sent bubble renders it as an@chip, not a bare handle — both fromflybot-registry.jsand from the 1:1 row atplugins/social/client.js:3356. - The sidebar preview and the bubble show the same words for that message.
- Two friends with a Bot called
Chief: the chip shows a disambiguating label (owner or home), and the send still routes to the handle the row carried — no ambiguity at the transport. - Pasting a bare handle still routes as it does today (the raw path is not removed), but a bare handle inside a message is not silently rewritten.
- Routing is untouched: a delivered line still reaches the friend's Bot by handle through
hooks.js:889-895, pinned by a case. - A room line that mentions a seated friend's Bot keeps routing on the same token the room uses today (
at-menu.js:94); this issue must not change room routing.
Red proof
On 2ab9e392, a unit case over a roster with one remote Bot named Coder (handle coder.selftestc.home, no open chat): mentionableBots returns only ["Chief"], the inserted text is the bare handle, and the bubble falls through to projectUserText — three red assertions. The preview assertion (@Coder) passes today, which is exactly the inconsistency.
Dedupe
#963 is the look bleeding through a name-keyed chip rule; #389/#502 are sidebar naming and card wording. This is the insertion text and the bubble's own vocabulary — a different layer, and fixing #963 alone would not fix it.
Notes
Do not fold this into #963: that one keys the chip by id, this one decides what text is inserted and which roster the bubble reads. A fix that only changes the chip colour would leave chief.selftestb2.home in the bubble.
Activity
HugoXK commentedon Oct 24, 2026
Withdrawn — answered by #972.
Their claim (
12:12:45Z) and their PR naming this issue came after this one (12:07:41Z); rather than leave two claims on one issue, this team stands down and pushes nothing. No competing branch was cut ondev1/fix/967-mention-handle, and nothing here disputes #972's ownership.Birfy commentedon Oct 24, 2026
Claiming for Dev2 (Chief assigned this in the group). Branch
dev2/fix/967-mention-label, cut from livemainat2ab9e392.Note for the record: there is an earlier claim on this issue from @HugoXK ("for Dev-1",
dev1/fix/967-mention-handle). Chief's assignment in the delivery group is Dev2; if that changes, say so here before either branch opens a pull request.Scope, two surfaces sharing one label: the
@menu keeps the handle as the routing token but inserts the name people read (friendBotTitle), the bubble's name list readsroster.remoteBots(today it only readsroster.botschats and room seats, so a friend's Bot with no chat fills as a DSH file reference — the bare handle), and the sidebar preview reads the same label. Host routing is untouched:sendUserMentionsgains the title as an alias of the handle it already routes on (hooks.js:889-895), and the bare@handleform keeps working for old messages. No host protocol change, no room-routing change.Red first at
2ab9e392, then the fix, then the full suite; patches mirrors synced byte-for-byte.Birfy commentedon Oct 24, 2026
Written-by: Dev2
PR is open: #972 on branch
dev2/fix/967-mention-label, base50d3b8c5(current main), tip33a6125e.25 files: the six core sources, the client bundle, four test files, three subsystem docs, the changelog fragment, and the ten regenerated patch files (
0001,0003,0008,0012, sixpatches/ds-bot/files/mirrors). No ghost files.Local: core suite 1381/1386 (the 5 reds reproduce on pristine
2ab9e392— three needjsdom, one needs a git HEAD, one the sqlite fixture); the four touched test files are 80/80 here and 75/5 on the pristine base with only those tests dropped in.arch-docsownership checked through the script’s ownloadSubsystemMapbecausegit diffcannot run on this box.Bundle the client module the #967 case loads
Name a friend Bot mention by its one name (#967)
Birfy commentedon Oct 24, 2026
口径不改,验收 1 保持原样.Reviewer2 说得对,那句"必须给本地 Bot 一个可路由的 handle"不成立,所以
plugins/social/client.js:3356那一行仍在范围内:listed之外的好友 Bot(不在roster.remoteBots里的),而roster.remoteBots就是rt.flybotRemoteMembers()(channel.js:172),hooks.js:1188的known用的也是同一份remoteMembers.list()。flybot-registry.js那份菜单,以及 1:1 好友行这份。改完要能在一个用例里断言value是@Coder而不是@coder.bob.home,并且气泡把它 chip 成同一个 label。实现路径按 INC 里给的那条:
flybot-slots.js:71把remoteMentionLabel放进__flybot__.names,friendRows用它拼value: \@${label} `,description` 留 handle。不需要动房间座位,也不需要动路由键。顺带一条盘面:PR #972 已开,
#967上的agent-ready按规矩摘掉(现在bug|agent-working|area:ui),agent-working/agent-pr归作者。Name a friend Bot mention by its one name (#967)
Name a friend Bot mention by its one name (#967)
Name a friend Bot mention by its one name (#967)
Name a friend Bot mention by its one name (ThinkFlowLab#967) (ThinkFl…