Paired user's rejected action in a not-connected shared channel gets the pairing notice copy instead of channel-not-connected copy
Symptom
A paired user acting in a shared channel whose channel is not connected for the installation receives the manifest's connect_required notice — copy written for the unpaired-actor case ("connect your account in the IronClaw web app…") — rather than messaging that says the channel isn't connected.
Cause
Two distinct conditions share one rejection kind. shared_conversation_not_connected_error() (crates/product/ironclaw_assistant/src/conversation_binding.rs) returns ProductOperationFailure::BindingRequired, the same variant the unpaired-actor path returns. Downstream, the run-delivery observer maps Rejected(BindingRequired) to the channel's connect_required nudge, so it cannot distinguish "this user isn't paired" from "this shared channel isn't connected".
This conflation pre-dates #7956 / PR #8054 on the user-message path; PR #8054's observer-predicate widening extends the same (previously silent) behavior to slash commands, which is parity but surfaces the wrong copy in the shared-channel case.
Suggested direction
Split the rejection kinds (e.g. a distinct ChannelNotConnected failure/rejection) or carry a reason discriminant through terminal_ack_for_error → observer, and give the shared-channel case its own notice text (likely a new manifest notice alongside connect_required). Pin both copies at the channel-host e2e tier; the group-channel BotCommand nudge branch currently has no e2e coverage (only the DM branch is pinned).
Found during adversarial review of PR #8054 (fix for #7956).
Generated with Claude Code
Source: nearai/ironclaw