Skip to content

fix(desktop): emit singular mention feed category so alerts route correctly - #6665

Open
morgmart wants to merge 2 commits into
mainfrom
fix/feed-item-category-contract
Open

fix(desktop): emit singular mention feed category so alerts route correctly#6665
morgmart wants to merge 2 commits into
mainfrom
fix/feed-item-category-contract

Conversation

@morgmart

Copy link
Copy Markdown
Contributor

Problem

Mentions — and thread replies that @-mention you — played the Needs action sound instead of the @Mentions sound. Reported by @morgmart: "I set Needs action to a different sound and it's the only one I ever hear."

Root cause

Two vocabularies got conflated in #475:

  • Section / filter vocabulary (plural): mentions, needs_action, activity, agent_activity — the shape of FeedSections, the --types filter, and the agent-facing CLI docs.
  • Per-item category vocabulary (singular for mention): mention, needs_action, activity, agent_activity — the FeedItemCategory contract in desktop/src/shared/api/types.ts, unchanged since Add desktop Home feed #12.

The Tauri feed builder reused the filter string "mentions" as each mention item's category. Only one word differs between the vocabularies, so only mentions broke. Every frontend consumer compares against the singular, so real mentions never matched and fell through to the resolver's needs_action fallback.

The E2E mock bridge emits the singular form, so tests never saw the drift.

Symptoms this fixes (all from the one mislabel)

  • Mentions and mentioning thread replies played the Needs-action sound
  • Mention notifications used the Needs-action title format
  • Mentions in muted channels were suppressed (the mute-bypass never fired)
  • Inbox / Home feed labelled mentions "Channel update"
  • Channel activity popover's mentions list was always empty

Fix

Fix the owner, not the symptoms. FeedItemInfo.category becomes a FeedItemCategory enum whose serde form is exactly the TS union, so a misspelled category can't compile at the producer. A serialization test pins each variant to its wire string.

Frontend: slotForFeedKind maps every known category explicitly. The needs_action fallback for unknown categories is kept on purpose — a contract drift should cost the user the wrong sound, not a missed alert — but it now console.warns so the drift is visible to developers instead of masquerading as intended behavior. e2eBridge.ts and tauri.ts now derive the category type from types.ts instead of retyping it.

Not touched: the plural --types filter and FeedSections keys. Those are the section vocabulary and are correct as-is.

Verification

  • just ci green (file-size ratchet, Rust/Tauri/desktop/mobile tests, desktop + web builds)
  • New tests: 2 Rust (feed_item_category_serializes_to_frontend_contract, feed_item_from_event_carries_singular_mention_category), 3 TS in sound.test.mjs incl. one that feeds the old "mentions" string and asserts fallback + warning
  • Runtime, dev build against the production relay: controlled test from an agent identity into a test channel —
    • mention in channel → @Mentions sound, inbox shows "Mentioned in" ✅ (was Needs-action)
    • thread reply with mention → @Mentions sound, once ✅ (was Needs-action)
    • plain thread reply in the channel being viewed → silent, as designed ✅

Reviewers

…orrectly

The Tauri home-feed builder stamped mention items with the plural section
name `"mentions"` (reused from the `--types` filter vocabulary) while the
frontend contract — `FeedItemCategory` in `shared/api/types.ts`, unchanged
since #12 — is the singular `"mention"`. Introduced in #475. Every frontend
consumer compared against the singular, so real mentions never matched:

- Mentions (and thread replies that @-mention you) played the Needs-action
  sound via the resolver's fallback instead of the @Mentions sound.
- Mention notifications used the Needs-action title format.
- Mentions in muted channels were suppressed; the mute-bypass never fired.
- Inbox / Home feed labelled mentions "Channel update"; the channel activity
  popover's mentions list was always empty.

The E2E mock bridge emits the singular form, so tests never saw the drift.

Fix the owner rather than the symptoms: `FeedItemInfo.category` becomes a
`FeedItemCategory` enum whose serde form is the exact TS union, so the
compiler rejects a mis-spelled category at the producer. A serialization
test pins each variant to its wire string.

On the frontend, `slotForFeedKind` now maps every known category
explicitly. The needs_action fallback for unknown categories is kept on
purpose — a contract drift should cost the user the wrong sound, not a
missed alert — but it now warns so the drift is visible to developers.
`tauri.ts` and `e2eBridge.ts` import the category union instead of
retyping it.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
@morgmart
morgmart requested a review from a team as a code owner August 24, 2026 01:52
…esolver

The refactor moved the mention check below the job-kind checks, so a
future job event that @-mentions the user would have played its job
sound instead of the Mention sound. Restore the original order and pin
it with a regression test.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
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