Repository navigation
fix(agents): can't delete an agent belonging to an archived channel - #1560
Merged
johnmatthewtennant merged 4 commits intoOct 23, 2026
Merged
Conversation
The relay refuses membership changes in an archived channel ("invalid:
channel is archived"), but Delete required a fresh roster read to show
the agent in none of its channels. An agent left in any archived
channel could therefore never be deleted. Skip archived channels when
collecting the memberships to remove: the relay keeps them inert, and
Delete still archives the identity and removes its key.
Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: John Tennant <jtennant@block.xyz>
Test the loaded-channel filter as well as the roster lookup, and say in the Delete flow docs that archived channels keep the agent. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: John Tennant <jtennant@block.xyz>
johnmatthewtennant
marked this pull request as ready for review
October 23, 2026 14:31
…e-skip-archived-channels * origin/main: Bump tokio to 1.53.3 for RUSTSEC-2026-0386 (#1581) Unify attachment cards with neutral icon tiles (#1548) Polish edit context, channel join and profile actions (#1545) fix(claude-code): keep context across channel threads (#1516) fix(builderlab): let Create agent cancel a pending browser sign-in (#1526) test(sidebar-filters): start the focus journey on General (#1555) Add opt-in native MCP for macOS tests (#1528) Show unreads for channels after access changes (#1550) Deliver artifact changes through shared live routes (#1480) condense photo and video attachments into a compact grid (#1549) Signed-off-by: John Tennant <jtennant@block.xyz>
A loaded channel row can still read as unarchived after another client archived it. Delete then sent a removal the relay refuses, and every retry failed the same way. memberChannels now applies the fresh relay archive check to the loaded candidates as well as to the relay's rosters. Co-authored-by: Oliver <e78152627ea32fbacb070e5047afcfb8e409fa3343d9e618227baacca5b5e607@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: John Tennant <jtennant@block.xyz>
loganj
approved these changes
Oct 23, 2026
loganj
left a comment
Contributor
There was a problem hiding this comment.
🤖 Larry and Rbot: an independent adversarial review of 4aaf864. Source review only; we did not run the tests locally. Hosted CI is green.
Approve. We found nothing that needs a change.
What we checked:
- Both callers of the Delete cleanup (
relay-removal.ts:33andservice.ts:3355) go throughremoveAgentFromChannels, so the archive skip covers every delete path.memberChannelshas no other caller. - The relay does refuse membership writes in an archived channel (
buzz-relay/src/handlers/ingest.rs, "invalid: channel is archived"), so skipping those channels is the only way the fresh-roster confirmation can succeed. - The archive check is one batched, fresh 39000 read for all candidates, not one read per channel. A channel with no readable metadata stays in the removal set, which is the safe default. A stale loaded row that does not show the archive is still skipped, and the new test covers that case.
- Race: if a channel is archived between the metadata read and the 9001, the 9001 is refused and Delete reports "isn't deleted yet"; a second Delete then skips it. That is acceptable.
Advice (no change needed): exactLifecycleTag throws on a malformed archived tag, so one malformed relay-signed 39000 would now fail the whole Delete, where before it was not read. The relay signs these, so this is very unlikely.
johnmatthewtennant
deleted the
jtennant/oliver/delete-skip-archived-channels
branch
October 23, 2026 15:50
morgmart
added a commit
that referenced
this pull request
Oct 23, 2026
Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com> Co-authored-by: Carl <c217fe6b9d958f41c3a5e030dccc7f626775a923089cb6491305eade75ea1f1b@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * origin/main: (24 commits) Unify chat and channel access, tidy the Solo chat menu (#1446) fix(todos): render nested TODOs with collapsible hierarchy and Markdown (#1483) fix(agents): Allow agents to propose updates to agents (#1478) fix(composer): prevent plugins from updating the recipient on a WIP draft message (#1497) fix(agents): can't delete an agent belonging to an archived channel (#1560) Bump tokio to 1.53.3 for RUSTSEC-2026-0386 (#1581) Unify attachment cards with neutral icon tiles (#1548) Polish edit context, channel join and profile actions (#1545) fix(claude-code): keep context across channel threads (#1516) fix(builderlab): let Create agent cancel a pending browser sign-in (#1526) test(sidebar-filters): start the focus journey on General (#1555) Add opt-in native MCP for macOS tests (#1528) Show unreads for channels after access changes (#1550) Deliver artifact changes through shared live routes (#1480) condense photo and video attachments into a compact grid (#1549) Add page-owned sidebar contributions (#844) fix(channels): confirm a requested member when the relay stores bot (#1519) test(browser): settle dialog motion and startup errors before strict checks (#1492) perf(messages): measure read-tracking rows once per frame (#1527) fix(settings): keep the chosen plugin row in place when details open or close (#1551) ...
joelrobotham
pushed a commit
to joelrobotham/buzz-app
that referenced
this pull request
Oct 24, 2026
…ocus * origin/main: (35 commits) fix(goose): say a provider isn't set up instead of offering placeholder models (block#1543) fix(agent-activity): note under a message when its agent was stopped (block#1544) feat(messages): show whose agent wrote a message (block#1502) feat(agents): put main agent choice in the card's actions menu (block#1530) fix(relay): let live dev connections save config artifacts (block#1583) feat(builderlab): let local agents create, deploy, share and open Builderlab apps (block#1340) Unify chat and channel access, tidy the Solo chat menu (block#1446) fix(todos): render nested TODOs with collapsible hierarchy and Markdown (block#1483) fix(agents): Allow agents to propose updates to agents (block#1478) fix(composer): prevent plugins from updating the recipient on a WIP draft message (block#1497) fix(agents): can't delete an agent belonging to an archived channel (block#1560) Bump tokio to 1.53.3 for RUSTSEC-2026-0386 (block#1581) Unify attachment cards with neutral icon tiles (block#1548) Polish edit context, channel join and profile actions (block#1545) fix(claude-code): keep context across channel threads (block#1516) fix(builderlab): let Create agent cancel a pending browser sign-in (block#1526) test(sidebar-filters): start the focus journey on General (block#1555) Add opt-in native MCP for macOS tests (block#1528) Show unreads for channels after access changes (block#1550) Deliver artifact changes through shared live routes (block#1480) ... Signed-off-by: user-kWN3CIVowEvEo3RM <joelrobotham+bbprod@gmail.com> # Conflicts: # tests/browser/github-body.spec.mjs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Deleting a local agent that is still a member of any archived channel never finishes. Every attempt ends with "Switchboard isn't deleted yet and may still be in some channels. It stays stopped; Delete it again to finish."
Delete removes the agent from every channel whose relay roster lists it, then requires a fresh roster read to confirm it is gone. The relay refuses membership changes in an archived channel (
OK false "invalid: channel is archived"), so the archived roster keeps listing the agent and the confirmation can never succeed. On John's production account, Switchboard was a member of 14 channels, all archived Solo chats he owns.Solution
Collect only unarchived channels when removing an agent's memberships:
removeAgentFromChannelspasses the loaded channels that list the agent tomemberChannelsas candidates.memberChannelsadds the relay roster hits, reads their fresh relay-signed 39000 metadata, and drops those witharchived=true. A loaded row that has not yet seen another client's archive is still skipped.An archived channel refuses all writes, so the leftover membership is inert. Delete still archives the identity, hiding it from member lists and mentions even if the channel is later unarchived, and deletes the key, so the agent can never act there. The owner can still remove that roster entry later, since removal is signed by the owner. The alternative, unarchiving, removing and re-archiving each channel during Delete, would change the owner's channels as a side effect of deleting an agent.
Reproduction
Testing
relay-removal.test.ts: one active and one archived channel, in both the relay rosters and the loaded channel list, where the loaded row is stale and does not say archived. Removal publishes 9001 only for the active channel and resolves. Without the fresh metadata check, the relay refuses the archived removal and the test fails. The fixture relay now refuses 9001 in archived channels as the real relay does.buzz-review-completed