mobile: consume agent mention acks (kind 44102) - #6578
Open
mfethe1 wants to merge 2 commits into
Open
Conversation
added 2 commits
August 22, 2026 15:54
Agents publish NIP-MR mention acknowledgements (kind:44102) when they accept or decline a mention, and desktop consumes them into an accepted/declined state machine. Mobile had zero references to 44102, so a phone user who @-mentioned an agent could not tell a decline from a delay. Add EventKind.agentMentionAck, include it in the subscribed channel kinds so acks reach the client, and add it to channelAuxEventKinds so it overlays rather than rendering as a timeline row. Route acks in the live handler ahead of the channel-visibility and unread work, mirroring desktop's ordering, so an ack never bumps a badge, reorders channels, or alters the last-message preview. Deliberate scope cut versus desktop: no `silent` verdict and no client-side timer. Mobile suspends and disconnects often, so a pending timer would fire false "nobody picked this up" verdicts after resume. Only received facts are stored, so a dropped ack degrades to "no answer yet", never to a false decline. Outcomes are attributed to the event's signer, never to the `p` tag, and are only applied for signers the mention actually tagged -- the relay is pure fan-out and cannot check agent-ness, so any member can publish a well-formed ack for someone else's message. Unknown status values are ignored rather than coerced into a decline, and the untrusted `reason` is length-clamped. No migration, no schema, no protocol change, and no change to the ACP publisher or to desktop. Signed-off-by: Michael Feth <michael@jira-flow.com>
Render the accepted/declined outcome carried by kind:44102 acks on the sender's own message bubble, completing the mobile acceptance criteria for NIP-MR mention acknowledgements. Nothing renders until an ack has actually arrived, so a message with no ack looks exactly as it did before: no spinner, no placeholder, and no claim that an agent stayed silent. An accept outranks a decline, matching desktop, since a mention that one agent is taking has been answered. The indicator is shown only on messages sent by the local identity -- acks for other people's mentions produce no visible change -- and only for acks whose signer was actually tagged in the mention. The untrusted `reason` is rendered as plain text with no markdown and no link handling. Signed-off-by: Michael Feth <michael@jira-flow.com>
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.
Agents publish NIP-MR mention acknowledgements (kind:44102) when they accept or decline an @-mention. Desktop consumes them; mobile had zero references to 44102, so a phone user could not tell a decline from a delay. This adds mobile consumption.
EventKind.agentMentionAckis added to the subscribed channel kinds so acks reach the client, and tochannelAuxEventKindsso 44102 overlays rather than rendering as a timeline row. Acks are routed in the live handler ahead of the channel-visibility and unread work, mirroring desktop's ordering, so an ack can never bump an unread badge, reorder channels, or change the last-message preview. A new community-scoped in-memory store keys outcomes by mention event id then signer pubkey, making double delivery idempotent by data shape.Deliberate scope cut vs desktop: no
silentverdict and no client timer. Mobile suspends often, so a timer would fire false "nobody picked this up" verdicts after resume. Only received facts are stored, so a dropped ack degrades to "no answer yet" — never to a false decline.No migration, no schema, no protocol change. The ACP publisher and desktop are untouched.
Security invariants
ptag (which carries the mention's author and is forgeable as an identity claim).reasonis untrusted: clamped to 200 chars at the parse boundary, rendered as plainText(no markdown, no link handling).statusis ignored, never coerced to declined.Verification
flutter test(full mobile suite): 1758 passing, 14 failing.comm -23 ours baselineis empty. No regression. Pre-existing failures live inchannel_detail_page_test.dart,channels_page_test.dart,search_page_test.dart,remind_me_later_sheet_test.dart.flutter analyze: 6 issues, unchanged from baseline (4 ×deprecated_member_use, 1 ×valid_regexps, 2 ×unawaited_return_in_try_block) — all pre-existing, none in changed files.cargo test -p buzz-acp --lib pool::tests: 131 passed, 0 failed. Publisher tag shape unchanged.Not verified
Known limitation
An ack landing while its channel is not in the live set is dropped. This is strictly better than today, where every ack is dropped, and it shows as "no answer yet" rather than a false decline.