Skip to content

Sharing to a home member that was deleted reports success and can never deliver #1125

Open

Description

@Birfy

Written-by: Triage

Status 2026-10-26: the local half is delivered. Route (b) — the honest row — landed as #1128 (15d7e525): a row whose Bot the other home removed is drawn removed: true with the reason, its Share is disabled, and social/share-with-friend refuses with bot/removed-bot before posting any grant. What remains on this issue is route (a) only — revoking the grant when a home member is removed, which is a Bot Social behaviour and cannot be closed in this repository. needs-human stays until that side agrees.

Split out of #970, which closed as fixed (#973 made the panel resolve the friend per Bot). That fix leaves this behind, and it is a product behaviour, not a client bug — hence needs-human.

What happens

  1. B removes one of its Bots from the home (remove_home_member succeeds on B's side).
  2. A's relationship with that Bot stays active on Bot Social.
  3. A's "Share with a friend" still lists that Bot, e.g. Coder (SelfTest B2).
  4. A clicks Share: the panel reports Shared Chief with selftestb2., the row then disappears because the fresh grant hides it, and nothing can ever arrive — the Bot it was granted to no longer exists on that home.

So the owner gets a success message for a grant that is dead on arrival, and the only way to notice is that no line ever comes back.

Two routes (both are acceptable; the owner picks one)

(a) Retire the relationship when the member goes. Removing a home member revokes the grants that name it, so step 3 cannot offer a Bot that is gone. Cleanest for the owner-facing meaning of "revoke", but it changes what removal means across the network and it is a Bot Social behaviour, not ours — it needs the server side to agree.

(b) Keep the grant, make the row honest. The panel marks a row whose Bot no longer exists as not shareable, with the reason ("this Bot was removed from that home"), and never posts the grant. Fully inside plugins/social, no protocol change.

Acceptance

Why not agent-ready yet

Route (a) is a protocol-level decision the owner has to make with the Bot Social side; route (b) is ours but the choice between them is not. Say "route (b)" and this becomes agent-ready in the same round with owner assigned.

Activity

  1. added
    bugSomething isn't working
    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)
    area:socialFriends, invites, grants, Bot Social
    on Oct 25, 2026
  2. Birfy commented on Oct 25, 2026

    @Birfy
    CollaboratorAuthor

    Owner decision (2026-10-25)

    Direction (a): removing a member also drops the grant, so the other home stops listing a Bot that no longer exists there. The protocol side has to agree with Bot Social, so split it:

    • the local half can start now: never report success for a row whose Bot is gone (fixes "reports success, can never arrive");
    • the cross-repo half (revoke on removal) needs the Bot Social side and stays on this issue as the second half.

    @triage: turn the local half into an agent-ready follow-up if it is cleaner as its own issue; keep this one for the protocol change.

  3. Birfy commented on Oct 25, 2026

    @Birfy
    CollaboratorAuthor

    Written-by: Triage

    Owner's call (2026-10-25): route (a) — removing a home member revokes the grants that name it. That is the behaviour to aim at, and it is not a client-only change: it is a Bot Social behaviour that has to be agreed with the server side, which is why this issue stays needs-human.

    Split done, so neither half waits on the other:

    • this issue = the protocol/behaviour half: on remove_home_member, retire the relationship (or the grants that name it) so the panel cannot offer a Bot that is gone. Needs the Bot Social side to agree on what "retire" means for an existing relationship.
    • the client half is now its own issue: the panel must stop printing a success line for a grant that cannot deliver. It is worth doing even if (a) lands, because (a) only travels with the server version that implements it, and until then every host on an older server can still share to a deleted Bot.

    Acceptance for this half: a test that drives a home-member removal and asserts the grants naming that member are gone (or the relationship is marked retired) and that a subsequent share to it fails visibly rather than reporting success.

  4. Birfy commented on Oct 26, 2026

    @Birfy
    CollaboratorAuthor

    Route (b) — decision from the task lead, 2026-10-26. Keep the grant, make the row honest.

    Why not (a) today: (a) changes what removing a home member means across the network, and the grants live on the Bot Social side, so it is a protocol decision that needs that side to agree — it cannot be closed inside this repository. (b) is fully inside `plugins/social`, removes the lie the owner actually sees (a success line for a grant that can never deliver), and does one thing: a row whose Bot no longer exists is rendered not-shareable with the reason, and no grant is posted.

    If Bot Social later adopts (a), this row-level guard stays correct and harmless: it only stops us from posting a grant we already know is dead.

    Acceptance is the card's, unchanged:

    This turns the card `agent-ready`; owner assigned in the group board.

  5. Birfy commented on Oct 26, 2026

    @Birfy
    CollaboratorAuthor

    Written-by: Dev4

    Route (b) is already on main — it shipped as #1128 (PR #1139, merge 15d7e525, an ancestor of 1e9f1844), so this card needs no new branch. The acceptance in the decision comment above is met by code and tests already in the tree:

    • plugins/social/src/social.js — removedOnRoster (:3141-3153): a row is judged against the roster the panel already reads (remoteBots() → list_remote_bots, "Bots granted to me").
    • social/share-friends — a row whose Bot the friend's home no longer lists comes back removed: true with the reason <name> was removed from that home. Sharing with it cannot reach anyone. (:3214-3217).
    • social/share-with-friend — before any grantBotToFriend, the same predicate refuses with bot/removed-bot (:3277-3283), so no grant is posted and the panel never prints a success line for it.
    • plugins/social/client.js — the row stays drawn with share-friend-removed, its Share is disabled, and a click that still arrives says why instead of calling the host (:3488-3489, :3527-3535).

    Tests that start from exactly this state — B removed the Bot, A's relationship is still active:

    What I ran at 1e9f1844: cd plugins/social && TZ=UTC node --import ./test/resolve.mjs --test test/social.test.js → # tests 449 / # pass 449 / # fail 0. Not run: the rest of npm run verify (core, tree, timeline, lint) — the card changes no file, so there is no tip of mine to verify.

    One residual, and it is the part that needs the server (route (a)). removedOnRoster refuses only on positive evidence: the home is in the roster and lists other Bots while the relationship's Bot is absent (or its handle is absent). A home that drops out of the roster entirely, or is listed with an empty bots list, decides nothing and the share goes through as before — the three knife tests (#1139) lock that in on purpose, because a cold or failed roster read must not disable a legitimate row. So in the case where the removed Bot was the friend's only Bot, the row can still post a grant that reaches nobody until Bot Social retires the relationship on remove_home_member (route (a), this issue's protocol half). Tightening the client half to treat a missing home as a removal is a product call, not a code fix: it would also refuse shares while the roster is merely stale.

    No branch, no PR from me on this one — the client half is done and main is green. The protocol half stays with this issue.

  6. Birfy commented on Oct 26, 2026

    @Birfy
    CollaboratorAuthor

    Written-by: Triage

    不转 agent-ready:路线 (b) 已经在 main 上交付完了。 #1128(客户端半边)在 2026-10-25 10:29Z 以 15d7e525 合入,1e9f1844 上就是它:

    • plugins/social/src/social.js:3141-3155 removedOnRoster():只有 roster 缓存里有这个 home、且两个名字(Bot id 与 handle)都不在,才判「已移除」;缓存缺失不猜;
    • :3213-3219 分享列表每一行先 rowGone()、在 :3217 打 removed: true 并给 reason(docs/subsystems/social.md:165);plugins/social/client.js:3535 把 Share 置灰、:3527-3528 画出 share-friend-removed 那行、:3488 点击时给出同一句 reason;
    • :3279-3283 就算点击绕过置灰,social/share-with-friend 也会在发 grant 之前(:3291 的 grantBotToFriend 之前)以 bot/removed-bot 拒绝;
    • 两条验收在 plugins/social/test/social.test.js:活着仍报成功并发 grant、被移除则不报成功也不发 grant。

    所以给 Dev4 开卡只会让他重做一遍已合入的东西。这张单剩下的只有 (a) 协议半边:remove_home_member 时收回 grant —— 那是 Bot Social 服务端行为,本仓改不了,needs-human 保留(我不会去别人的上游仓库开单)。#1128 的正文也写着「Not this issue: revoking grants on member removal (#1125)」。

    我把这条状态补进正文头,免得下一轮又按「面板报假成功」来分诊。

    (2026-10-26 01:36 更正锚点:Dev4 在 1e9f1844 上复核,removed: true 在 :3217、守卫在 :3279-3283;先前的 :3188 是 rowGone() 的调用处、:3280-3282 差一行。)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:socialFriends, invites, grants, Bot SocialbugSomething isn't workingneeds-humanThe agent loop stopped; a person must decide (reason in the last comment)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions