Time, Provenance, and Contradiction

por Frank de Alcantara em 23/07/2026

Time, Provenance, and Contradiction

On day 52, Lia tells Aurora that she avoids caffeine at night. On day 90, Aurora uses that restriction while answering an evening request. Five days later, Lia clarifies that the restriction actually began on day 40. The clarification changes the modeled past, but it cannot change what Aurora knew during the day 90 conversation.

A mutable field called created_at cannot represent this situation. If we replace day 52 with day 40, we falsify the audit trail. If we keep day 52, we falsify Lia’s corrected history. If we store both values without naming their meanings, we have preserved two numbers and lost the model.

We need separate clocks. We also need evidence that explains where each version came from, and we need a disciplined response when two sources disagree. Deleting the older claim is tempting because deletion makes the current graph look tidy. It also removes the information required to determine whether the deletion was justified. A suspiciously clean memory is often merely a memory that has misplaced its receipts.

This is the fifth article in the Memory in Graphs series. The Memory Multigraph gave independent identity to claims, sources, episodes, and relation occurrences. We now add complete temporal semantics to those objects. We will define event time, valid time, and transaction time; derive bitemporal queries; represent provenance as a graph; distinguish contradiction from change and qualification; implement a C++23 reference ledger; use two interactive laboratories; and solve 65 exercises.

1. Why one timestamp lies

A timestamp is not meaningful until we state which question it answers. Consider Lia’s correction:

Record Event day Valid from Recorded day
original statement 52 52 52
late clarification 40 40 95

The first row is simple because all three values happen to agree. The second row separates them. The clarification is communicated on day 95, but it describes a restriction that began on day 40. We must not move the communication to day 40, and we must not move the restriction to day 95.

Suppose the database keeps only created_at=95. A historical query for day 50 concludes that no restriction existed. Suppose it keeps only valid_from=40. An audit of the day 90 conversation concludes that Aurora should have known the restriction began on day 40. Both answers are wrong because each uses one clock to answer a question owned by another.

The same error appears in ordinary systems under friendlier names. updated_at may mean when a user edited a form, when a service accepted a request, when a transaction committed, or when a downstream replica observed the change. These instants can coincide, but coincidence is data, not a semantic contract.

Our first rule is therefore strict:

Store a temporal value only after naming the question it answers.

1.1 Solved exercises

Exercise 1.1. Lia reports on day 12 that an appointment occurred on day 9. Which day is event time?

Solution. Day 9. Day 12 is the recording or observation time for the report.

Exercise 1.2. A claim is inserted on day 20 and corrected on day 27. Can created_at=20 answer when the correction became known?

Solution. No. The correction requires its own transaction-time boundary at day 27.

Exercise 1.3. Why is replacing valid_from=52 with valid_from=40 insufficient?

Solution. Replacement loses the interval during which the system believed day 52 was the start. An audit can no longer reconstruct the earlier knowledge state.

Exercise 1.4. Two timestamps have the same numeric value. Are they semantically identical?

Solution. Not necessarily. Event, validity, and transaction time may coincide for one record while retaining different meanings and update rules.

Exercise 1.5. Which defect is more dangerous, a missing timestamp or an unnamed timestamp?

Solution. Both are dangerous, but an unnamed timestamp can be worse because it looks complete and invites confident use in the wrong query.

2. The three clocks of memory

We distinguish three temporal roles.

Event time answers when an interaction or occurrence happened. A message delivery, recommendation, acceptance, and observed outcome each have an event time. An event may be instantaneous at the chosen granularity or may occupy an interval.

Valid time answers when a proposition is taken to hold in the modeled world. “Lia avoids caffeine at night” may be valid from day 40 onward even though the message that revealed it arrived later. Valid time belongs to the proposition’s world-facing semantics.

Transaction time answers when a version is present in the memory system. It begins when the store commits the version and ends when a later transaction closes it. Transaction time belongs to the database’s knowledge history and should be assigned by the system, not retroactively edited by application code.

Let a claim version be

\[c=(p,e,I_v,I_t,S,\pi,\sigma),\]

where $p$ is the proposition, $e$ is event time, $I_v$ is the valid-time interval, $I_t$ is the transaction-time interval, $S$ is the set of sources, $\pi$ is the provenance subgraph, and $\sigma$ is lifecycle status.

Event time and valid time are related but not interchangeable. The sentence “Lia started avoiding caffeine on day 40” is an event about a change whose resulting proposition can remain valid on $[40,\infty)$. The starting event is a boundary; the validity interval is a state.

Transaction time is different again. The correction recorded on day 95 creates a version whose transaction interval begins at 95:

\[I_t(c_{\text{corrected}})=[95,\infty).\]

No honest operation may make this version visible at transaction day 90.

2.1 Solved exercises

Exercise 2.1. A policy is effective from day 30, published on day 35, and ingested on day 37. Identify valid and transaction starts.

Solution. Valid time begins on day 30. Transaction time begins on day 37. Day 35 is a publication event time that remains useful provenance.

Exercise 2.2. Is a birthday an event or a valid state?

Solution. The birth is an event. “Lia is 30 years old” is a time-bounded proposition derived from that event and the query date.

Exercise 2.3. Who should assign transaction time?

Solution. The storage system should assign it at commit or ingestion. Allowing a client to backdate transaction time corrupts the audit axis.

Exercise 2.4. Can one claim have several event times?

Solution. A claim may summarize several events, but those events should keep independent identities. The claim then links to an event set or episode rather than pretending that several occurrences are one instant.

Exercise 2.5. Why include status if valid time already ends?

Solution. Status distinguishes expiry, retraction, dispute, and policy suppression. Equal interval shapes can result from different operations with different audit consequences.

3. Half-open intervals and temporal relations

We represent an interval as

\[I=[a,b),\]

which includes $a$ and excludes $b$. SQL:2011 adopts the same closed-open period convention. It gives adjacent versions a clean boundary:

\[[40,92)\cap[92,\infty)=\varnothing.\]

At day 92, only the second interval contains the instant. We avoid the artificial double validity produced by two closed intervals, $[40,92]$ and $[92,\infty)$.

For finite half-open intervals $A=[a_s,a_e)$ and $B=[b_s,b_e)$, overlap exists exactly when

\[a_s<b_e\land b_s<a_e.\]

If $a_e=b_s$, the intervals meet but do not overlap. James Allen’s interval algebra distinguishes relations such as before, meets, overlaps, starts, during, finishes, and equals, together with their inverses. We do not need all thirteen basic relations for every memory query, but we do need to stop treating “near in time” as a substitute for temporal semantics.

An open-ended interval uses a distinguished infinity:

\[[40,\infty).\]

Infinity is not the largest date a library happens to represent. It is a semantic marker. Production storage may encode it with a sentinel timestamp or a nullable end, but the query contract must remain explicit.

Temporal precision also matters. Day-level examples are readable, but a real ingestion service may need microseconds and a total commit order. If two transactions share a wall-clock timestamp, a sequence number or database commit identifier must break the tie.

3.1 Solved exercises

Exercise 3.1. Does $[10,20)$ contain day 20?

Solution. No. It contains days from 10 through 19 at day granularity.

Exercise 3.2. Do $[10,20)$ and $[20,30)$ overlap?

Solution. No. They meet at the boundary, but the first interval excludes day 20.

Exercise 3.3. Do $[10,25)$ and $[20,30)$ overlap?

Solution. Yes. Both overlap conditions hold: $10<30$ and $20<25$.

Exercise 3.4. Why not encode infinity as day 9999?

Solution. A large date can become an ordinary valid date, can overflow conversions, and hides intent. An explicit open end preserves the distinction.

Exercise 3.5. Two commits share the same millisecond. What additional value can order them?

Solution. A monotonically increasing commit sequence, transaction identifier, or log offset can supply a total order within the timestamp.

4. The bitemporal plane

Valid time and transaction time form two independent axes. A claim version occupies a rectangle on the bitemporal plane:

\[R(c)=I_v(c)\times I_t(c).\]

The original restriction version occupies

\[R(c_1)=[52,\infty)\times[52,95).\]

The corrected version occupies

\[R(c_2)=[40,\infty)\times[95,\infty).\]

These rectangles encode two histories at once. Before transaction day 95, the system models the restriction as beginning on valid day 52. From transaction day 95 onward, it models the restriction as beginning on valid day 40. The valid boundary moves backward; the transaction boundary moves only forward.

A bitemporal slice at valid instant $v$ and transaction instant $t$ is

\[\mathcal C(v,t)= \{c\mid v\in I_v(c)\land t\in I_t(c)\}.\]

Set $v=50$ and $t=90$. Neither restriction rectangle contains the point, so the memory does not return the restriction. Keep $v=50$ and move $t$ to 96. The corrected rectangle contains the point, so the restriction appears.

Try the two independent axes in the laboratory. Use the first two presets and observe that the modeled day remains 50 while the knowledge day changes.

The laboratory makes an essential distinction visible:

A correction may change our model of the past without changing the past state of our knowledge.

4.1 Solved exercises

Exercise 4.1. Which point asks what the system knew on day 90 about valid day 50?

Solution. The bitemporal point is $(v,t)=(50,90)$.

Exercise 4.2. Is the corrected restriction visible at $(50,96)$?

Solution. Yes. Valid day 50 lies in $[40,\infty)$ and transaction day 96 lies in $[95,\infty)$.

Exercise 4.3. Is the original restriction visible at $(60,96)$?

Solution. No. Its transaction interval ends at day 95, even though valid day 60 lies in its valid interval.

Exercise 4.4. What geometric object represents a version with two interval axes?

Solution. The Cartesian product of the intervals forms a rectangle on the valid-time and transaction-time plane.

Exercise 4.5. Can two versions of one claim occupy disjoint transaction intervals and overlapping valid intervals?

Solution. Yes. That is the normal shape of a correction to valid history.

5. Late arrivals, corrections, and retroactive validity

We distinguish three operations that are often collapsed into “update.”

A late arrival introduces information whose event or valid time precedes its transaction time. It need not correct anything. A newly discovered day 30 message can add an independent episode on day 95.

A correction states that a stored proposition, boundary, identity, or qualifier was wrong. It closes the open transaction interval of the old version and appends a corrected version. The earlier row remains available for audit.

A retraction withdraws support or marks a claim as no longer endorsed. Retraction does not prove the logical negation. “The source retracts $p$” and “the source asserts $\neg p$” are different events.

For the night restriction, the append-only revision is:

\[\begin{aligned} c_{1}:&\ I_v=[52,\infty),\ I_t=[52,95),\\ c_{2}:&\ I_v=[40,\infty),\ I_t=[95,\infty). \end{aligned}\]

The correction transaction performs two writes atomically: it closes $I_t(c_1)$ at 95 and inserts $c_2$ with transaction start 95. If only one write succeeds, the store can expose either two open versions or no open version. Temporal correctness therefore depends on ordinary transaction atomicity.

Retroactive validity also requires authorization. A user may correct her own preference. An extractor may correct a parse after a model upgrade. A downstream summarizer should not backdate a medical restriction merely because a generated sentence sounds plausible.

Idempotency remains separate. Replaying the correction event must not create $c_3,c_4,\ldots$ with identical payload and provenance. An occurrence identifier or ingestion key detects retries without collapsing independent corroboration.

5.1 Solved exercises

Exercise 5.1. A day 30 message is first discovered on day 80 and adds a new event. Is it necessarily a correction?

Solution. No. It is a late arrival. It becomes a correction only if it changes a previously stored assertion or boundary.

Exercise 5.2. Does retracting “Lia avoids caffeine” assert “Lia consumes caffeine”?

Solution. No. Retraction removes endorsement. Negation introduces a separate proposition and requires its own evidence.

Exercise 5.3. Why close and insert in one transaction?

Solution. Atomicity prevents gaps or multiple open transaction-time versions for the same revision chain.

Exercise 5.4. What should happen when the same correction event is retried?

Solution. The idempotency key should return the existing result or perform no additional write.

Exercise 5.5. May an extractor backdate valid time without recording its own version?

Solution. No. The extraction activity, model version, source, and transaction boundary must remain auditable.

6. Provenance as a derivation graph

Time tells us when a version applies and when it became known. Provenance tells us why it exists.

The W3C PROV model begins with three classes. An Entity is something with identifiable fixed aspects. An Activity acts on entities over time. An Agent bears responsibility for an activity or entity. These distinctions map naturally to memory:

Memory object PROV role
immutable message Entity
extraction run Activity
extracted claim version Entity
user, service, or model operator Agent

Suppose source message $m_{52}$ produces claim version $c_1$ through extraction activity $a_7$. The graph records:

\[a_7\ \texttt{USED}\ m_{52}, \qquad a_7\ \texttt{GENERATED}\ c_1, \qquad c_1\ \texttt{WAS\_DERIVED\_FROM}\ m_{52}.\]

If model build $g_3$ performed the extraction, we also record:

\[a_7\ \texttt{WAS\_ASSOCIATED\_WITH}\ g_3.\]

The exact edge vocabulary may specialize PROV-O, but the separation must survive. A source is not an activity. An activity is not the claim it generates. A model identifier is not the human author of the source.

For a derived claim $c$, let $\operatorname{anc}(c)$ be the provenance ancestors reachable through approved derivation edges. An auditable claim requires at least one terminal source:

\[\exists s\in\operatorname{anc}(c): \operatorname{type}(s)=\texttt{Source}.\]

This condition is necessary, not sufficient. A path can exist and still point to an irrelevant source. Provenance supplies traceability; semantic verification checks whether the source supports the proposition.

6.1 Solved exercises

Exercise 6.1. Is an extractor run an Entity or an Activity?

Solution. It is an Activity. Its configuration and model build may be Entities used by that activity.

Exercise 6.2. Why keep the original message immutable?

Solution. Later claims, corrections, audits, and extractor reruns need a stable source whose content has not been rewritten.

Exercise 6.3. A claim has a source edge. Is it therefore true?

Solution. No. The source may be mistaken, misread, unauthorized, or irrelevant. Provenance explains origin, not truth.

Exercise 6.4. What edge supports reprocessing after an extractor upgrade?

Solution. A derivation path from claim version to extraction activity, model version, and immutable source identifies which outputs require recomputation.

Exercise 6.5. Why model the operator or user as an Agent?

Solution. Responsibility, authority, consent, and delegation concern who caused or authorized an activity, not merely which bytes were consumed.

7. Sources, activities, and extractor versions

“Source: conversation” is too vague for a production memory. A source identity should resolve to an immutable object or a content-addressed snapshot. At minimum, we need tenant, channel, author, event identifier, payload hash, and access policy. The extraction activity needs its own time, model identifier, prompt or rule version, parser version, and configuration.

These records prevent several false equivalences. Two claims extracted from the same message are not independent evidence. The same message processed by two models supplies two derivations, not two independent observations. Two messages copied from one upstream document may look independent while sharing one origin.

Let $\operatorname{root}(s)$ return the ultimate source family of evidence item $s$. A simple independence check requires distinct roots:

\[\operatorname{root}(s_i)\ne\operatorname{root}(s_j).\]

Even this is only a structural approximation. Two people may repeat the same rumor. Independence is a claim requiring evidence, not a reward for having two identifiers.

Source authority and claim confidence also differ. Authority describes a policy judgment about a source in a domain. Confidence describes uncertainty attached to one extraction or proposition. A highly authoritative source can be parsed with low confidence; a low-authority source can be parsed with near certainty.

We should never multiply these numbers casually. If extractor confidence is $0.9$ and source authority is $0.8$, the product $0.72$ has no calibrated probabilistic meaning unless the model defines and validates that combination.

7.1 Solved exercises

Exercise 7.1. Two extractors process one message. How many independent source observations exist?

Solution. One. There are two extraction activities but one root source observation.

Exercise 7.2. Why store a payload hash?

Solution. It detects source mutation, supports content identity, and helps distinguish retries from new observations.

Exercise 7.3. Can source authority replace provenance?

Solution. No. An authority score without an addressable source cannot be audited or recomputed.

Exercise 7.4. Is $0.9\times0.8=0.72$ a valid combined probability?

Solution. The arithmetic is correct, but the interpretation is unjustified without a calibrated probabilistic model and suitable independence assumptions.

Exercise 7.5. Which metadata identifies a model upgrade?

Solution. The model or extractor version attached to the generation activity identifies which claim versions came from each build.

8. When two claims become contradiction candidates

Textual opposition is not enough to establish contradiction. Before comparing polarity, we align:

  1. subject identity;
  2. predicate meaning;
  3. object identity or value domain;
  4. contextual scope;
  5. modality;
  6. valid-time overlap;
  7. polarity.

Let the proposition signature be

\[\operatorname{sig}(c)= (\operatorname{subj}(c),\operatorname{pred}(c), \operatorname{obj}(c),\operatorname{ctx}(c), \operatorname{modal}(c)).\]

Claims $c_i$ and $c_j$ become contradiction candidates when

\[\operatorname{sig}(c_i)=\operatorname{sig}(c_j), \qquad I_v(c_i)\cap I_v(c_j)\ne\varnothing, \qquad \operatorname{pol}(c_i)\ne\operatorname{pol}(c_j).\]

The equality symbol hides ontology work. “Tea” and “green tea” may denote a broad class and a subclass. “Avoids caffeine” and “does not drink coffee” are related but not logical negations because tea, soda, and medication may contain caffeine. An embedding can propose candidates; it cannot prove proposition identity.

The canonical example exposes contextual scope. “Lia avoids caffeine at night” and “Lia drinks coffee in the morning” are compatible. Removing the qualifiers creates a false conflict. The graph should preserve context as queryable structure rather than burying it in an opaque sentence.

Use the second laboratory to change predicate, polarity, context, validity, and source authority. Notice that authority changes the resolution policy but not the alignment test.

Contradiction detection should return a candidate plus the failed or satisfied conditions. A naked Boolean cannot explain whether the blocker was context, time, ontology, or polarity.

8.1 Solved exercises

Exercise 8.1. “Lia drinks coffee in the morning” contradicts “Lia avoids caffeine at night.” True or false?

Solution. False. The contexts are disjoint under the modeled daily scopes.

Exercise 8.2. Two opposite claims have disjoint valid intervals. Are they simultaneously contradictory?

Solution. No. They describe change or succession unless another constraint relates the intervals.

Exercise 8.3. Can cosine similarity prove that two predicates are equivalent?

Solution. No. It can propose semantic candidates. Equivalence requires ontology, rules, or reviewed mappings.

Exercise 8.4. Why align modality?

Solution. “Lia must avoid caffeine” expresses an obligation; “Lia avoids caffeine” describes behavior. They can differ without logical contradiction.

Exercise 8.5. Does a high-authority source make two claims contradictory?

Solution. No. Authority affects resolution after incompatibility is established. It does not define proposition identity.

9. Contradiction, qualification, specialization, and supersession

One generic RELATED_TO edge cannot describe how claims interact. We need at least these relations:

Relation Meaning
EQUIVALENT_TO same proposition under aligned scope
SPECIALIZES one proposition narrows a broader one
QUALIFIES added context limits how a proposition applies
CONTRADICTS propositions cannot both hold under aligned scope
SUPERSEDES policy selects one version as an operational successor
RETRACTS a source or activity withdraws endorsement

CONTRADICTS is epistemic. It records incompatibility between propositions or evidence-supported claims. SUPERSEDES is operational. It records a version-management decision. Neither implies the other.

Two sources can remain in unresolved contradiction, so neither supersedes the other. A spelling correction can supersede an earlier version without contradicting its meaning. A narrower claim can specialize a broad claim without invalidating it. A later time interval can succeed an earlier interval without overlapping it.

This separation protects history from premature resolution. If a resolver chooses $c_2$ over $c_1$, the graph adds:

\[c_2\xrightarrow{\texttt{SUPERSEDES}}c_1\]

and links the decision to its policy, evidence, activity, and responsible agent. It does not erase $c_1$ or rewrite its source.

Direction must be documented. In this series, the newer operational version points to the version it supersedes.

9.1 Solved exercises

Exercise 9.1. Does CONTRADICTS imply SUPERSEDES?

Solution. No. A conflict can remain unresolved while both claims stay available.

Exercise 9.2. Does SUPERSEDES imply logical negation?

Solution. No. Formatting, spelling, scope, or provenance corrections can create successor versions with compatible meaning.

Exercise 9.3. “Lia likes tea” and “Lia likes green tea” have which likely relation?

Solution. The second may specialize the first, subject to the intended ontology and quantification.

Exercise 9.4. What does RETRACTS record?

Solution. It records withdrawal of endorsement by a source or activity. It does not automatically assert the opposite proposition.

Exercise 9.5. Why store the resolver activity?

Solution. It explains who applied which policy to which evidence and enables later review or reversal.

10. Resolution policies and current views

The graph stores versions and relations. A current view is a derived projection produced by a named policy. It is not the stored graph itself.

Let $A(q,\tau,t)$ be claims applicable to query $q$, valid instant $\tau$, and transaction instant $t$. A resolver $\rho$ produces:

\[V_{\rho}(q,\tau,t)=\rho(A(q,\tau,t),P),\]

where $P$ contains provenance, authority, permissions, contradiction links, and lifecycle status.

The safest default for unresolved material conflict is preservation. The view returns both claims, labels the dispute, and includes their sources. This may be less convenient for generation, but convenience is not evidence.

Other policies can be legitimate when declared. A direct user correction may outrank an old extractor inference about the user’s preference. A signed policy document may outrank an informal summary. A domain expert may resolve a medical term. A “latest wins” policy can serve low-risk configuration values, but recency alone should not decide identity, safety, or law.

Resolution should satisfy three invariants:

  1. the selected claim remains linked to competing claims;
  2. the decision remains linked to evidence and policy;
  3. changing the policy can recompute the view without rewriting history.

Confidence thresholds do not eliminate this duty. Selecting a claim because $0.91>0.89$ converts two uncertain scores into a categorical choice. Unless calibration and decision loss support that threshold, the extra decimals are decorative certainty.

10.1 Solved exercises

Exercise 10.1. What should the default view do with equal-authority conflicting sources?

Solution. Preserve and expose the dispute unless a domain policy supplies a justified resolution.

Exercise 10.2. When can “latest wins” be reasonable?

Solution. It can be reasonable for explicitly mutable, low-risk settings whose contract defines the latest authorized write as current.

Exercise 10.3. Why keep losing candidates after resolution?

Solution. Audits, policy changes, appeals, and new evidence may require reconstructing or reversing the decision.

Exercise 10.4. Can a resolver mutate valid history?

Solution. It may append a correction or decision with explicit valid and transaction intervals. It should not overwrite earlier transaction history.

Exercise 10.5. What is wrong with choosing $0.91$ over $0.89$ automatically?

Solution. The scores may be uncalibrated, correlated, or unrelated to decision cost. Numeric ordering alone does not justify a categorical truth decision.

11. Current, historical, and audit queries

The two temporal axes produce three common query families.

A current query asks what the latest memory currently treats as valid now:

\[Q_{\text{current}}(q)=\mathcal C_q(n,n),\]

where $n$ is the present instant on both axes.

A historical query asks what the latest memory currently says was valid at past instant $\tau$:

\[Q_{\text{history}}(q,\tau)=\mathcal C_q(\tau,n).\]

An audit query asks what the system knew at transaction instant $t$ about valid instant $\tau$:

\[Q_{\text{audit}}(q,\tau,t)=\mathcal C_q(\tau,t).\]

These are not interchangeable. After the day 95 correction, a historical query for day 50 returns the night restriction. An audit query with $t=90$ does not.

The C++23 reference exposes the distinction directly:

const auto before_correction = memory.as_of(day(50), day(90));
const auto after_correction = memory.as_of(day(50), day(96));

assert(before_correction.size() == 1);
assert(after_correction.size() == 2);

The first argument selects valid time. The second selects transaction time. Naming both arguments prevents a call site from hiding the temporal question inside a generic timestamp.

A production query also constrains tenant, authorization, proposition signature, context, status, and provenance. Suitable indexes may include valid interval, transaction interval, subject-predicate-object signature, source, and adjacency. Indexes accelerate a contract; they do not define it.

11.1 Solved exercises

Exercise 11.1. Which query reconstructs what Aurora knew on day 90 about day 50?

Solution. An audit query with valid day 50 and transaction day 90.

Exercise 11.2. Which query answers what the latest memory now says about day 50?

Solution. A historical query with valid day 50 and the current transaction instant.

Exercise 11.3. Why name both valid_at and known_at in an API?

Solution. The names force the caller to state the temporal semantics and reduce accidental axis substitution.

Exercise 11.4. Does an interval index define valid time?

Solution. No. It accelerates interval predicates. The schema and query contract define what the interval means.

Exercise 11.5. Must an audit query apply today’s resolution policy?

Solution. Not necessarily. A strict audit may need the policy version that was active at transaction time $t$.

12. Schema invariants and the C++23 reference

A bitemporal ledger requires more than two date columns. We enforce these invariants:

  1. every claim, revision, source, activity, and decision has a stable identifier;
  2. every interval satisfies start $<$ end unless the end is open;
  3. transaction intervals in one revision chain do not overlap;
  4. at most one transaction-time version remains open per claim chain;
  5. transaction time never moves backward;
  6. every claim version has at least one valid provenance source;
  7. correction closes and inserts atomically;
  8. contradiction requires aligned proposition, context, overlapping validity, and opposite polarity;
  9. retraction does not create negation implicitly;
  10. tenant and authorization scope remain valid across every provenance and version edge.

The bitemporal_memory.cpp reference is a didactic CPU correctness baseline. HalfOpenInterval centralizes boundary semantics:

[[nodiscard]] constexpr bool contains(const Instant instant) const noexcept {
    return start_ <= instant && (!end_.has_value() || instant < *end_);
}

[[nodiscard]] constexpr bool overlaps(
    const HalfOpenInterval& other) const noexcept {
    const auto this_ends_before_other =
        end_.has_value() && *end_ <= other.start_;
    const auto other_ends_before_this =
        other.end_.has_value() && *other.end_ <= start_;
    return !this_ends_before_other && !other_ends_before_this;
}

The ledger closes the old transaction interval before appending the corrected version:

current->transaction_time =
    DayInterval{current->transaction_time.start(), recorded_at};

auto revised = *current;
revised.revision =
    RevisionId{static_cast<std::uint32_t>(versions_.size())};
revised.valid_time = std::move(corrected_valid_time);
revised.transaction_time = DayInterval{recorded_at};
versions_.push_back(std::move(revised));

Copying the version is deliberate. Subject, predicate, object, context, event time, and status remain unchanged in this operation; valid time, transaction time, revision identity, and provenance can change. A different proposition should create a different claim identity or an explicit successor relation.

The bitemporal query scans contiguous storage:

for (const auto& version : versions_) {
    if (version.status == ClaimStatus::asserted &&
        version.valid_time.contains(valid_at) &&
        version.transaction_time.contains(known_at)) {
        result.push_back(&version);
    }
}

This baseline costs $O(n)$ for a slice over $n$ versions and $O(k^2)$ for contradiction comparison over $k$ returned versions. Production candidate generation indexes proposition signatures and intervals, reducing the pair set before semantic checks.

The verified MSVC build used compiler version 19.51.36248 for x64:

cl.exe /nologo /std:c++latest /EHsc /W4 /permissive- `
  /Zc:__cplusplus memoria_grafos\codigo\bitemporal_memory.cpp

The executable produced:

valid_day=50 known_day=90 claims=1 contradictions=0
valid_day=50 known_day=96 claims=2 contradictions=0
valid_day=90 known_day=90 claims=3 contradictions=0
valid_day=100 known_day=101 claims=4 contradictions=1

12.1 Solved exercises

Exercise 12.1. Why use distinct ClaimId, RevisionId, and SourceId types?

Solution. They prevent accidental interchange and document which identity space an API expects.

Exercise 12.2. Why use std::span for read-only version access?

Solution. It provides a non-owning contiguous view without copying or transferring lifetime responsibility.

Exercise 12.3. Why is the baseline query $O(n)$?

Solution. It scans every stored version and performs two constant-time interval containment tests.

Exercise 12.4. What makes pairwise contradiction comparison $O(k^2)$?

Solution. The nested loops inspect each unordered pair among $k$ visible versions.

Exercise 12.5. Which result proves that the late correction preserved audit history?

Solution. Valid day 50 returns one claim at knowledge day 90 and two claims at knowledge day 96.

13. Storage, evaluation, limits, and the frontier

The abstract model does not require one database engine. A relational implementation can use a version table with valid and transaction periods, foreign keys to sources and activities, and exclusion constraints that prevent overlapping open versions. A property graph can attach interval properties to claim-version vertices and keep provenance edges traversable. An event log can remain the immutable write authority while relational or graph projections serve queries.

The physical choice should follow measured workloads:

Workload Useful support
audit by claim and transaction instant claim and transaction interval index
historical state by proposition signature and valid interval index
provenance explanation derivation adjacency and source index
contradiction candidates signature, context, polarity, and interval index
replay after extractor upgrade immutable log and extractor-version index
governed deletion reverse derivation and tenant-policy traversal

Evaluation must test temporal semantics, not merely retrieval accuracy. A minimum suite includes:

  1. a late correction that changes historical state but not an earlier audit;
  2. adjacent half-open intervals with no double validity at the boundary;
  3. an idempotent retry that creates no extra revision;
  4. a morning claim and night restriction that produce no false contradiction;
  5. opposite claims with aligned context and time that remain visible together;
  6. source removal that identifies every dependent claim and cached view;
  7. a policy change that recomputes current views without rewriting history.

The model has limits. Exact event time may be unknown. Natural-language scope may remain ambiguous. Entity resolution can align the wrong Lia. Source authority can encode institutional bias. Provenance graphs can become large. A bitemporal database can preserve every mistake with admirable precision and still fail to identify which source is right.

Current temporal knowledge-graph systems for agent memory, including Graphiti as described in the Zep paper, show that periods of validity and historical relationships improve dynamic memory. Research on temporal knowledge graphs also studies conflict detection through learned or mined constraints. These systems support our direction, but benchmark gains do not settle ontology, authority, consent, or resolution policy.

The next frontier combines interval semantics with uncertain time, source dependence, policy versioning, privacy-preserving provenance, and calibrated resolution. MG06 will address the preceding stage: How Experience Enters Memory. It will define how messages and episodes become candidate entities, claims, outcomes, and write decisions without confusing extraction with truth.

13.1 Solved exercises

Exercise 13.1. Does a system-versioned table automatically provide valid time?

Solution. No. System versioning supplies transaction history. Application-valid periods require a separate semantic axis.

Exercise 13.2. Which test detects an accidental closed interval boundary?

Solution. Query exactly at the shared boundary and verify that only the new interval is valid.

Exercise 13.3. Why test a policy change?

Solution. It verifies that current views are recomputable projections and that stored history was not destructively conformed to one policy.

Exercise 13.4. Can provenance eliminate bias?

Solution. No. It can expose responsible sources and activities, which makes bias inspectable and contestable.

Exercise 13.5. What does bitemporality fail to determine?

Solution. It does not determine truth, source authority, correct entity resolution, consent, or the best contradiction policy.

Conclusion

Agent memory needs more than a timestamp and more than a current value. Event time locates occurrences. Valid time describes when propositions hold in the modeled world. Transaction time preserves when each version entered and left the system’s knowledge.

Together, valid and transaction intervals create a bitemporal plane:

\[\mathcal C(v,t)= \{c\mid v\in I_v(c)\land t\in I_t(c)\}.\]

This single definition separates current, historical, and audit questions. A late correction can change today’s reconstruction of valid day 50 while leaving intact the fact that Aurora did not know the correction on transaction day 90.

Provenance adds the missing explanation. Messages and documents remain immutable entities. Extraction and resolution remain activities. Models, users, and services remain responsible agents. A claim version becomes useful only when the graph can trace how it was generated and which source it represents.

Contradiction then becomes a disciplined candidate relation. We align proposition identity, context, modality, polarity, and valid-time overlap before declaring incompatibility. We preserve competing claims and distinguish CONTRADICTS from SUPERSEDES, QUALIFIES, SPECIALIZES, and RETRACTS.

The central rule is:

Correct the current view by adding accountable history, never by erasing inconvenient history.

The memory multigraph can now represent changing experience without pretending that the agent always knew the latest correction. In the next article, How Experience Enters Memory, we will build the write pipeline that extracts candidate structure from interaction, validates it against this temporal contract, and decides what deserves persistence.

References

  • ALLEN, James F. Maintaining knowledge about temporal intervals. Communications of the ACM, v. 26, n. 11, p. 832–843, 1983. DOI: 10.1145/182.358434. Available at: https://cse.unl.edu/~choueiry/Documents/Allen-CACM1983.pdf. Accessed on: 23 July 2026.
  • CHEN, Jianhao; REN, Junyang; DING, Wentao; OUYANG, Haoyuan; HU, Wei; QU, Yuzhong. Conflict detection for temporal knowledge graphs: a fast constraint mining algorithm and new benchmarks. arXiv, 2025. DOI: 10.48550/arXiv.2312.11053. Available at: https://arxiv.org/abs/2312.11053. Accessed on: 23 July 2026.
  • DOYLE, Jon. A truth maintenance system. Artificial Intelligence, v. 12, n. 3, p. 231–272, 1979. DOI: 10.1016/0004-3702(79)90008-0. Available at: https://www.sciencedirect.com/science/article/pii/0004370279900080. Accessed on: 23 July 2026.
  • KULKARNI, Krishna; MICHELS, Jan-Eike. Temporal features in SQL:2011. SIGMOD Record, v. 41, n. 3, p. 34–43, 2012. Available at: https://sigmodrecord.org/2012/09/30/temporal-features-in-sql2011/. Accessed on: 23 July 2026.
  • LEBO, Timothy; SAHOO, Satya; MCGUINNESS, Deborah. PROV-O: the PROV ontology. W3C Recommendation, 2013. Available at: https://www.w3.org/TR/prov-o/. Accessed on: 23 July 2026.
  • MOREAU, Luc; MISSIER, Paolo. PROV-DM: the PROV data model. W3C Recommendation, 2013. Available at: https://www.w3.org/TR/prov-dm/. Accessed on: 23 July 2026.
  • RASMUSSEN, Preston; PALIYCHUK, Pavlo; BEAUVAIS, Travis; RYAN, Jack; CHALEF, Daniel. Zep: a temporal knowledge graph architecture for agent memory. arXiv, 2025. DOI: 10.48550/arXiv.2501.13956. Available at: https://arxiv.org/abs/2501.13956. Accessed on: 23 July 2026.
  • SNODGRASS, Richard T. Temporal databases. In: The encyclopedia of database systems. New York: Springer, 2009. Available at: https://www2.cs.arizona.edu/~rts/pubs/EDC.pdf. Accessed on: 23 July 2026.

(Updated: )