GES — Review & EARS Requirements
Companion to git-event-store-spec.md (v0.21.0). The gap and edge-case review, formerly Part 1, is the page GES — Gap & edge-case review. Part 2 restates the spec’s obligations as EARS requirements per section, so Claude Code can check each mechanically.
EARS patterns used (Mavin, https://alistairmavin.com/ears/): Ubiquitous The <system> shall <response>; State While <precond>, the <system> shall <response>; Event When <trigger>, the <system> shall <response>; Optional Where <feature>, the <system> shall <response>; Unwanted If <trigger>, then the <system> shall <response>; Complex = combinations. Clause order is always While → When → the system → shall.
Part 2 — EARS requirements by section
Section titled “Part 2 — EARS requirements by section”System names: store (the GES event store — the framework-neutral core; a framework binding such as the Emmett adapter is an optional layer over it), exporter, capture subsystem, authoritative remote (default origin; the role held by convention, not a node), writer / appender (a submitting role; calls appendToStream on the local store; multiple permitted), decider (command → events), projection runner, documentation. IDs are stable (E-<section>-<n>); split requirements carry a/b suffixes. Cross-refs point to family sections (resolved per core §0.0) and, where applicable, §16.1 tests. Part 2 below holds the core families; each extension document (core §0.0) carries its own families as a Requirements annex. Part 3 spans the whole family.
Authoring rules applied (EARS review pass). Each requirement was checked for: exactly one system name; the correct pattern (event→When, state→While, feature→Where, fault→If/Then); a single, observable, testable response; ≤3 preconditions; no hidden second requirement in an “and”/“or”; and no implementation leakage. Compound requirements were split. Documentation obligations are phrased as the documentation shall state…. Statements that are design principles rather than runtime-verifiable behaviour were moved to Design invariants (below), following EARS’s own guidance not to force non-behavioural constraints into trigger/response form. The Audit log at the end records every change.
§1 Scope & extensions
Section titled “§1 Scope & extensions”- E-1-1 The documentation shall state which of the non-goals N1–N2 the implementation relaxes, if any. (§1; sequencer designation is E-20-1)
§3 Repository layout
Section titled “§3 Repository layout”- E-3-1 The store shall place every ref under its store segment per the §3.2 layout: the global stream at
refs/ges/<store>/global, each state stream understreams/, each tag index undertags/, each snapshot undersnapshots/. - E-3-2 The store shall not store event streams under
refs/heads/. - E-3-3 Where many streams exist, the store shall resolve a stream tip by direct ref lookup and shall not enumerate the stream namespace. (test 18)
- E-3-4 Where the store is deployed for many streams, the store shall use packed-refs or the reftable backend.
- E-3-5 The store shall not use the
refs/ges/prefix for any purpose beyond the §3.2 layout, the local-only refs of §3.3.1, and the refs a claimed extension defines under the same store segment.
§4 Stream naming
Section titled “§4 Stream naming”- E-4-1 The store shall encode a stream name into a valid ref component using a reversible transform.
- E-4-2 The store shall store the raw stream name inside every event record.
- E-4-3 If a stream name contains characters invalid in a ref component, then the store shall percent-encode them and shall not produce a component that is empty, ends in
.lock, or contains... (round-trip test)
§5 Event storage & granularity
Section titled “§5 Event storage & granularity”- E-5-1 The store shall store each event as one whole record in its own file and shall not store an event as a diff.
- E-5-2 The store shall create exactly one commit per event.
- E-5-3 When appendToStream is called with N>1 events, the store shall build a chain of N one-event commits and make them visible by a single terminal ref compare-and-swap. (test 2)
- E-5-4 If a crash occurs before the terminal ref update, then the store shall leave no event of that append visible and shall leave the stream unchanged. (test 2)
- E-5-5 The store shall not advance the stream ref incrementally across the events of one append.
- E-5-6 The store shall determine event order from commit ancestry and the in-record position, and shall not depend on directory enumeration.
- E-5-7 Where an accumulating file layout is used, the store shall shard files into a prefix-tree and shall keep any single directory below its stated entry bound.
- E-5-8a The store shall treat the ref update (
git update-ref[ --stdin]) as the transactional boundary: an append becomes visible only at the CAS-guarded ref update, never at the writing of a commit object. (§5.5) - E-5-8b When reading, the store should resolve a stream’s tip once and read from that fixed commit, since a concurrent ref update can move the tip mid-read (no per-reader MVCC snapshot). (§5.5.2)
§6 Record format & serialization
Section titled “§6 Record format & serialization”- E-6-1 The store shall serialize each record with the §6.2 schema fields.
- E-6-2 The store shall compute every hash over the RFC 8785 canonical form of the record.
- E-6-3a The store shall store writer metadata inside the record.
- E-6-3b The store shall not treat the commit message as authoritative for any immutable field.
- E-6-4 The store shall store events in a human-readable JSON encoding.
- E-6-5 The store shall not make a binary or schema encoding the default log format. (C20)
- E-6-6 The store shall not pre-compress records destined for the object store.
- E-6-7 Where working-tree materialization is chosen, the documentation shall state its merge and storage consequences.
- (E-6-8 moved to Design invariants — “reason about disk cost from packed size” is authoring guidance, not runtime behaviour.)
§7 Commit model
Section titled “§7 Commit model”- E-7-1 The store shall include
GES-Version,GES-Stream, andGES-Positiontrailers on each commit. - E-7-2 When reading a stream’s current version, the store shall derive it from the tip commit’s
GES-Positiontrailer without opening the tree. - E-7-3 Where linkage is used, the store shall record a resolvable
GES-Linktrailer. - E-7-4 Where signing is enabled, the store shall sign the commit (or its tip/tag) so authorship is verifiable.
§8 Identity & integrity
Section titled “§8 Identity & integrity”- E-8-1 The store shall not add a redundant “hash of previous commit” field duplicating Git’s parent chain.
- E-8-2 When an event id is not supplied, the store shall derive it as
sha256:over the canonical record excludingidandpredecessorHash. - E-8-3 If an event with an already-present derived id is appended at the same position, then the store shall treat the append as a no-op. (test 6)
- E-8-4 Where the integrity chain is enabled, the store shall set each event’s
predecessorHashto the SHA-256 of the prior event’s canonical form, per stream, withnullfor the first. - E-8-5 The store shall use SHA-256 for the application chain and shall not rest integrity claims on SHA-1.
- E-8-6 When verifying integrity, the store shall detect a modified event at the position where the chain breaks. (test 9)
§9 Concurrency & the append condition
Section titled “§9 Concurrency & the append condition”- (E-9-1 moved to Design invariants — mechanism-vs-contract is a design principle, not a runtime-verifiable behaviour.)
- E-9-2 When appending, the store shall advance every affected ref by an atomic compare-and-swap against the tips observed at read time.
- E-9-3a If any affected ref no longer equals the observed tip, then the store shall fail with a distinct concurrency error. (test 3)
- E-9-3b If any affected ref no longer equals the observed tip, then the store shall not apply the append and shall leave every view unchanged. (test 3)
- E-9-4 If the underlying library lacks an atomic conditional multi-ref update, then the store shall perform the transaction via
git update-ref --stdinor an equivalent atomic mechanism. - E-9-5 While an append condition names sequence position 0, the store shall succeed only if no event matches its query. (test 4)
- E-9-6 While an append condition names a non-zero sequence position, the store shall succeed only if no event matching its query exists after that position. (test 5)
- (E-9-7 merged into E-9-3a/E-9-3b — it duplicated the CAS-failure response.)
§10 Core interface & the Emmett binding (DCB core; Emmett = reference adapter over the derived stream view, §10)
Section titled “§10 Core interface & the Emmett binding (DCB core; Emmett = reference adapter over the derived stream view, §10)”- E-10-0a The store shall expose a framework-neutral DCB core —
append(events, condition?)andread(query, options?)plus a fold (§10.0). “append”/“read” are generic event-store verbs, not owned by any framework; Emmett (§10.1) is the reference binding over the derived stream view. - E-10-0b The core shall be the DCB model (§18c), so the DCB terms (query, append condition, sequenced event; sequence position = global stream position) are core terms. The tag record field (§6.2, §18b) is the core query selector; it is not a Git tag and has no Emmett equivalent (in Emmett it is a
data/metadatafield); the store shall not conflate the three. (§10.0, §2.1) - E-10-0c The store’s core conformance (§16.1) shall not depend on any framework binding; Emmett-interface compatibility is an optional profile.
- E-10-0d When events are appended, the store shall update projections subscribed to the affected streams via cursor-based catch-up (§16c). (The notification mechanism — hook, poll, or blocking — is TBD; open design axis, §10.0.)
- E-10-1a When appendToStream is called, the store shall build all objects in memory.
- E-10-1b When appendToStream is called, the store shall not perform a checkout or stash and shall not modify HEAD, the index, or the working tree. (test 8)
- E-10-2 While durability is claimed, the store shall make the appended objects durable before making the ref update durable.
- E-10-3 When readStream is called on a non-existent stream, the store shall return an empty result. (§10.5.2)
- E-10-4 When appendToStream is called with zero events, the store shall perform no commit and no ref move. (§10.5.2)
- E-10-5 While events and evolve are identical, the store shall produce byte-identical aggregateStream results across runs. (test 7)
- E-10-6 The store shall route all Git-object, ref, and filesystem operations through the storage-core interface.
- E-10-7 Where the core invokes Git as a subprocess, the store shall use
execFileorspawnand shall not open a shell. - E-10-8 While on a hot write path, the store shall issue Git operations through a long-lived importer or an in-process library rather than forking one process per event.
- E-10-9 Where a cross-process critical section is not reducible to a single ref update, the store shall guard it with a maintenance lock that has ownership and staleness semantics.
- E-10-10 If a crashed writer leaves a stale ref
*.lock, then the store shall reclaim it after its staleness timeout or fail with a distinct locked error.
§11 Durability
Section titled “§11 Durability”- E-11-1 The store shall state the durability level (L0/L1/L2) in effect. (C10)
- E-11-2 If the store claims L1 or L2, then the store shall configure
core.fsyncto include at leastloose-object,reference. - E-11-3 Where durability is claimed, the store shall not use a write path that reaches only the page cache.
- E-11-4a While at L1, the store shall bound the loss window to its stated
T/N. - E-11-4b While at L1, the store shall not report an append within the current loss window as durably acknowledged.
- E-11-5 The documentation shall state that durable-append throughput is bounded by fsync latency rather than compute.
- E-11-6 When durability is enabled, after a simulated unclean shutdown the store shall retain the stream tip and its objects. (test 15)
§12 Distribution & remotes
Section titled “§12 Distribution & remotes”- E-12-1a The store shall represent per-event replication state as local-only, shared, or incoming via remote-tracking refs.
- E-12-1b The store shall treat remote-tracking refs as point-in-time copies.
- E-12-2 The store shall declare a single-authoritative-remote or multi-master authority model.
- E-12-3 Where a stream requires replicated durability, the store shall make a fast-forward push to the authoritative remote part of the append.
- E-12-4a If two clones append to the same stream from the same tip, then the authoritative remote shall reject the second push as non-fast-forward. (test 12)
- E-12-4b The store shall not auto-merge a divergent single-stream history. (test 12)
- E-12-5 When appends target distinct streams, the store shall merge them by union without conflict. (test 11)
§13 Compaction & retention
Section titled “§13 Compaction & retention”- E-13-1 The store shall distinguish lossless snapshotting from lossy truncation.
- E-13-2 The store shall not truncate on live stream refs except behind a replicated, causally stable horizon.
- E-13-3 When truncating, the store shall re-anchor the retained snapshot to the pre-truncation tip hash.
- E-13-4a Where personal data may be present, the store shall encrypt event data and metadata under a per-subject key held outside the repository.
- E-13-4b The documentation shall state that plaintext already distributed to clones cannot be retroactively deleted.
- E-13-5 The documentation shall state that unbounded streams grow without a retention policy.
- E-13-6 When the loose-object count exceeds its configured threshold, the store shall repack.
- E-13-7 Where per-event signing would dominate storage, the store shall anchor integrity at tips, snapshots, or tags instead of at each event.
§14 Branching (what-if)
Section titled “§14 Branching (what-if)”- E-14-1 The store shall support appending hypothetical events on a throwaway branch and discarding them, without violating append-only on live stream refs. (§14.1)
- E-14-2 The store shall perform counterfactual history rewrites only on clearly-marked throwaway refs that never become canonical. (§14.2)
- E-14-3 The store shall not push what-if branches to live stream refs or the authoritative remote. (§14.3, C14)
- E-14-4 Integration tests should use real historical stream states as fixtures rather than synthetic ones. (§14.4)
(Enforcement mechanism — namespace, GES-WhatIf trailer, hook rejection — deliberately deferred; open design axis, §14.5.)
§15 Security & append-only
Section titled “§15 Security & append-only”- E-15-1 The authoritative remote shall reject any non-fast-forward update or deletion of
refs/ges/<store>/global,refs/ges/<store>/streams/andrefs/ges/<store>/snapshots/refs, except the authorized horizon-truncation operation. (test 13) - E-15-2 Where signing is used, the verifier shall validate each signature against a known-good anchor.
- E-15-3 The documentation shall state that any party with repository read access can read every event on a readable ref.
§18b Tags (core)
Section titled “§18b Tags (core)”- E-18b-1a The store shall store tags authoritatively in the record.
- E-18b-1b The store shall denormalize tags as
GES-Tagtrailers. - E-18b-2a The store shall not treat a trailer as authoritative. (covers R11)
- E-18b-2b When denormalizing event content into a trailer, the store shall sanitize it so that injected trailer-like text cannot be parsed as a trailer. (covers R11)
- E-18b-3 The store shall maintain a tag index that is rebuildable from the records. (§18b.3)
- E-18b-4 The store shall tag every event with the identity of its state stream, so that the derived stream view is expressible as a query. (§18b.4)
§18c Dynamic Consistency Boundaries (core)
Section titled “§18c Dynamic Consistency Boundaries (core)”- E-18c-1 When an append carries a condition, the store shall evaluate that condition against the global stream after the sequence position the condition names.
- E-18c-2a When a conditional append is performed, the store shall evaluate the condition and advance every affected ref in a single atomic
git update-ref --stdintransaction. - E-18c-2b If any precondition of that transaction fails, then the store shall abort the whole append.
- E-18c-3 The store shall treat a consistency boundary as globally enforced only at the authoritative remote.
- E-18c-4 The documentation shall state the window during which an offline append under a boundary is not yet globally validated.
- E-18c-5 The store shall enforce a conjunctive query exactly, and shall not reject an append that matches only part of that query.
§19 Spec evolution
Section titled “§19 Spec evolution”- E-19-1 When a breaking format change is made, the specification shall increment the format version (
gesVersion/GES-Version) and define a migration. (§19.1)
§20 The global stream (core, C22) (dual-view, single authoritative remote)
Section titled “§20 The global stream (core, C22) (dual-view, single authoritative remote)”- E-20-1 Where more than one repository participates, the store shall designate one authoritative remote as the global-stream sequencer. (§20.5, C22)
- E-20-2 The store shall assign each event’s global stream position as its depth in the global-stream chain. (§20.3.2)
- E-20-3 The store shall make every view of an event (global stream, state stream, tag index) visible in a single atomic ref transaction. (CB-2, test CB-b)
- E-20-4 If the atomic view transaction does not complete, then the store shall leave every view unchanged. (CB-2, test CB-b)
- E-20-5 The store shall treat a local global stream position as provisional and shall expose it as authoritative only after a fast-forward push to the authoritative remote. (CB-3)
- E-20-6 The authoritative remote shall enforce fast-forward-only and append-only on GES refs. (CB-1, §20.5)
- E-20-7 If a push is rejected as non-fast-forward, then the store shall reconcile by
pull --rebaseonto the authoritative remote’s tip and re-push, conflict-free. (CB-4, test CB-a) - E-20-8 The store shall re-sign only the new tip after a rebase and shall not rely on per-event commit signatures. (CB-4, §20.7.2)
- E-20-9 The store shall store each event payload once and reference it from all views. (CB-5, test CB-c)
- E-20-10 The store shall always push the global stream and its event blobs to the authoritative remote; it MAY push state streams and tag indices (shared, verifiable) or keep them local and rebuild them by replay (derived); it shall never push projection cursors or read models. (open design axis — §20.5, not to be over-specified pre-implementation)
- E-20-11 (open design axis) The store shall document whether its state streams are per stream id (short, many refs) or per state type (few, long, filter-needed). Not mandated pending measurement.
- E-20-12 The store shall use
originas the default name of the authoritative remote and shall allow the authoritative-remote role to be reconfigured to another remote. (§20.5.1) - E-20-13 The store shall permit multiple appenders, reconciling them at the authoritative remote rather than by a single-writer rule. (§20.3.1, §20.6)
§21 Alignment with established practice
Section titled “§21 Alignment with established practice”- E-21-1 The documentation shall record each deviation from the cross-store consensus with its substrate- or goal-based justification, in the §21 register. (covers R21)
- E-21-2 When a decision changes its relationship to the consensus, the store’s maintainers shall update the §21 register in the same change.
Design invariants (prose, not runtime-verifiable EARS)
Section titled “Design invariants (prose, not runtime-verifiable EARS)”These are design principles, not trigger/response behaviours; EARS’s own limitations note advises against forcing such constraints into requirement form. State and check them as prose, not as shall requirements.
- DI-1 (was E-9-1) The concurrency guard is the tip commit SHA; the version contract is the derived stream version; the two are never conflated. (§9.1)
- DI-2 (was E-6-8) On-disk cost is reasoned about from packed size, never from the loose-object state. (§6.3.2, §11.6)
Audit log — EARS review pass
Section titled “Audit log — EARS review pass”The ears-requirements checklist was applied to every Part 2 block. Changes:
- Two-actor / two-response requirements split into
a/b: E-6-3, E-9-3, E-10-1, E-11-4, E-12-1, E-12-4, E-16c-3, E-16c-4, E-16d-1, E-16d-4, E-18b-1, E-18b-2, E-18c-2. The clearest defect was E-12-4, which named two systems (authoritative remote and store) in one requirement. - Duplication removed: E-9-7 restated the CAS-failure response of E-9-3 and was merged.
- Vague responses tightened: “support crypto-shredding” → an explicit encryption behaviour (E-13-4a); “detect and handle” a stale lock → reclaim-or-fail (E-10-10); “pack proactively” → a threshold-triggered repack (E-13-6); “honor concurrency and idempotency” → two concrete behaviours (E-16d-4).
- Wrong pattern keywords fixed: “Given identical events…” (Gherkin, not EARS) → “While … identical” (E-10-5); “While the store targets many streams” → “Where the store is deployed for many streams” (E-3-4, a deployment variant, not a runtime state).
- Embedded If/Then unpacked from a When requirement: E-18c-2 → E-18c-2a (When) + E-18c-2b (If/Then).
- Non-behavioural statements moved out of EARS into Design invariants: E-9-1, E-6-8.
- Documentation obligations reworded as the documentation shall state…: E-6-7, E-11-5, E-13-4b, E-13-5, E-15-3, E-16b-3, E-18c-4.
- Unchanged (already conformant): §4, §5, §7, §8, §3.4, and the E-NEW items.
Suggested requirements to add (from Part 1, not yet in spec)
Section titled “Suggested requirements to add (from Part 1, not yet in spec)”These have no spec section yet; add the section, then the EARS requirement.
- E-NEW-upcasting When readStream encounters an event whose payload schema version precedes the current one, the store shall apply the registered upcaster before returning it. (R2)
- E-NEW-vectors The store shall reproduce the published interop test vectors for canonicalization, id derivation, and integrity-chain hashing. (R3)
- E-NEW-snapshot-logic If a snapshot’s logic version differs from the current evolve, then the store shall ignore the snapshot and replay from an earlier point. (R5)
- E-NEW-timestamp The store shall order events by position and ancestry and shall not order by record timestamp. (R8)
- E-NEW-profiles The store shall declare which conformance profile it satisfies (Core is required and framework-neutral; Distributed, Agent-capture, DCB, and Emmett-binding are optional add-ons). (R16)
Part 3 — Traceability matrix (requirement ↔ verifier ↔ conformance clause)
Section titled “Part 3 — Traceability matrix (requirement ↔ verifier ↔ conformance clause)”Every EARS requirement maps to how it is verified, keeping the catalog, the spec’s §16.1 tests, and the §16 MUST-list (C-items) in sync. Re-run this mapping whenever any of the three changes; a requirement with no verifier is a coverage gap.
Verifier legend: T# = §16.1 runtime test · RC# = §16.2 review check · Review = inspection/code-review, no dedicated test yet · GAP = no verifier; add one.
| EARS | Verified by | C-item | Notes |
|---|---|---|---|
| E-3-1 | T1, Review | C1 | every ref under its store segment, per the §3.2 layout |
| E-3-2 | Review | C1 | not under refs/heads/ |
| E-3-3 | T18 | C16 | direct tip resolution |
| E-3-4 | Review | — | deployment variant (packed-refs/reftable) |
| E-3-5 | Review | C1 | no refs/ges/ use beyond §3.2, §3.3.1 and claimed extensions |
| E-4-1 · E-4-2 · E-4-3 | T24 | C2 | ref-encoding round-trip + raw name in record |
| E-5-1 | T1, Review | C3 | whole record, not a diff |
| E-5-2 · E-5-3 · E-5-4 · E-5-5 | T2 | C3 | one-commit-per-event, atomic multi-event, crash-before-ref |
| E-5-6 | T1, T17 | C3 | order from ancestry + position |
| E-5-7 | Review | C17 | prefix-tree only if accumulating layout used |
| E-5-8a | T2 | C3 | ref update = transactional boundary (atomicity) |
| E-5-8b | Review | — | read from a fixed tip (no MVCC); testable via mid-read ref move |
| E-6-1 | T1 | C4 | schema fields present |
| E-6-2 | T25 | C4 | JCS bytes |
| E-6-3a | T1 | C4 | writer metadata in record |
| E-6-3b | Review | C4 | commit message not authoritative |
| E-6-4 | T17, Review | C20 | readable JSON |
| E-6-5 | Review | C20 | no binary default |
| E-6-6 | Review | — | no pre-compression |
| E-6-7 | RC-3 | — | documentation obligation |
| E-7-1 · E-7-2 | T28 | C5 | trailers + O(1) version read |
| E-7-3 | T20, Review | — | GES-Link (agent-capture) |
| E-7-4 | Review | — | signing optional |
| E-8-1 | Review | C6 | no redundant prev-hash field |
| E-8-2 | T25 | C6 | id derivation |
| E-8-3 | T6 | C6 | idempotency |
| E-8-4 | T9, Review | C6 | predecessor chain set correctly |
| E-8-5 | Review | C6 | SHA-256 for the chain |
| E-8-6 | T9 | C6 | tamper detection |
| E-9-2 | T3 | C7 | atomic CAS on append |
| E-9-3a · E-9-3b | T3 | C7 | distinct error + no-apply/unchanged |
| E-9-4 | T3, Review | C7 | update-ref fallback |
| E-9-5 | T4 | C7 | STREAM_DOES_NOT_EXIST |
| E-9-6 | T5 | C7 | exact version |
| E-10-0a | T1, T2 | — | DCB core operations (conditional append / query read / fold) |
| E-10-0b | Review | — | DCB terms are core terms; tag notions not conflated |
| E-10-0c | RC-1-adjacent | — | core conformance framework-independent; Emmett binding optional profile |
| E-10-0d | Review | — | append ⇒ subscribed projections updated (mechanism TBD, open design axis) |
| E-10-1a · E-10-1b | T8 | C8 | in-memory build, no checkout |
| E-10-2 | T15 | C10 | durability ordering |
| E-10-3 | T26 | C8 | non-existent stream read |
| E-10-4 | T27 | C8 | zero-event append no-op |
| E-10-5 | T7 | C9 | determinism |
| E-10-6 | RC-5 | — | storage-core seam |
| E-10-7 · E-10-8 · E-10-9 | RC-5 | — | subprocess/fork/lock discipline |
| E-10-10 | Review | — | stale-lock reclaim-or-fail (testable; add if pursued) |
| E-11-1 | RC-1 | C10 | durability level stated |
| E-11-2 | T29 | C10 | fsync config |
| E-11-3 | T15, Review | C10 | not page-cache-only |
| E-11-4a · E-11-4b | T16 | C10 | L1 loss-window bound + no false ack |
| E-11-5 | RC-3 | — | documentation obligation |
| E-11-6 | T15 | C10 | crash survival at L2 |
| E-12-1a · E-12-1b | Review | C11 | three-state status / point-in-time copies |
| E-12-2 | RC-2 | C11 | authority model declared |
| E-12-3 | Review | — | push-as-append (opt-in) |
| E-12-4a · E-12-4b | T12 | C12 | reject second push + no auto-merge |
| E-12-5 | T11 | — | union merge |
| E-13-1 · E-13-2 · E-13-3 | Review | C13 | snapshot vs. truncation + horizon + re-anchor |
| E-13-4a | Review | — | crypto-shredding (if PII) |
| E-13-4b · E-13-5 | RC-3 | — | documentation obligations |
| E-13-6 | T30 | — | threshold repack |
| E-13-7 | Review | — | sign tips not events |
| E-14-1 · E-14-2 · E-14-4 | Review | — | what-if branching obligations (enforcement deferred, §14.5) |
| E-14-3 | Review | C14 | never push what-if branches to live refs / authoritative remote |
| E-15-1 | T13 | C15 | append-only enforcement |
| E-15-2 | Review | — | signature verification |
| E-15-3 | RC-3 | — | documentation obligation |
| E-16b-1 · E-16b-2 | Review | — | scan / read-model routing |
| E-16b-3 | RC-3 | — | documentation obligation |
| E-16c-1 · E-16c-2 · E-16c-3a · E-16c-3b · E-16c-4a · E-16c-4b | Review | — | projection behaviours; add a projection test (idempotent catch-up) — GAP-adjacent |
| E-16d-1a · E-16d-1b | T23 | C21 | ordered self-contained + no checkout |
| E-16d-2 | Review | C21 | streamed not buffered |
| E-16d-3 | T23, Review | C21 | re-inject minimized fields |
| E-16d-4a · E-16d-4b | T23, T6 | C21 | import under CAS + dedup |
| E-18b-1a · E-18b-1b · E-18b-2a · E-18b-2b | Review | — | tags authoritative + denormalized + sanitized |
| E-18b-3 · E-18b-4 | Review | — | tag index rebuildable; state-stream tag present on every event |
| E-18c-1 · E-18c-2a · E-18c-2b · E-18c-5 | T31 | — | condition evaluated on the global stream + atomic multi-ref + abort + exact conjunction |
| E-18c-3 | Review | — | authority-only global enforcement |
| E-18c-4 | RC-3 | — | documentation obligation |
| E-3.4-1 | T19 | C18 | side-effect-free capture |
| E-3.4-2 | T21 | C18 | scoped capture |
| E-3.4-3 | T19, T22 | C19 | ref-name anchor |
| E-3.4-4 | T22 | C19 | worktree-scoped resolve |
| E-3.4-5 | Review | C19 | HEAD-move re-anchor (testable; add if pursued) |
| E-3.4-6 | T20 | C18 | shadow refs local, not pushed |
| E-NEW-upcasting | GAP | — | needs §6.4 + test (R2) |
| E-NEW-vectors | T25 | — | interop vectors (R3) |
| E-NEW-snapshot-logic | GAP | — | needs §13.6 + test (R5) |
| E-NEW-timestamp | Review, GAP | — | order-by-position rule (R8) |
| E-NEW-profiles | RC-1-adjacent | — | declare conformance profile (R16) |
| E-1-1 | RC-3 | — | N1–N2 relaxations documented |
| E-19-1 | Review (process) | — | format-version increment + migration on breaking change |
| DI-1 · DI-2 | RC-4 | — | design invariants, code review |
| E-20-1 | RC-1-adjacent | CB-decl | sequencer designated |
| E-20-2 | Test CB-a | CB-3 | global stream position = chain depth |
| E-20-3 · E-20-4 | Test CB-b | CB-2 | atomic multi-view visibility |
| E-20-5 | Test CB-a | CB-3 | provisional until pushed |
| E-20-6 | Test CB-a, T13 | CB-1 | authoritative remote FF-only + append-only |
| E-20-7 | Test CB-a | CB-4 | pull –rebase reconciliation |
| E-20-8 | Review | CB-4 | re-sign tip only after rebase |
| E-20-9 | Test CB-c | CB-5 | one blob, many views |
| E-20-10 · E-20-11 | Open design axis | — | shared-vs-local / stream granularity — resolve by implementation, not tested |
| E-20-12 | Review | CB-1 | authoritative remote default origin, rebindable |
| E-20-13 | Test CB-a | — | multiple appenders reconciled at the authoritative remote |
| E-21-1 · E-21-2 | RC-3 (register) | — | §21 deviation register kept current |
Coverage summary
Section titled “Coverage summary”- Runtime-tested: 31 core tests (T1–T31) plus 3 the global stream tests (CB-a/b/c), covering append/read/aggregate/concurrency/durability/distribution/export and the optional agent-capture, DCB, and the global stream profiles.
- Review/config checks: RC-1…RC-5 for stated levels, declared models, documentation obligations (incl. the §21 register), design invariants, and the storage-core seam.
- Open design axes (deliberately not specified pre-implementation): shared-vs-local derived refs and state-stream granularity (E-20-10/11, §20.5); CloudEvents envelope (R19) and an EventQL-style query layer (R20); the what-if marking/enforcement mechanism (§14.5); the subscribe notification mechanism (E-10-0d, §10.0). These are decisions for a running implementation, per the §21 register — not gaps to fill on paper.
- Open gaps to close before or during implementation: a projection idempotency test (E-16c-3b, from R4); upcasting and snapshot-logic-version requirements + tests (R2, R5) once §6.4/§13.6 exist; optionally, dedicated tests for tag handling (§18b), HEAD-move re-anchor (E-3.4-5), and stale-lock reclaim (E-10-10) if those profiles are pursued.
- Rule against drift: whenever an EARS requirement, a §16.1/CB test, a §16 C-item, or the §21 register changes, update this matrix and both documents in the same edit. A row with
GAPor a bareReviewfor a MUST-level behaviour is the signal that coverage is missing.
Git Event Store is an independent open specification for an event store that uses Git as its storage component. It is not affiliated with or endorsed by the Git Project or Software Freedom Conservancy. Git and the Git logo are either registered trademarks or trademarks of Software Freedom Conservancy, Inc., corporate home of the Git Project, in the United States and/or other countries.
Git Event Store is not affiliated with or endorsed by Kurrent, the maker of KurrentDB (formerly EventStoreDB). "Event store" is used here as the generic name of the event-sourcing storage pattern.