Skip to content

mobile: consume agent mention acks (kind 44102) - #6578

Open
mfethe1 wants to merge 2 commits into
block:mainfrom
mfethe1:upstream/HW-003
Open

mobile: consume agent mention acks (kind 44102)#6578
mfethe1 wants to merge 2 commits into
block:mainfrom
mfethe1:upstream/HW-003

Conversation

@mfethe1

@mfethe1 mfethe1 commented Aug 22, 2026

Copy link
Copy Markdown

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.agentMentionAck is added to the subscribed channel kinds so acks reach the client, and to channelAuxEventKinds so 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 silent verdict 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

  • Attribution is to the event signer, never the p tag (which carries the mention's author and is forgeable as an identity claim).
  • Only acks whose signer was actually tagged in the mention are applied — the relay is pure fan-out and cannot check agent-ness.
  • Only the local identity's own messages surface an outcome.
  • reason is untrusted: clamped to 200 chars at the parse boundary, rendered as plain Text (no markdown, no link handling).
  • Unknown status is ignored, never coerced to declined.
  • Store is bounded at 512 event ids with oldest-first eviction.

Verification

  • flutter test (full mobile suite): 1758 passing, 14 failing.
  • The same 14 failures occur on untouched upstream main (1647 passing, 14 failing). Failure name sets are identicalcomm -23 ours baseline is empty. No regression. Pre-existing failures live in channel_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.
  • New store test: 19 cases covering signer attribution, untagged-signer rejection, unknown/absent/empty/wrong-case status, reason clamping, idempotent double delivery, accept-outranks-decline, bounded eviction.
  • Widget render verified via an ephemeral golden capture of both accepted and declined states (indicator found, non-blank raster). The capture harness was not committed.

Not verified

  • No emulator/simulator run and no live relay test. No real 44102 event from a real agent was observed end to end; acks are synthesized in tests from the publisher's tag shape.
  • No performance profiling of the 512-entry bound.

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.

Michael Feth 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>
@mfethe1
mfethe1 requested a review from a team as a code owner August 22, 2026 20:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant