fix(channels): take over a stale conversation-ownership claim from a channel-ineligible holder (#5323)#6132
Merged
Merged
Conversation
…channel-ineligible holder (#5323) Follow-up to #6127. When agent A holds a conversation-ownership claim and A's manifest.channels allowlist is later narrowed to exclude that channel, the still-live claim suppressed every non-addressed follow-up — routed to an eligible agent B — until the TTL (default 600s) expired, a silent message drop. conversation_ownership_allows now reads the current holder and, when the holder can no longer serve the channel (agent_allows_channel is false), treats the dispatch as a takeover so the eligible candidate re-claims immediately. A still-eligible holder keeps its claim unchanged; a killed holder continues to degrade to a graceful send_message error (its empty allowlist reads as "all channels", so it is not treated as stale). Verified: cargo test -p librefang-channels --lib (494, incl. new stale_holder_loses_claim_when_channel_ineligible with an eligible-holder control), cargo clippy -p librefang-channels --lib -- -D warnings, cargo fmt --check — all clean.
…ment blocks The channels stale-claim bullet's last continuation line had the entire `**memory: Matrix peers…**` entry appended to it (the deleted bullet was never re-added as its own entry), so Closes #6100 was attributed to the wrong section. Restored the memory bullet as a separate entry. Also condensed three multi-line comment blocks in bridge.rs to single lines per CLAUDE.md style rules.
houko
enabled auto-merge (squash)
June 16, 2026 07:20
houko
commented
Jun 16, 2026
houko
left a comment
Contributor
Author
There was a problem hiding this comment.
Two mechanical fixes pushed in a follow-up commit (f9001a7):
CHANGELOG.md — garbled bullet (data loss)
The - **memory: Matrix peers…** bullet (the one landing the #6100 fix) was deleted in the diff, and its text was appended verbatim to the tail of the new channels bullet.
After the fix, Closes #6100 lives under its own - **memory:** entry again and the channels bullet ends cleanly after "…graceful send_message error as before."
bridge.rs — multi-line comment blocks condensed
Three comment blocks exceeded the one-line limit in CLAUDE.md:
- The 7-line block before
stale_holder→ single line. - The 2-line wrap before
was_mentioned→ single line. - The 4-line block at the top of the test function → single line.
No logic changed.
Generated by Claude Code
This was referenced Jun 17, 2026
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.
Summary
Follow-up to #6127 (per-conversation agent routing, #5323), hardening the one minor edge an adversarial review of that PR surfaced.
When agent A holds a conversation-ownership claim and A's
manifest.channelsallowlist is later narrowed to exclude that channel, the still-live claim suppressed every non-addressed follow-up — which now resolves to an eligible agent B — until the TTL (default 600s) expired. The result was a silent message drop for up to 10 minutes after a reconfiguration.(The behavior predates #6127 — the same gate suppressed in this case before — but #6127's sticky-resolution model raised the expectation of continuity, so it is worth closing now while the code is fresh.)
Change
conversation_ownership_allows(crates/librefang-channels/src/bridge.rs) now reads the current holder and, when the holder can no longer serve the channel (agent_allows_channelis false), treats the dispatch as a takeover (was_mentioned = … || stale_holder) so the eligible candidate re-claims immediately instead of being suppressed.send_messageerror, unchanged — a missing agent's allowlist reads as empty ("all channels"), so it is not treated as stale.current_holderread plus one allowlist lookup, only when a different live holder exists.Verification
cargo test -p librefang-channels --lib— 494 passed, incl. the newstale_holder_loses_claim_when_channel_ineligible(asserts both the takeover and the eligible-holder control).cargo clippy -p librefang-channels --lib -- -D warnings— clean.cargo fmt --check— clean.No public API changed (
conversation_ownership_allowsis a private free function), so dependent crates are unaffected. No LLM call path touched.