86537edef5
Splits "events accepted for persistence" from "events accepted for observation". The new ObservableEventStore wraps any IEventStore and owns events: SharedFlow<Event>: - Non-ephemeral events forward to the inner store; success → emit, any rejection (expired, NIP-09 / NIP-62 tombstone, NIP-01 supersession loser) → no emit. - Ephemeral events (kinds 20000-29999) skip persistence entirely but still emit, so an open EventStoreProjection renders them while alive. They vanish from any future seed because the DB never had them. Reverts the previous round of plumbing inside SQLiteEventStore / FsEventStore: stores no longer carry an inserts SharedFlow. IEventStore goes back to a clean read/write contract. ObservableEventStore is the single place that decides what makes it onto the projection bus. EventStore (the SQLite convenience class) embeds an ObservableEventStore internally so existing call sites like `store.observe(filter, scope)` keep working without changes. EventStoreProjection now collects via Flow.onSubscription so the collector subscription is established before the seed query runs — fixes a race where an insert immediately after `ready.await()` could land in the SharedFlow before the collector was subscribed. Tests: - ephemeralEventsAppearInProjection — kind-22000 event reaches items but isn't queryable from the inner store, and a fresh projection on the same store gets an empty seed. - 14/14 projection tests + 219/219 other store tests pass. https://claude.ai/code/session_01Jny85MTu1ynKgFBgysfWu5