Files
amethyst/commons
Claude 4888d30f6c refactor(live-chat): lift NIP-53 live-stream state into commons
Address the architectural critique from self-review. The leaderboard
math and the shared system card are now platform-neutral primitives in
commons, the on-UI-thread aggregation is gone, and two latent
correctness bugs around subscription lifecycle and zap routing are
fixed.

- Introduce a pure LiveActivityTopZappersAggregator in commons that
  takes plain ZapContribution values and returns a sorted, deduped,
  anon-bucketed top-N list. Covered by a unit-test suite that is
  Compose/Android-independent.
- Introduce LiveStreamTopZappersViewModel in commons/commonMain. It
  owns two partitioned contribution maps (stream-scoped and
  goal-scoped), mutates them under a Mutex on the IO dispatcher in
  response to channel.changesFlow and Note.zaps.stateFlow emissions,
  and publishes the aggregator result via a StateFlow<List<TopZapperEntry>>.
  UI is now a dumb consumer with no aggregation logic left in the
  composable.
- Move StreamSystemCard to commons/commonMain/compose/ so Desktop can
  consume it alongside Android.
- Fix attachZapToLiveActivityChannel to run even when a zap receipt was
  already consumed by another subscription. Previously a zap first seen
  by notifications/profile would never reach the stream's channel
  cache; addNote is already idempotent so this is a safe retro-route.
- Fix ChannelFilterAssemblerSubscription to re-invalidate filters when
  a live-activity channel's metadata arrives. The 30311 stream event
  usually lands after the initial assembler run, so the goal-tag-driven
  subscription never fired. Now it re-runs as metadata resolves and the
  goal id is discovered.

https://claude.ai/code/session_01WJA5PvDABegBYUu6h42YZi
2026-04-21 00:20:01 +00:00
..
2026-04-06 09:22:21 -04:00