event-store-semantics

Documents the behavioral contract of Quartz's IEventStore SQLite implementation for parity testing.

1.6k|222|Updated Jan 11, 2023
One-click install
npx skills add https://github.com/vitorpamplona/amethyst --skill event-store-semantics
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: event-store-semantics
Source: https://github.com/vitorpamplona/amethyst/tree/main/.claude/skills/event-store-semantics
Command: npx skills add https://github.com/vitorpamplona/amethyst --skill event-store-semantics

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

Implementing or verifying a Nostr event store that matches Quartz's reference SQLite behavior requires digging through QueryBuilder, MergeQueryExecutor, and dozens of test files to learn the real rules. This Skill turns that archaeology into a lookup by stating every observable behavior as a named, numbered rule (STORE-F/W/D/S/C/N) that parity implementers can cite when annotating divergences.

Core Features & Use Cases

  • Filter semantics reference: Defines since/until inclusivity, tag OR/AND combination, per-filter limits with multi-filter union dedup, ordering tiebreaks, and the merge fast path.
  • Write-path and deletion rules: Specifies replaceable/addressable supersession, NIP-09 deletion, NIP-40 expiration, NIP-62 vanish, NIP-45 counts, and NIP-50 search behavior inside the store.
  • Parity vocabulary: Each rule has a stable id so external engines (Vespa, filesystem store, geode) can annotate exact divergences and review pin bumps against the changelog.
  • Use Case: While building a Vespa-backed event store, you find same-second events returned in a different order than Quartz; you check STORE-F08 and learn the id tiebreak is off by default, so your output is a valid newest-N rather than a bug.

Quick Start

Ask the assistant to explain how the Quartz SQLite event store handles a specific behavior, such as whether since and until filters are inclusive or how NIP-09 deletions block re-inserts.

Frequently Asked Questions about event-store-semantics

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I implement a Nostr event store that matches Quartz behavior?

Treat the SQLite EventStore in nip01Core/store/sqlite as the reference implementation and follow the numbered rules in this contract. Assert parity with the commonTest suites, using FsParityTest as the in-repo pattern for holding a second engine to the same semantics.

Are since and until filters inclusive in Nostr event store queries?

Yes, both are inclusive in the Quartz SQLite store: since compiles to created_at >= and until to created_at <=. An event whose created_at equals both bounds still matches the filter.

How do multiple filters with limits combine in a Nostr REQ query?

Each filter gets its own subquery with its own ORDER BY and LIMIT, then branches are combined with SQL UNION for dedup. There is no global limit, so three filters with limits 10, 20, and 30 can return up to 60 events.

Does the Quartz event store support NIP-01 id prefix matching?

No, ids and authors are exact-match only against the full 64-character hex values. Shorter prefixes are logged as errors by the Filter constructor but still sent, and they simply never match anything.

Why does my event store return same-timestamp events in a different order?

The id ASC tiebreak on equal created_at only applies when useAndIndexIdOnOrderBy is true, which is off in both the client default and geode relay preset. Same-second ordering is otherwise unspecified, so any newest-N result is valid.

What happens when a NIP-09 deletion targets another deletion event?

A kind-5 can delete another kind-5, which removes its tombstone rows and makes previously deleted events re-insertable. This is a documented known quirk; some external implementations deliberately diverge by treating deletion-of-a-deletion as a no-op.