3946117084
Replace the SharedFlow-based broadcast in LiveEventStore with an inverted index over filter-bearing subscribers. Each REQ registers its filters into a per-store FilterIndex<LiveSubscription>; insert() calls index.candidatesFor(event) and only delivers to candidates whose Filter.match still passes. Cuts the per-event walk from O(N_subs * N_filters) to a few hash lookups plus match() over a small candidate set. FilterIndex itself lives next to Filter.kt (commonMain, KMP-friendly, AtomicReference + COW) so other call sites with the same shape (LocalCache.observables, ObservableEventStore.changes) can reuse it. Each filter contributes entries on its single most-selective dimension (ids > authors > tags > tagsAll > kinds > unindexed) to keep buckets narrow and avoid Set-dedupe work in candidatesFor. The historical-replay race the previous SharedFlow + onSubscription handoff closed is preserved by registering BEFORE replay starts and deduping seen ids until EOSE.