mirror of
https://github.com/block/buzz.git
synced 2026-11-11 20:01:09 +00:00
Four correctness defects in the 384ebc9d7 merge resolution:
1. [CRITICAL] markChannelRead/markAllChannelsRead bypassed the NIP-RS clear
transition. Both paths deleted forced-unread state unconditionally without
calling applyOverrideRead/applyMarkAllReadTransition. A refused clear left
the authoritative override active while local presentation was wiped.
Fix: advance frontier first, then call applyOverrideRead (C-bump); gate
forcedUnread deletion and observed evidence removal on overrideCleared
outcome. markAllChannelsRead calls applyMarkAllReadTransition per channel
and routes observed deletion through observedPersistence.removeChannel.
2. [IMPORTANT] Sidebar projection used forcedUnreadRef (stale-prone local
cache) instead of getOverrideLiveness (manager-authoritative). A remotely
synced override could fail to light the sidebar.
Fix: derive isForcedUnread from getOverrideLiveness(channel.id)?.active.
3. [IMPORTANT] Observer fallback (no complete projection) decoded fetched
events with mergeReadStateEvents (frontier-only) and set override
authority to an empty map, silently dropping active remote registers.
Fix: use mergeReadStateEventsStructured in the fallback; use
structured.overrides as authority; also check authoritative register in
the channel evaluation loop before falling back to forcedUnreadMap.
4. [IMPORTANT] handleMarkMessageUnread mutated forcedUnreadMsgRef before
calling markChannelUnread, ignoring the boolean result. A refused manager
accept (budget_exhausted, load_incomplete) produced phantom unread state.
Fix: call markChannelUnread first; mutate overlay only on true.
Also adds production-path witnesses:
- adversarial-7 (communityUnreadObserver): active fetched register with no
complete projection lights the rail (positive fallback coverage).
- adversarial-5/6 (nip-rs-unread-ui): refused-clear contract for
markChannelRead gate; spec-order frontier-advance-before-cbump.
- useUnreadChannels.test.mjs: updated markAllChannelsRead happy-path to
reflect NIP-RS-gated semantics (no longer unconditional clearAll).
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Buzz
Desktop chat shell with:
- Tauri + React + TypeScript + Vite
- Tailwind CSS
- shadcn/ui-ready shared components
- Biome (lint/format/check)
- Feature-driven frontend structure
Scripts
pnpm dev- run the web frontendpnpm tauri dev- run the desktop apppnpm build- typecheck and build frontendpnpm typecheck- TypeScript checkspnpm lint- Biome lintpnpm format- Biome format (write)pnpm check- Biome check
Structure
src/shared- reusable app-wide code (ui,lib,styles)src/features- feature modules (vertical slices)src/app- top-level app composition