mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-09 08:04:45 +00:00
Milestones 2-3 of quartz/plans/2026-07-03-incremental-negentropy-storage.md. SQLiteEventStore now maintains the LiveNegentropyIndex when the strategy opts in (geode's does by default; [negentropy].live_index = false turns it off; app-side stores are untouched): - Write paths collect a LiveIndexDelta and apply it after COMMIT while still holding the writer mutex — rolled-back savepoint rows never reach the index and updates land in exact commit order (also vs the rebuild, which runs under the same mutex). - Replaceable/addressable overwrites report the row their BEFORE-INSERT trigger displaces via one indexed pre-SELECT that mirrors the trigger predicate (including the NIP-01 lowest-id tie-break and the d_tag-NULL case). - Paths that can't itemize (kind-5, vanish, delete-by-filter/id, expiration sweeps, clearDB) invalidate; the next NEG-OPEN rebuilds from one scan on the writer connection. - Until that first NEG-OPEN populates the index, ingest pays zero bookkeeping — the populated check happens under the writer mutex so it can't race the rebuild. LiveEventStore serves a single unconstrained filter (the relay-relay sync default; relayBench sends exactly this) from the index; everything else keeps the scan+seal path and its single-slot cache. Micro-benchmark at 50k events (LiveNegentropyBenchmark, in-container): scan+seal cold path 80-100 ms; index post-write open 9-16 ms (~5-10x). The relayBench A/B is the acceptance gate and comes next. Correctness: LiveNegentropyIndexStoreTest asserts index content == snapshotIdsForNegentropy scan after every mutation pattern (overwrites, losers, kind-5 rebuilds, filter deletes, mixed-outcome batches, transactions); the full geode suite (NIP-77 + interop sync tests) runs with the index on. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TtDNpayEYvJH7QuPswND3A