Repository navigation
feat(notifications): notify on all activity in chosen channels - #2956
Open
LordMelkor wants to merge 3 commits into
Open
LordMelkor wants to merge 3 commits into
LordMelkor wants to merge 3 commits into
Conversation
Contributor
|
🤖 Design review: this isn't critical path for the Nov 10 launch. Please hold it until after launch, or build it as an external plugin that isn't bundled into the app. Questions: #buzz-design-review. |
Contributor
|
Instructions to get the build to run: buzz://message?channel=5909b3f1-fbe6-4f63-9cd2-06440e58b4a1&id=41538c84fc77a64cc0d124407b31805e3d485d331654a91b5185d62dc9245b05&thread=71a8d710754540d5c562226840389021badb3398752eb76d821d2a5b6c2b16ba |
LordMelkor
force-pushed
the
clod/channel-all-activity
branch
from
November 10, 2026 16:17
a2462aa to
e8550ca
Compare
9 tasks
kazemek21
added a commit
that referenced
this pull request
Nov 10, 2026
## TL;DR Captured explicit reads now check the current saved manual-unread journal inside the replacing transaction, so a newer local choice—including one saved by another window—is not erased. Retries retain their original cut; the additive `unread.prepareThreadRead(channelId, rootId)` captures only retained incoming replies without reading the root or advancing the channel. The fence also preserves earlier same-window queued manual actions, authorizing their revisions only after a successful save whose prior same-key intent is also captured. An earlier queued save cannot mask an intervening unread choice from another window. It leaves reading-lease ownership, passive observations, remote-marker ordering, journal format and relay protocol unchanged. Mark all now reserves one shared saved revision cut before queued writes. Each predicate retains only the revision, not a full journal copy. ### Validation - Shared-cut correction: pinned Linux Blox run of both complete owner files passed 383 tests (174 read-state; 209 unread). The per-sweep capture-budget and capture-failure regressions fail on the prior implementation; older queued-save controls pass. No new browser cases. - Linux Blox, pinned tools: both owner files passed 366 tests on the initial head. After review fixes, `pnpm exec vitest run src/features/relay/unread.test.ts` passed all 206 tests. The final queue-ordering fix passes all 174 tests in `src/features/relay/read-state.test.ts`, typecheck and the commit/push hooks. - Pre-fix channel regressions: six failures; bypassing the new transaction fences makes eleven targeted concurrency regressions fail. Replacing canonical thread selection with parent-edge traversal makes the narrow-thread regression fail. Restoring the implementation passes both owner files. - Three successful-save interleavings fail before the final fix and pass afterward, with three matching controls: channel, thread and message marks overwritten by an older queued save after another window marks unread. - Eight additional regressions fail before the review fixes and pass afterward: root/reply deletion before or after persistence, and shared sidebar hints with absent, present or cross-window forced-message overlays. - Touched-file Biome, `pnpm typecheck`, `pnpm author:build`, strict generated-SDK consumer compilation and repository commit/push hooks. - Deterministic fixture gates cover newer channel/thread/message marks, second-window saves at the transaction boundary, queued ordering, retry cuts, later arrivals, independent root/thread markers and access/lifecycle expiry. No browser tests were added or removed. Generated type-only SDK declarations expose the additive method through the existing `UnreadCapability` export; existing channel and message APIs remain compatible. Capture requires initialized read-state storage. The thread API does not discover history; receipts remain device-local. A narrow read leaves the shared sidebar hint until channel open reconciles it, since that hint has no subtree ownership. Its shared message-force fence is conservative: a newer mark elsewhere in the same channel can also reject the save. This does not establish native runtime behavior, identical remote-tuple ordering or atomicity through an operation's eventual return. Related independent work remains with #2060 (quiet Solo/Inbox), #2610 (selected-message UI), #3181 (passive recovery), and #2939/#1666/#2956 (notification/audience behavior). This change is limited to the explicit mutation/preparation seam. Fixes NEXUS-4426 [Initiative status](https://g2.sqprod.co/apps/kylez-buzz-improvements-status) *Posted by Codex (gpt-6.1-sol) on behalf of kylez.* Signed-off-by: Kyle Zemek <[email protected]> Co-authored-by: Codex <[email protected]>
kazemek21
added a commit
that referenced
this pull request
Nov 12, 2026
## TL;DR This supports retained readers that need to undo an explicit read action without overwriting newer unread intent. It offers Undo only for saved local-unread markers removed by that action. ## How Undo checks the current journal revision inside the storage transaction and revalidates access, visit, and captured-message evidence. It restores only markers removed by that exact saved action. ## Boundary and risk Undo never restores forced-message overlays or rewinds or publishes read frontiers. Results omit Undo if the completed read also cleared forced-message overlays, or if force work was queued while the read saved. The handle expires after any later journal save, even if unrelated or quiet. This whole-journal lifetime is deliberately conservative. Older hosts may omit the optional handle. ## Related PRs This change is independent of [#3264](#3264), [#2918](#2918), [#2939](#2939), [#1666](#1666), and [#2956](#2956). Generated with Codex (gpt-6-luna) on behalf of kylez Signed-off-by: Kyle Zemek <[email protected]> Co-authored-by: Codex (gpt-6-luna) <[email protected]>
A channel's menu, beside Mute, can now set it to notify on every post or reply by someone else; Settings lists those channels to turn off. The new `channel` category applies only when no other category does, mute and thread unfollow still win, and the device-local set is read at delivery. Co-authored-by: Clod <c7b21872e9ddb79ca62967d0e21e6a4518a669eb04648e963cdfb2426e62fafb@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: LordMelkor <[email protected]>
…annel activity A reply's thread read frontier applies only once its root is known. After a window reset, a decided reply whose root was dropped skipped that frontier, so an already-read thread's reply could still count as channel activity. Asking for attention now fetches such a root (after the conversation lookup, which already fetches it for an undecided reply) and holds the alert until it lands. Co-authored-by: Clod <c7b21872e9ddb79ca62967d0e21e6a4518a669eb04648e963cdfb2426e62fafb@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: LordMelkor <[email protected]>
…etched it The conversation lookup already fetches a reply's root. Past the structural cache's 1,024 events, asking for an evicted root again only evicted another, so many threads' lookups never settled. The recovery now runs only for a reply whose lookup did not fetch its root, such as one the window held then. Co-authored-by: Clod <c7b21872e9ddb79ca62967d0e21e6a4518a669eb04648e963cdfb2426e62fafb@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: LordMelkor <[email protected]>
LordMelkor
force-pushed
the
clod/channel-all-activity
branch
from
November 12, 2026 18:09
e8550ca to
ea7d8d2
Compare
This branch has not been deployed
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.
Problem
A channel notifies you only about mentions, DMs and replies in your own conversations. There's no way to follow a channel closely: an ordinary post in a channel you're in gets no notification category and never alerts. The only per-channel control is Mute.
Change
channelcategory. Stop notifying for all activity goes back to the default. Other channels keep the default.activityUnread: likeunread, but a reply outside your conversations counts, except in a thread you unfollowed. It decides only whether an all-activity alert is still worth showing. No count, badge or Inbox item changes.notify-channelsview state). It's read again at delivery, so turning a channel off cancels an alert that's still waiting.messages.tsmoves its existing per-message checks into one shared classify helper, so the new rule sits beside the others. Most of that file's diff is re-indentation.docs/notifications.md,docs/unread.mdanddocs/buzz-help.md.No FOUNDATION file is changed.
Intent
Original request: kray's #buzz-feedback post (Nov 2): "Would be great to be able to customize notifications: eg. channel activity vs mentions, posts by certain people". This PR is the "channel activity vs mentions" half. "Posts by certain people" is #2939.
Validation
messages.channel-activity.test.ts:NotificationSettings.test.tsx: the list shows channels by name, turns one off, and reports a failed save.ChannelInventory.test.tsx: the menu item turns all activity on and off beside Mute, and reports a failed save.tsc --noEmitandbiome checkpass. Full suite ata2462aaa, on main41e64bf0: 19,436 passed and 3 failed, in 3 files this diff doesn't touch (browser-host/vite-config,App.profile,codex-sh). Run alone, those files pass 65/65, so the failures are timeouts on a heavily loaded shared machine.sq agents reviewand Sigil): sq found three P2s and Sigil two, one of them the same. All are fixed.sq agents reviewata2462aaa, after rebasing onto main41e64bf0: no findings.sq agents review) at2a40a34e, after squashing and rebasing onto mainb1436b09: two P2s, both fixed ine8550cae. Each has a test that fails without its fix. Production change: +14/−9.Full suite at
e8550cae: 20,531 passed, 0 failed.f10e7771, squashed to one feature commit (ad1abee1). Main's new sound-fallback test now includes this PR'schannelsound.sq agents review): one P2, fixed in09c0c206(+11/−3 production lines). The window can evict a nested reply's thread root, and the finished lookup was never repeated. The reply then had no root, so it counted as channel activity even in a thread already read.attention()now recovers the evicted root through the existing structural lookup before deciding. Unread counts and badges are unchanged. The new test fails without the fix.sq agents reviewat09c0c206: one P2 in this PR's older delivery code, which the fix doesn't change. Per the review stop rule it's recorded as a known limitation, not fixed here:messages.ts:260, "Resolve viewed replies before choosing channel activity". Ordinary activity waits only on a running lookup, not on an unknown conversation status. So with Notify while viewing on, a reply in a viewed thread can alert as channel activity before its thread category is known.09c0c206: 21,251 passed and 25 failed, in 7 files.InboxPage,WorkflowLanding,MessageReactionsandstore-system-discovery.browser-host/vite-configbuilds Vite, isn't touched here, and times out at 30 s even when run alone under that load.unread-followsandunread-startup, were a real regression from09c0c206.ea7d8d22(+10/−1 production lines). Per the stop rule it gets one fix and no new review round.src/features/relay/unread*andsrc/features/notificationsfiles pass (20 files, 561 tests), including both regressed tests and the new one.f219e18c, nowa2462aaaafter a clean rebase) both probes pass. It checked missing-parent delivery, cancelling a waiting alert on unfollow, turn-off and mute precedence, and the Settings failure message, and found nothing else. 552 tests, TypeScript and Biome pass. Native notification delivery wasn't exercised.Try it (AGENTS.md step 3, for a human)
🤖 Generated with Claude Code