Tiramemsu

What leaves the store intact

Tiramemsu articles · 13 October 2026 · companion to the paper When Is a Temporal Statement Store a Statement Graph?

Every tiramemsu record is (e, s, p, o, a, d, v1, v2): an occurrence id, a triple, a transaction-time lifetime [a, d) and a valid-time interval [v1, v2). The subject or object can be another record's id. Gelling, Fletcher and Schmidt's Statement Graphs, the formal model behind Amazon Neptune's OneGraph, have statement vertices with exactly three outgoing edges: subject, predicate and object. Statement graphs and tiramemsu argued that one record is one statement vertex.

So is the store a Statement Graph? Sometimes. The paper says exactly when, and what an exporter should do in the other cases.

The rule: export, don't invent

An export is identity-preserving when it obeys two rules:

No new occurrences and no renamed ones. Under those rules the first theorem is short: a set of records exports exactly when it is closed and acyclic. Closed means every record it points at is in the set. Acyclic means no chain of references comes back to where it started, because a Statement Graph is a DAG. The export is then unique, and reading its role edges gives back every triple with its id.

A tempting shortcut breaks the first rule. You can turn a dangling reference into a plain IRI leaf and still get a valid graph. But a consumer can no longer tell a reference to a missing occurrence from an ordinary term, so the shortcut is not allowed.

The running example

At transaction 1 we write a route and its distance:

e1 = (:FRA, :route, :LHR)
e2 = (e1, :distance, 655)          # an annotation on e1

At transaction 2 we correct the route's valid time with supersede. The engine retracts e1 and its dependent e2, replays them under fresh ids e1' and e2', and records the lineage ℓ = (e1', sys:supersedes, e1).

A different correction, one whose patched object names the annotation e2, replays into e1' = (:FRA, :route, e2') and e2' = (e1', :distance, 655). Neither record refers to itself, but together they form a two-cycle. Neither the snapshot nor the history can export it whole.

The kernel: the most you can export

When a set is not exportable, the exporter has to drop whole records. It cannot patch endpoints or invent referents. Which records should go? The paper's answer is the export kernel. Start from nothing and repeatedly add every record whose references are all already in. Records that reference nothing go in first, then the records that point only at those, and so on, until nothing changes.

The kernel is the unique greatest closed, acyclic subset, so no other choice exports more. It drops exactly the records that reach a problem: a missing target, or a cycle. Unrelated facts stay. It is Kahn's topological sort, so a peel computes it in linear time and outputs records in an order where every record comes after its targets. That is the order a streaming RDF-star writer needs. In the cyclic example, the history kernel keeps e1, e2 and any unrelated fact. The snapshot kernel keeps only the unrelated fact, because ℓ also dangles there.

The kernel has one weakness: it costs provenance. In the first example it exports {e1', e2'} from the snapshot and silently drops the lineage ℓ. The paper's dual, the reference closure, goes the other way. It keeps every selected record and adds the historical records they point at, marked as retracted. That exports {e1, e1', e2', ℓ} whole. Either way, an exporter should report every omitted record with a reason: missing target x, on a cycle, or depends on omitted y.

Export the history, not the present

A temporal store has a property most graph stores lack: records are immutable and never deleted, and a write may point only at records that already exist. The paper proves that under these rules the full history is always closed. Snapshots can dangle, but history cannot. The only cycles history can contain are the ones a single correction creates inside its own replay batch.

Two practical consequences follow:

Engine status. Tiramemsu does not apply the acyclic-replay rule today. A correction can still create the two-cycle above, and a regression test pins that behaviour. The engine's own invariants (live endpoints, cascade, immutability) hold for such a cycle; export is the first consumer that needs a DAG. Nor is the kernel an engine API yet. The paper recommends the rule for stores that export.

Both clocks, into RDF-star

RDF-star's branch of OneGraph needs one more thing: a statement nothing points at must be asserted by a membership statement (e, in, G). The paper's temporal encoding adds, for each record:

The roundtrip is lossless: decoding returns the same records with all eight fields, and the same asserted set. Asserting only the current snapshot and quoting the rest is a natural choice. A time-unaware RDF-star consumer then sees exactly the snapshot, and the history hangs off it as statements about quoted triples.

Queries come with one condition. A conjunctive query over the asserted part returns the same answers as the store, up to quoting, when no two records share the same triple. That condition is not idle. A valid-time correction creates a new occurrence with the old content, so in RDF-star e1 and e1' quote to the same triple. A join can then merge annotations the store keeps apart.

Where the boundary moves

TargetWhat exportsWhat it costs
Statement Graph / RDF-starThe kernel: closed and acyclic recordsEqual contents merge on quoting
RDF 1.2 reifiersEvery store, cycles and dangling references includedAssertion is per triple, not per occurrence
Property-graph branchOnly edges, labels and properties nothing points atReference depth at most one; both clocks for edges only

RDF 1.2 names an occurrence with a reifier IRI instead of nesting it, so a reference is just a name. Closure and acyclicity become checks for consumers that dereference, not conditions of the format. In exchange, an asserted triple cannot say which occurrence it asserts when two share content, so the asserted set has to come from the clocks.

Evidence and limits

No performance claims are made.

Read the paper

When Is a Temporal Statement Store a Statement Graph? Export Boundaries for Occurrence Records with Two Clocks has every definition, theorem and proof, the encodings, the query view and the comparison with RDF 1.2 and property graphs. It is a draft preprint under CC BY 4.0, archived on Zenodo with its validation archive.

Download the PDF About the paper DOI 10.5281/zenodo.23335652

The series in one page → · ← Previous: cheap to write, careful to read