← BlogEngineering

Bi-temporal memory: what was true, and what did the system know?

Northsun · Aug 2026 · 8 min read

A single updated_at timestamp cannot answer both when a claim was true in the world and when a system learned, stored, or corrected it. Bi-temporal records preserve those questions separately. That lets an audit distinguish a late-arriving fact from a later correction and reconstruct prior belief without silently rewriting the past.

One timestamp hides two events

Suppose a policy changed on March 1, but the agent system learned about the change on March 5.

Two questions now have different answers:

  • What policy was valid on March 3?
  • What policy did the system believe on March 3?

If the record has only updated_at = March 5, both questions collapse into one ambiguous timestamp. An audit cannot tell whether the world changed late, the data arrived late, or an earlier value was corrected.

Bi-temporal modeling separates:

  • Valid time: when the claim applies in the world.
  • Transaction time: when the system held that version in its recorded state.

This is an epistemic boundary for agents. A model can act on the best context available at the time and still be wrong in hindsight. An audit should show what the system was given then, not overwrite history with what is known now.

Evolution and correction are different

Consider two changes to the same fact.

Evolution: a customer’s approved shipping address changes on August 15. The old address was correct before that date and the new address afterward. The world changed.

Correction: an address was entered incorrectly on August 10 and corrected on August 12. The earlier value was never valid, but the system did believe it for two days. Knowledge changed.

A single mutable row loses this distinction. An append-and-supersede model preserves it by closing the prior version’s transaction window, inserting a successor, and linking the new row to the one it superseded.

The exact Northsun (formerly Mnemix) substrate scope

Northsun’s D3 decision constrains bi-temporal scope to evidence_refs and locked_facts. It does not make memory_objects bi-temporal.

The governed tables expose a shared range vocabulary through different encodings.

Locked facts

The locked_facts migration stores:

  • valid_range — a PostgreSQL tstzrange for world validity.
  • tx_range — a tstzrange for the recorded version’s transaction lifetime.
  • supersedes_ref_id — the predecessor link.
  • evidence_ref_id — the provenance relation.

The substrate defines procedures for asserting, evolving, correcting, and querying facts as of a time. Evolution and correction close the earlier transaction range and insert a successor rather than mutating the earlier value in place.

Evidence references

The evidence substrate begins with source timestamps and validity scalars such as event_time, ingestion_time, t_valid, and nullable t_invalid, alongside lineage and provenance fields. A following migration adds generated valid_range and tx_range columns.

The source scalars remain authoritative, and the generated ranges cannot drift from them. The two tables do not have identical mutation and constraint semantics; sharing range names does not make them interchangeable.

What an as-of question requires

An as-of audit is not merely “find the latest row before timestamp T.” It needs the relevant tenant, entity and fact key, the applicable valid-time interval, the transaction-time version known at the audit moment, and the evidence supporting that version.

Conceptually, the query asks for both clocks:

SELECT fact_value, evidence_ref_id
FROM locked_facts
WHERE tenant_id = $1
  AND entity_id = $2
  AND fact_key = $3
  AND valid_range @> $world_time
  AND tx_range @> $knowledge_time;

The two timestamps may be equal for a simple replay, but they are conceptually independent. Keeping both visible prevents an audit from quietly answering a different question than the evaluator asked.

What the substrate does not prove

The presence of migrations and procedures does not establish that every public Northsun response exposes bi-temporal facts, that a public facts API exists, or that every agent action can be replayed end to end.

There is no direct facts endpoint in the frozen public REST trio. “Governed recall in production” requires the accepted serving path to attach the correct policy, provenance, and temporal state to the context the customer receives, plus runtime proof that the behavior survives failure cases.

The honest state map is:

  • Substrate: evidence and locked-fact migrations and procedures exist in the repository.
  • Public API: no direct facts/evidence endpoint is part of the frozen caller-memory trio.
  • Direction: governed context serving uses these primitives to make historical belief auditable.
  • Proof gate: deployment and customer-visible serving behavior require separate evidence.

Enterprise evaluators should ask whether the system can represent both clocks, preserve earlier belief after correction, trace evidence to a stable source, enforce tenant boundaries, and demonstrate that customer-visible behavior rather than merely showing an architecture diagram.

Continue with Bi-temporal validity, Evidence references, and Locked facts.