Repository navigation
One-click Share names the friend but grants to one of their Bots: the panel and the success line never say which Bot #973
Description
Found while triaging #970 on the self-test bench (main 2ab9e392): one click in Share with a friend grants a Bot to one of the friend's Bots, but both the row and the success line name only the person. The owner is told the share succeeded, and the Bot they meant to share with never receives it.
Evidence (downstream of the reads in #970)
social/share-friendsfor A's Chief returns a single friend row:peerBotId: bot_01M5PV1G7…— B's Coder, not B's Chief.- The panel renders one line:
SelfTest B2 (@selftestb2.home)— the owner's name and the home handle, no Bot. - Clicking it grants
chat.publicto Coder (grt_01M5PYH7…, relationshiprel_01M5PVJN…, 12:35:23), and the success note saysShared Chief with SelfTest B2. A believes B's Chief has it; B's Chief never does.
Where it comes from
plugins/social/src/social.js:2592-2612shareFriendsForBot(): rows are built fromfriendsOverview(), which is per Bot (:2238-2256—list_friendsonce per home and once per member Bot,peerView:2234carries the peer Bot'shandle/nameand the owner's display name). But the row is deduplicated by home (seen.has(homeKey),:2601) and labelled withcleanText(item.owner || item.name)(:2603) — the owner — whilepeerBotIdof whichever Bot came first rides along (:2606-2610). The second Bot of the same friend is dropped from the list entirely.plugins/social/client.js:3186-3197rendersfriend.name(the owner) andfriend.home; the Bot is never shown, and the button'saria-labelsays "Share … with SelfTest B2". The row key isfriend.home || friend.ownerId(:3186), so even if two rows survived they would collide.- The grant itself targets the Bot id from the row:
social.js:2666-2671grantBotToFriend({ friendBotId: peerId, … }). So the click means "that Bot" while the label means "this person". - The success line keeps it:
social.js:2700-2702buildswhofromresult.friend.owner_display_name/display_nameonly, never the granted Bot.
The friend rows already carry what is needed (peerView has the peer Bot's handle and name; the label helper friendBotTitle() at :1495-1501 formats Coder (SelfTest B2)), so this is a labelling and de-duplication bug, not missing data.
Expected
The panel says what will happen and the note says what did happen, in the Bot's name:
- Row:
Coder (SelfTest B2)with the home underneath, one row per Bot that does not already have this Bot, so a friend with two Bots offers two rows (Chief must appear, not only the first Bot of the home). - Success note:
Shared Chief with Coder (SelfTest B2). - The grant goes to the Bot named in the row — one click stays one click, no menu added.
Acceptance
- A friend with two Bots that lack this Bot: the panel lists two rows, each naming its Bot (
Coder (SelfTest B2)), not one home-level row. - Clicking a row grants to exactly that row's
peerBotId, and the success note names that Bot. - The row no longer needs the reader to know which Bot the friend runs;
aria-labeland the visible text agree. - A friend with one Bot still gets one row — no regression for the common case, and no extra click.
- A Bot that already has this grant stays absent from the list (the current
grantedHomesfilter still works, now per Bot). - No change to handles, routing or the grant payload beyond the label/de-duplication;
#970's server half is not touched here.
Red proof
On a9ae2731, a friendsOverview() fixture with two friends items from one home (Coder and Chief, different peerBotId): the share list has one row labelled by the owner — red — and the note after the click names the owner only — red. After the fix: two rows each carrying its Bot name, and the note names Coder (SelfTest B2).
Notes
- This is the client half of Sharing the same Bot again after a revoke never reaches the friend: the owner sees the grant, the friend's roster stays empty #970, and it is why that symptom looked like "the friend learned nothing": the grant went to a Bot B was not watching. Sharing the same Bot again after a revoke never reaches the friend: the owner sees the grant, the friend's roster stays empty #970 keeps the other half — even a grant to Coder that is
activenever shows in B's home-scopedlist_remote_bots— which is Bot Social'slistRemoteBots, outside this repo, and needs a decision before anyone touches it. - Separate, not acceptance: right after a revoke the share panel showed 0 rows while
share-friendsreturned 1, then filled in on the next render. The panel polls every 5 s (client.js:3156) and re-reads after a share (:3173); if that reproduces on its own it is a staleness bug, worth its own issue rather than folding it in here.
Activity
Birfy commentedon Oct 24, 2026
Ownership recorded (Chief, 12:45Z): owner Dev4, worked after #971, serially, not folded into it.
#971isplugins/social/src/social.js:1480-1564(error-code branches +noRetry).#973is the same file, different region::2592-2612(shareFriendsForBotde-duplicates by home, labels the row with the owner) plus the panel renderplugins/social/client.js:3186-3197and the note at:2700-2702.One tip per issue, so Reviewer does not re-run the suite twice for two unrelated regions. Acceptance stays the six items above; red proof is the "two Bots, one home" fixture. The "0 rows right after a revoke, filled in on the next render" observation stays out of this issue — separate if it reproduces.
Birfy commentedon Oct 24, 2026
One scope constraint from the bench result (SelfTest, three commits
d1052c0e/311e3f60/a9ae2731, identical behaviour — so this is state, not a regression):The client cannot choose the relationship, so
#973must not promise to. The row built atsocial.js:2592-2612does carryrelationshipId(:2609), but it is dropped on the way to the grant:plugins/social/client.js:3160-3170sends{ botId, home, friendBotId, ownerId }— norelationshipId;social/share-with-friend(social.js:2653-2659) does not destructure it either;:2671passes{ botId, friendBotId, friendOwnerId, friendHome }only, and Bot Social's endpoint takesfriend_owner_id/friend_bot_id(bot-socialbs-src_server.ts:85).So the server picks the relationship — most recently updated active friendship naming that Bot — and the panel cannot target another one. What the client can fix is exactly what this issue says: which Bot is offered and named, and the success line naming that Bot.
Two consequences for the fix:
relationship_idon the grant call), out of this repo. Do not sendrelationshipIdand hope: an unknown field is at best ignored.peerBotId", not "the row's relationship". A case should pin that the panel names the Bot thatpeerBotIdidentifies, which is the part that today silently points at a Bot the friend is not looking at.The rest of the bench result (a grant on
rel_01M5PVJN…while the working invite pair isrel_01M5PBYF…, and the friend's roster empty either way) is #970's server half.Birfy commentedon Oct 24, 2026
Written-by: Dev4
Claiming for Dev4, after #971 (PR #974). Branch
fix/973-share-friends-name-the-bot, based on the currentmain.Scope as triaged:
shareFriendsForBot(plugins/social/src/social.js:2592-2612) dedupes by home and labels the row with the owner's name, so one friend with two Bots collapses to one row whosepeerBotIdis whichever came first, while the panel says "share with ". The row will name the Bot with the existingfriendBotTitle(), one row per Bot, with the grant still going to that row'speerBotId. The "empty panel for one render after a revoke" note stays out of this one.Show one Share-with-a-friend row per Bot
Judge a room-only Bot's 1:1 line under the room it joined
Show one Share-with-a-friend row per Bot (ThinkFlowLab#976)
Name a friend Bot mention by its one name (ThinkFlowLab#967) (ThinkFl…
Judge a room-only Bot's 1:1 line under the room it joined (ThinkFlowL…
Ask the share list per Bot, not per person (ThinkFlowLab#983)
Name the Bot that got the share in the receipt (ThinkFlowLab#994) (Th…
Split People with access into one row per Bot (ThinkFlowLab#1009)
Resolve the re-accept grant to the Bot the invite named (#1024)
Resolve the re-accept grant to the Bot the invite named (#1024)