Skip to content

fix(channels): take over a stale conversation-ownership claim from a channel-ineligible holder (#5323)#6132

Merged
houko merged 2 commits into
mainfrom
fix/stale-claim-takeover
Jun 16, 2026
Merged

fix(channels): take over a stale conversation-ownership claim from a channel-ineligible holder (#5323)#6132
houko merged 2 commits into
mainfrom
fix/stale-claim-takeover

Conversation

@houko

@houko houko commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

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.channels allowlist 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_channel is false), treats the dispatch as a takeover (was_mentioned = … || stale_holder) so the eligible candidate re-claims immediately instead of being suppressed.

  • A still-eligible holder keeps its claim unchanged (control asserted in the test).
  • A killed holder still degrades to a graceful send_message error, unchanged — a missing agent's allowlist reads as empty ("all channels"), so it is not treated as stale.
  • The check is a single current_holder read plus one allowlist lookup, only when a different live holder exists.

Verification

  • cargo test -p librefang-channels --lib — 494 passed, incl. the new stale_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_allows is a private free function), so dependent crates are unaffected. No LLM call path touched.

…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.
@github-actions github-actions Bot added size/M 50-249 lines changed area/docs Documentation and guides area/channels Messaging channel adapters and removed size/M 50-249 lines changed labels Jun 16, 2026
…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
houko enabled auto-merge (squash) June 16, 2026 07:20
@github-actions github-actions Bot added the size/M 50-249 lines changed label Jun 16, 2026

@houko houko left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

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

Labels

area/channels Messaging channel adapters area/docs Documentation and guides size/M 50-249 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants