Skip to content

Temporal validity intervals on entities + relations (as-of graph queries) #2

Description

@addadi

Pitch

memory_atoms already carries validity columns — valid_from_ms, valid_until_ms, last_verified_at_ms (src/migrations.zig:153-155, mirrored in the Postgres schema at :610-612). entities and relations do not: they only have created_at_ms (entities at :135, relations at :236). This means an atom can be time-scoped, but the entity it references and the edges connecting entities cannot. Graph traversal today can only filter on status (proposed/superseded/...), not on "was this edge true at time T".

I'd like to build this if it's wanted upstream, and open a PR. Filing this first to check direction before writing code.

Proposed design (valid-time only, not full bi-temporal)

  1. Schema — add nullable valid_from_ms + valid_until_ms to entities and relations, in both the SQLite and Postgres schemas, copying the memory_atoms column pattern exactly. New migration; no edits to shipped ones. Semantics: NULL valid_from = since-creation; NULL valid_until = still valid. Transaction time stays created_at_ms (no second time axis).
  2. Query surface — optional as_of_ms parameter on the graph commands (traverse/path/relations), filtering rows to valid_from_ms <= as_of < coalesce(valid_until_ms, inf). Default (no param) = current behavior, zero breakage.
  3. Supersedes interplay (the open design question) — today supersedes is expressed as a relation type + a 'superseded' status. If we add validity intervals, should writing a supersedes edge automatically close the target's valid_until_ms = now? My lean is yes (status + validity should agree), but I want a call from the maintainer before encoding it.

Scope / non-goals

  • Not proposing a Cypher parser or in-process graph algos — graph_projection (FalkorDB/Neo4j) already covers that per the README.
  • Not touching artifacts (it has last_verified_at_ms but a different lifecycle).

Validation plan

  • Migration applies cleanly on SQLite + Postgres; existing DBs upgrade without data loss.
  • traverse with as_of_ms excludes expired relations; without the param, behavior is unchanged (regression tests).
  • `zig build test-local --summary all` green.

Open to feedback on the semantics, the `as_of` naming, and whether `supersedes`-closes-validity should be automatic or explicit. Happy to scope down (e.g. relations-only, skip entities) if that's a better first cut.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions