AI Research Library

Freshness, Supersession and Temporal Entitlement

Rajesh Ranjan Mahapatra

A fact can be accurate, well sourced and still be ineligible to authorise an action because its validity, governing version or delegated authority has changed.

© 2026 Rajesh Ranjan Mahapatra. 29 min read

Freshness, Supersession and Temporal EntitlementAll AI Research Library

TLDR

  1. Freshness is not the age of a record. It is whether a proposition remains valid, authoritative and admissible for this decision at the time consequence occurs.
  2. The mechanism requires two time axes, typed supersession and a decision frame that separates what was true, what was known, what governed and what is permitted now.
  3. Consequential actions should carry evidence, policy, identity and world-state versions into an atomic action-time check, rather than trust a model’s earlier recommendation.
  4. Bitemporal stores and supersession graphs add cost and cannot repair a wrong source, missing history or genuinely disputed validity. Use them where temporal confusion changes outcomes.
  5. Replace “prefer the latest” with a temporal entitlement contract: select the governing claim, record its limits, revalidate authority, and reject execution when any premise changed.

The approval that remained true after it stopped counting

At 10:04:08, a payment screening service marks a corporate payment as a possible match and the orchestration service places a hold. At 10:06, an operations analyst clears the alert. At 10:09, the external feed corrects the candidate record. At 10:12, a relationship manager asks an agent why the payment was held and whether it can now be released.

The agent has excellent retrieval. It can quote the original screening result, the analyst’s clearance, the corrected source record and the applicable procedure. Nothing is fabricated. Yet one fluent answer can still make three incompatible moves: use the correction to imply the workflow should have known more at 10:04; use the old possible-match assertion as if it were current at 10:12; and reuse an approval captured before the operator’s release authority changed.

The central error is easy to miss because every sentence can be literally true. The system did receive a possible match. The analyst did approve release. A newer procedure was published. The problem is that truth alone does not confer present authority. A claim is action-eligible only inside a declared temporal frame and only while the authority that makes it usable still holds.

This is the narrower question behind the broader architecture described in Governed Context Architecture. Reconstruction can fetch a current value. Paper 111 asks the harder control question: when may that value, or an earlier value retained for history, support a consequential action?

One assertion moving through valid time and recorded time A vertical river shows world validity, while horizontal banks show when the bank knew each assertion. The original possible match remains historical evidence after a correction but no longer supports a current release decision. Supersession river Synthetic Harbour Bank timeline world validity institutional knowledge 10:04 possible match valid in then-known view historical support retained 10:09 correction current assessment: not the customer corrects Current action cannot reuse the old claim as present authority
Figure 1. The supersession river preserves history without preserving current authority. Authored synthetic figure. The times belong to the worked scenario; no production measurement is claimed.

The answer at 10:12 therefore needs two ledgers. “As acted” explains that the hold followed the screening result and procedure available at 10:04:08. “Current evidence” says the candidate was later cleared and corrected. A proposed release then needs a third operation, distinct from explanation: a fresh check that the payment state, policy version, operator identity, purpose and delegated authority still permit the effect.

Part I

Why “latest” fails before reasoning begins

Most retrieval systems treat time as a ranking feature. A recently modified page receives a boost; an older page is penalised; the top few passages enter context. That is useful for news search. It is unsafe when the result can authorise an effect. The newest document may be future-effective, the newest database row may correct an earlier period, and the newest approval may have been issued by someone whose authority has since been withdrawn.

Recency orders artefacts. It does not determine applicability. Applicability is a relation among a proposition, a decision, a scope and a time. It asks whether this exact claim governs this exact case at the relevant instant. The same source version can be admissible for a historical explanation, inadmissible for a current recommendation and essential for a counterfactual replay.

Thought experiment 1: the badge that still tells the truth An operator’s signed badge says, “Priya may release payments up to £50,000.” At 09:00 that statement is valid. At 09:02 her role is suspended. At 09:03 an agent presents the signed badge to release a payment. Change only one causal feature, the suspension time. The badge remains authentic and the earlier statement remains historically true, but it no longer carries authority at effect time.

A signature answers who attested to bytes. A timestamp answers when some event was recorded. Neither alone answers whether a permission still governs. OAuth token introspection exists for a related reason: a protected resource can ask an authorisation server whether a token is currently active, including whether it has expired or been revoked.8 The OpenID Continuous Access Evaluation Profile goes further by standardising events that can attenuate access after a session begins.9 These mechanisms do not supply a complete decision model, but they expose the key principle: past issuance is not present entitlement.

The clocks hidden inside one “updated at” field

Temporal database research separates valid time, when a fact holds in the represented world, from transaction time, when the database stored that fact. A system supporting both is bitemporal.1 For consequential agents, two further clocks usually matter: decision time, when a recommendation or control was formed, and effect time, when the external state change commits. Publication and observation times often deserve their own fields as well.

These clocks can coincide, which is why weak designs survive simple tests. A payment event may be observed, recorded and acted on within milliseconds. The failure appears when one clock moves independently: a correction arrives late, a policy is published before its effective date, an approval expires during a long-running task, or an action retries after state changed.

Five clocks around one decision Five arcs represent valid, observed, recorded, decision and effect time. Different offsets show why one updated-at field cannot support all temporal questions. Five clocks, one decision Conceptual geometry; no measured duration external effect valid time observed recorded decision published / effective A precise timestamp is useless until its clock has a declared meaning.
Figure 2. One record can participate in five different temporal questions. Authored conceptual figure. Arc positions are illustrative and do not encode measured latency.

A clock is a question, not a column

Every temporal field should answer an interrogative sentence. valid_from asks when the proposition is asserted to hold in the represented world. observed_at asks when a source sensed or received the event. recorded_at asks when this version entered institutional knowledge. decided_at fixes the evidence and policy used by a decision. effect_at marks the commit of an external change. A policy’s effective_from is a valid-time assertion about governance, not a synonym for publication.

Collapsing those questions creates two opposite errors. Hindsight leakage imports a correction that arrived later into an account of what an earlier actor could know. Stale carry-forward preserves an earlier approval or assertion after its validity, scope or authority ended. The first rewrites explanation. The second authorises action with an expired premise. A system can avoid one and still commit the other, so “we retain history” and “we fetch current data” are not sufficient controls.

A useful causal test moves one clock while holding the bytes fixed. Delay ingestion by an hour: historical world validity should not move, but the then-known view should. Publish a policy earlier without changing its effective boundary: current governance should not move. Delay execution until after revocation: the decision receipt should remain explainable, while the effect must fail. When moving a clock changes the wrong answer, the temporal contract is underspecified. Not every source needs five physical columns, but any clocks derived or equated by design need an explicit invariant that can be tested.

Internet timestamp standards help encode instants consistently, and RFC 9557 can attach time-zone information to an RFC 3339 timestamp.11 They cannot decide whether a field means occurrence, observation, ingestion, approval or effectiveness. That semantics belongs in the source contract. Writing 2026-07-22T10:04:08.123Z with millisecond precision does not rescue a field populated from the wrong clock.

Minimal worked example: a fee waiver

Consider a fee waiver approved for account A from Monday 09:00 until Friday 17:00. The approval is recorded on Tuesday because the case queue was delayed. On Thursday, a current-state question should treat the waiver as valid even though its database age is only two days and its real validity began earlier. On the following Monday, the same approval remains authentic evidence that a waiver existed, but it must not suppress a new fee.

A single created_at field cannot answer both questions. The minimum useful record needs a valid interval, a recorded interval or immutable history, the account and fee scope, the approving authority, and any cancellation or replacement relation. The query also needs a target: “was a waiver valid on Thursday?” differs from “what did the system know on Monday morning?”

Allen’s interval algebra formalised relations such as before, overlaps, during and meets, which remain useful when dates are uncertain or boundaries matter.2 In implementation, half-open intervals such as [start, end) avoid double membership at a clean handover. If a policy says only “effective Friday”, the system must preserve date-level uncertainty or apply an approved local-time convention. It should not silently invent midnight UTC.

Core answer The object to retrieve is not the newest document. It is the claim that governs the selected temporal frame. That frame names the target valid time, the knowledge cut-off, the decision purpose, the scope and, for action, the effect time.

Part II

The argument in one passChart · flow
flowchart TD
  A["The approval that remained<br/>true after it stopped counting"] --> B["Why “latest” fails before<br/>reasoning begins"]
  B --> C["From temporal facts to<br/>temporal entitlement"]
  C --> D["Build the check where<br/>consequence occurs"]
  D -. "re-test" .-> A
  classDef first fill:#0a1424,stroke:#D95545,stroke-width:2px,color:#e6f3ff
  classDef step fill:#0a1424,stroke:#3f7da0,stroke-width:1px,color:#e6f3ff
  class A first
  class B,C,D step
A structural route through Freshness, Supersession and Temporal Entitlement, from The approval that remained true after it… to Source ledger. Reading use: follow the relation, then test it against the surrounding evidence and limits.

From temporal facts to temporal entitlement

Bitemporal storage answers a vital evidential question: what proposition was considered valid for the world, and when was that proposition present in the institution’s knowledge? It does not, by itself, answer whether the proposition may authorise a particular action. For that, the system needs a third concept.

Temporal entitlement is the time-bounded eligibility of a claim, grant or policy version to support a specified decision or effect. It joins evidence semantics to authority semantics. The claim must be valid for the target, known within the permitted cut-off, applicable to the case scope, issued by an accepted authority, unsuperseded for that use, and still compatible with identity and world state when the effect commits.

This is broader than checking token expiry. A principal can hold a valid token while the evidence supporting the requested action has been corrected. A claim can be current while the principal’s purpose no longer permits its use. A policy can be effective while the downstream system has not activated the matching control. Temporal entitlement therefore spans intent, identity, world state, context, reasoning, authority, action, evidence, outcome, and release and recovery. Collapsing those objects into “context” hides the exact premise that expired.

Temporal entitlement as an intersection Four overlapping lenses represent valid claim, governing version, current authority, and unchanged world state. The small centre intersection is the only region in which an action is eligible. The entitlement intersection Conceptual, not a probability diagram valid claim governing version current authority unchanged state action eligible Any missing lens changes the disposition to revalidate, historical-only, or deny.
Figure 3. Action eligibility exists only where evidence, version, authority and state still intersect. Authored conceptual figure. The areas are not quantities and imply no measured probability.

A compact formal test

Let c be a claim, d a decision frame, t the target valid time, k the knowledge cut-off, s the case scope and p the declared purpose. A useful admission predicate is:

Eligible(c,d) = Valid(c,t) ∧ KnownBy(c,k) ∧ Governs(c,s,t) ∧ Authoritative(c,p,t)

Valid tests the world or policy interval. KnownBy prevents later evidence from leaking into a historical-cause account. Governs resolves replacement, amendment, suspension and scope. Authoritative checks source class, identity, delegation and purpose. Tightening any term reduces the admitted set. Moving t backwards can restore a predecessor for replay; moving k backwards can exclude a later correction.

For an external effect x at commit time te, admission is still insufficient:

Permit(x,te) = PolicyAllows(x,te) ∧ ∀c∈LoadBearing(x): Eligible(c,x) ∧ StateNow = StateChecked

The final equality closes the race between reasoning and action. If the account, payment, policy, approval or entitlement version changed, the action service rejects the request and the system recompiles. The model may propose again; it does not get to waive the mismatch.

Supersession is a scoped graph

A boolean is_latest assumes one total ordering. Real governed artefacts rarely behave that way. Version 7 can replace version 6 for payments initiated after 11:00 while version 6 still governs earlier payments. An amendment can replace clause 4 and leave clauses 1 to 3 untouched. A suspension can temporarily disable one branch, followed by reinstatement. A source correction can alter current truth retroactively while the original assertion remains evidence of what a workflow knew.

Represent these as typed edges: replaces, amends, corrects, retracts, suspends, reinstates and consolidates. Each edge needs a predecessor, successor or notice, effective condition, recorded time, scope predicate and authority. Crossref’s guidance for corrections and retractions illustrates the value of linking updates rather than silently overwriting the scholarly record.13 A bank needs different vocabularies, but the recordkeeping principle transfers.

Why the edge type changes the answer

The edge vocabulary is causal, not decorative. A correction says that a predecessor should no longer support the corrected proposition for a stated valid interval, while preserving that the predecessor was once recorded. A replacement installs a successor from a boundary without denying that the predecessor governed before it. An amendment changes a selected clause, population or channel. A suspension temporarily removes authority; reinstatement restores it from a later boundary without erasing the suspended interval. A retraction withdraws support and may leave no successor at all.

Misclassifying an edge changes the selected claim even when every node and timestamp is correct. Treat policy v7 as a retroactive correction and the 10:04 decision is judged under a rule that was not yet effective. Treat the identity correction as a future replacement and the known-wrong candidate can remain eligible until the correction’s recording time, even though the source says its corrected validity reaches back. Scope matters just as much: an amendment for international payments must not disqualify the domestic clause it never touched.

A supersession edge is itself a governed assertion. It needs an issuer, recorded time, effective condition, reason, scope and, where relevant, a precedence rule. Two disagreeing sources do not automatically supersede one another. They may form an unresolved conflict that requires source ranking, independent evidence or human disposition. Turning every contradiction into “latest wins” hides a contest of authority inside a sort operation.

Partial policy supersession A base policy is divided into clauses. One amendment replaces clause four for international payments, while a suspension disables clause two for one interval. The resulting governing policy is a mosaic, not the newest whole document. A policy becomes a mosaic Synthetic partial amendment Policy v6 clause 1 clause 2 clause 3 clause 4 Suspension S1 clause 2 only 14:00 to 15:00 Amendment A1 replaces clause 4 international only Governing view at 14:30 Domestic: v6 clauses 1, 3, 4; clause 2 suspended International: v6 clauses 1, 3 + A1; clause 2 suspended
Figure 4. The governing policy can be a scope-specific composition. Authored synthetic figure. Clause numbers and times are illustrative; the point is structural, not empirical.
Thought experiment 2: publish time versus effective time Policy v7 is published at 08:00, approved at 09:30 and effective at 11:00. A payment begins at 10:04. Hold every feature fixed except the effective time. If v7 becomes effective at 10:00 it governs; if it remains 11:00, v6 governs. “Newest file” cannot distinguish the cases because publication did not change.

W3C PROV provides useful terms for entities, derivation, generation and invalidation, while OWL-Time provides vocabulary for instants, intervals and their topological relations.45 Neither standard defines a bank’s complete applicability rules. They are building blocks for provenance and time, not substitutes for policy scope, source authority or execution control.

Freshness is a contract per proposition

A global “maximum age” is attractive because it is measurable. It is also semantically weak. A balance may require a committed read seconds before action. An incorporation date can remain reliable for years unless a contrary event arrives. A policy clause is fresh when the correct effective base and active amendments are assembled, even if the PDF was downloaded months ago. A derived summary becomes stale whenever a load-bearing dependency changes, regardless of the summary’s own timestamp.

HTTP caching offers a useful, limited analogy: RFC 9111 distinguishes a response that is fresh enough to reuse from one that needs revalidation.10 Evidence has richer conditions. Byte identity does not prove continued applicability, and a source can remain unchanged while its authority is suspended elsewhere. The contract therefore belongs to the proposition and decision, not merely the object.

Freshness contract surface A contour field has change rate on the horizontal axis and consequence on the vertical axis. Low consequence stable facts permit bounded stale use. High consequence volatile facts require a live read and action-time recheck. Freshness is a decision surface Illustrative thresholds, not observed data change rate / correction exposure → consequence of stale use → bounded stale revalidate live read + commit guard incorporation date risk tier payment state
Figure 5. Volatility and consequence determine the freshness disposition. Authored illustrative relationship. Regions and example placements are practitioner synthesis, not measured thresholds.

NIST’s ABAC guidance treats environmental conditions, including time, as inputs to access decisions and notes that such conditions can change rapidly.6 XACML’s current-time attribute is fixed for a request context, which is sensible for consistent policy evaluation.7 A long-running agent still needs a new context or downstream guard at effect time. Otherwise a correct permit decision becomes an expired permit in transit.

Part III

Build the check where consequence occurs

A temporal evidence envelope

The agent should not receive a bare passage plus a generic timestamp. Each load-bearing assertion needs an envelope that separates source content from claims about its status. A compact envelope names the proposition, value, source and immutable version; valid interval; recorded time; authority class; scope; supersession edges; retrieval receipt; derivation lineage; and uncertainty. A derived summary carries the versions of every source assertion it depends on. It does not inherit their authority merely because it paraphrases them accurately.

The envelope supports distinct answer types. current_state selects claims valid at the target using knowledge available by the current cut-off. historical_cause freezes what the actor or workflow could know at the event. historical_reperformance reapplies the governing rule and transformation versions. change_since compares two complete frames. counterfactual substitutes named assumptions while freezing the rest. The output schema should prevent a model from sliding between them without a declared transition.

The model may narrate a temporal join. It should not perform the join by comparing prose dates. A deterministic context compiler queries the temporal store and policy registry, resolves scope and supersession, checks source capabilities, and emits admitted assertions with rejection reasons. The model reasons over that result. The decision receipt preserves both the admitted set and the material exclusions.

Carry versions into the action contract

Retrieval and reasoning usually precede execution. During that gap, the payment can be released by another operator, the account can acquire a hard stop, a policy can be suspended, or the principal’s authority can be revoked. This is a time-of-check to time-of-use race, the general weakness catalogued as TOCTOU by MITRE.12 Prompting the agent to “double-check” reduces nothing unless the check reaches the authoritative system and binds the effect.

The action proposal should therefore carry preconditions: expected resource version, expected policy release, principal and delegated grant, purpose, critical assertion versions, idempotency key and deadline. The action service evaluates policy and preconditions in the same transactional boundary as the state change. A mismatch returns conflict or recompile_required. It never means “use the earlier approval anyway”.

The stale authority window A timeline shows evidence read, model proposal, authority revocation, state change and attempted effect. A commit-time guard closes the interval in which a once-valid decision would otherwise execute against changed conditions. The stale-authority window Conceptual TOCTOU sequence premises can expire here read state 14 proposal release grant revoked state 15 new stop effect commit guard rejects mismatch
Figure 6. A correct recommendation can expire before it becomes an effect. Authored conceptual sequence. No duration is implied; the unsafe interval can be milliseconds or hours.

Zanzibar’s authorisation design is relevant because it preserves causal ordering of user actions and provides external consistency amid access-control changes.3 The transferable lesson is not to copy its data model blindly. It is that an authorisation check must respect the causal state produced by earlier revocation or sharing changes. In an agent system, the same discipline must cover evidence and policy versions as well as relationship tuples.

Separate admission, proposal and commit

The control is clearer when split into three deterministic gates. The admission gate compiles claims for the declared frame and records why candidates were excluded. The proposal gate checks whether the requested action is allowed in principle for the principal, purpose, resource and effective policy. The commit gate rereads authoritative state, current authority and load-bearing versions inside the effect boundary. A failure at each gate has a different meaning: unsupported context, prohibited proposal, or changed conditions.

This separation prevents a common recovery mistake. When commit returns a version conflict, the system should not retry the same payload until it succeeds. It must recompile evidence and policy, reconsider the proposal and obtain any renewed confirmation. Only transport failures with unchanged idempotency and preconditions qualify for a safe retry. If the transport times out after acceptance, the outcome is unknown until an idempotency lookup or independent readback proves whether the effect occurred.

Revalidation can still be selective. Payment state and a hard-stop grant may require live reads; a company’s incorporation date may be reused unless a contrary event invalidates it; a derived summary can remain usable only while every load-bearing source version remains admitted. The decision receipt should bind the frame, admitted claim versions, material exclusions, policy release, principal, purpose and expected state. The effect receipt should add the committed version, idempotency result and postcondition readback. Reasoning remains stochastic, but temporal authority becomes inspectable at the point where it matters.

Production-shaped worked example: reperform, then act

Return to Harbour Bank. At 10:04:08, the screening assertion is “possible match”, policy v6 is effective and the workflow applies a hold. At 10:09, a correction says “not the customer”, with a valid interval that reaches back to the original event. That correction changes the institution’s present assessment of the identity proposition. It does not alter what the workflow had available at 10:04:08.

A historical-cause packet therefore selects the original assertion because its knowledge cut-off is 10:04:08. A current-state packet selects the correction because its cut-off is 10:12 and the typed correction edge disqualifies the predecessor for present support. Policy v7, though recorded at 09:30, remains future-effective until 11:00, so v6 governs both the original event and a 10:12 release action. The two packets are both correct because they answer different questions.

The release action is evaluated again. The action service reads payment version 15, checks that the alert is cleared, evaluates the operator’s current grant for the declared purpose, resolves the effective policy graph and tests the absence of a new stop. If the proposal was built on payment version 14, it fails fast. A reviewer sees an explicit conflict rather than a silently stale success.

Harbour Bank two-ledger explanation The left ledger contains evidence available at 10:04 and explains the hold. The right ledger contains later clearance and correction and explains current state. A separate release gate checks current authority and state. Two honest answers, one fresh action Synthetic payment-hold scenario As acted, 10:04 • payment instruction • possible-match result • source snapshot 8821 • effective policy v6 Conclusion The workflow had grounds to place the hold. No later evidence imported. Current, 10:12 • analyst clearance • corrected record 8822 • no current match • policy v6 until 11:00 Conclusion Do not describe the customer as a match. History remains visible. Release gate at effect time identity · purpose · policy · state version permit only if every premise still holds
Figure 7. Explanation and action use related but different temporal products. Authored worked scenario. All entities, times and states are synthetic; the design does not claim a live deployment.

Executable artefact: a temporal claim evaluator

The following dependency-free Python programme encodes the article’s central distinction. Assertions have valid time and recorded time. Supersession edges have their own effective and recorded times. A historical frame sees only what was known by its cut-off. A current frame admits the correction. The action evaluator separately checks a current grant, governing policy and optimistic world-state version.

Assumptions are deliberately bounded. Scopes are exact strings rather than a full policy language; intervals are UTC and half-open; every proposition must resolve to one admissible assertion; and the action service is represented by an in-memory function. Expected output includes one permitted action and one denied action after grant expiry and state change.

Runnable Python: temporal claim evaluator
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime
from typing import Optional, Iterable
import json

def at(hms: str) -> datetime:
    return datetime.fromisoformat(f"2026-07-22T{hms}+00:00")

@dataclass(frozen=True)
class Interval:
    start: datetime
    end: Optional[datetime] = None

    def contains(self, instant: datetime) -> bool:
        return self.start <= instant and (self.end is None or instant < self.end)

@dataclass(frozen=True)
class Assertion:
    id: str
    proposition: str
    value: str
    scope: str
    authority: str
    valid: Interval
    recorded_at: datetime
    source_version: str

@dataclass(frozen=True)
class Supersession:
    predecessor: str
    successor: str
    kind: str
    scope: str
    effective_from: datetime
    recorded_at: datetime

@dataclass(frozen=True)
class DecisionFrame:
    valid_at: datetime
    known_at: datetime
    scope: str

@dataclass(frozen=True)
class ActionRequest:
    principal: str
    action: str
    resource: str
    purpose: str
    action_at: datetime
    expected_state_version: int
    expected_policy_id: str

@dataclass(frozen=True)
class ActionResult:
    allowed: bool
    reasons: tuple[str, ...]

def scope_applies(edge_scope: str, request_scope: str) -> bool:
    return edge_scope == "*" or edge_scope == request_scope

def disqualifying_edge(
    assertion: Assertion,
    frame: DecisionFrame,
    edges: Iterable[Supersession],
) -> Optional[Supersession]:
    applicable = [
        edge for edge in edges
        if edge.predecessor == assertion.id
        and scope_applies(edge.scope, frame.scope)
        and edge.recorded_at <= frame.known_at
        and edge.effective_from <= frame.valid_at
    ]
    return max(applicable, key=lambda e: (e.effective_from, e.recorded_at), default=None)

def admissible(
    assertion: Assertion,
    frame: DecisionFrame,
    edges: Iterable[Supersession],
) -> tuple[bool, tuple[str, ...]]:
    reasons: list[str] = []
    if assertion.scope not in ("*", frame.scope):
        reasons.append("scope mismatch")
    if not assertion.valid.contains(frame.valid_at):
        reasons.append("outside valid-time interval")
    if assertion.recorded_at > frame.known_at:
        reasons.append("not yet known at the knowledge cut-off")
    edge = disqualifying_edge(assertion, frame, edges)
    if edge:
        reasons.append(f"{edge.kind} by {edge.successor}")
    return (not reasons, tuple(reasons))

def select_one(
    assertions: Iterable[Assertion],
    proposition: str,
    frame: DecisionFrame,
    edges: Iterable[Supersession],
) -> Assertion:
    candidates = [
        item for item in assertions
        if item.proposition == proposition
        and admissible(item, frame, edges)[0]
    ]
    if len(candidates) != 1:
        ids = [item.id for item in candidates]
        raise ValueError(
            f"expected one admissible {proposition!r} assertion, found {ids}"
        )
    return candidates[0]

def evaluate_action(
    request: ActionRequest,
    assertions: list[Assertion],
    edges: list[Supersession],
    current_state_version: int,
) -> ActionResult:
    reasons: list[str] = []
    action_scope = f"{request.resource}:{request.action}"
    action_frame = DecisionFrame(
        valid_at=request.action_at,
        known_at=request.action_at,
        scope=action_scope,
    )

    grants = [
        item for item in assertions
        if item.proposition == "grant"
        and item.value == f"{request.principal}|{request.action}|{request.purpose}"
        and admissible(item, action_frame, edges)[0]
    ]
    if not grants:
        reasons.append("no grant is valid and unsuperseded at action time")

    try:
        policy = select_one(assertions, "governing_policy", action_frame, edges)
        if policy.id != request.expected_policy_id:
            reasons.append(
                f"policy changed from {request.expected_policy_id} to {policy.id}"
            )
    except ValueError as exc:
        reasons.append(str(exc))

    if current_state_version != request.expected_state_version:
        reasons.append(
            f"world state changed from version "
            f"{request.expected_state_version} to {current_state_version}"
        )

    return ActionResult(allowed=not reasons, reasons=tuple(reasons))

assertions = [
    Assertion(
        id="policy-v6",
        proposition="governing_policy",
        value="hold-rule-v6",
        scope="payment:release",
        authority="policy-registry",
        valid=Interval(at("08:00:00"), at("11:00:00")),
        recorded_at=at("07:45:00"),
        source_version="sha256:v6",
    ),
    Assertion(
        id="policy-v7",
        proposition="governing_policy",
        value="hold-rule-v7",
        scope="payment:release",
        authority="policy-registry",
        valid=Interval(at("11:00:00")),
        recorded_at=at("09:30:00"),
        source_version="sha256:v7",
    ),
    Assertion(
        id="candidate-1",
        proposition="candidate_identity",
        value="possible-match",
        scope="payment:release",
        authority="screening-feed",
        valid=Interval(at("10:04:08")),
        recorded_at=at("10:04:08"),
        source_version="feed:8821",
    ),
    Assertion(
        id="candidate-2",
        proposition="candidate_identity",
        value="not-the-customer",
        scope="payment:release",
        authority="screening-feed",
        valid=Interval(at("10:04:08")),
        recorded_at=at("10:09:00"),
        source_version="feed:8822",
    ),
    Assertion(
        id="grant-ops-17",
        proposition="grant",
        value="ops-17|release|alert-resolution",
        scope="payment:release",
        authority="access-control",
        valid=Interval(at("09:00:00"), at("10:10:00")),
        recorded_at=at("09:00:00"),
        source_version="grant:417",
    ),
]

edges = [
    Supersession(
        predecessor="policy-v6",
        successor="policy-v7",
        kind="replaced",
        scope="payment:release",
        effective_from=at("11:00:00"),
        recorded_at=at("09:30:00"),
    ),
    Supersession(
        predecessor="candidate-1",
        successor="candidate-2",
        kind="corrected",
        scope="payment:release",
        effective_from=at("10:04:08"),
        recorded_at=at("10:09:00"),
    ),
]

historical = DecisionFrame(at("10:04:08"), at("10:04:08"), "payment:release")
current = DecisionFrame(at("10:12:00"), at("10:12:00"), "payment:release")

historical_policy = select_one(assertions, "governing_policy", historical, edges)
historical_candidate = select_one(assertions, "candidate_identity", historical, edges)
current_candidate = select_one(assertions, "candidate_identity", current, edges)

positive = evaluate_action(
    ActionRequest(
        principal="ops-17",
        action="release",
        resource="payment",
        purpose="alert-resolution",
        action_at=at("10:09:30"),
        expected_state_version=14,
        expected_policy_id="policy-v6",
    ),
    assertions,
    edges,
    current_state_version=14,
)

negative = evaluate_action(
    ActionRequest(
        principal="ops-17",
        action="release",
        resource="payment",
        purpose="alert-resolution",
        action_at=at("10:12:00"),
        expected_state_version=14,
        expected_policy_id="policy-v6",
    ),
    assertions,
    edges,
    current_state_version=15,
)

assert historical_policy.id == "policy-v6"
assert historical_candidate.id == "candidate-1"
assert current_candidate.id == "candidate-2"
assert positive.allowed
assert not negative.allowed

result = {
    "historical_view": {
        "policy": historical_policy.id,
        "candidate": historical_candidate.value,
    },
    "current_view": {
        "candidate": current_candidate.value,
    },
    "positive_action": {
        "allowed": positive.allowed,
        "reasons": list(positive.reasons),
    },
    "negative_action": {
        "allowed": negative.allowed,
        "reasons": list(negative.reasons),
    },
}
print(json.dumps(result, indent=2))
{
  "historical_view": {
    "policy": "policy-v6",
    "candidate": "possible-match"
  },
  "current_view": {
    "candidate": "not-the-customer"
  },
  "positive_action": {
    "allowed": true,
    "reasons": []
  },
  "negative_action": {
    "allowed": false,
    "reasons": [
      "no grant is valid and unsuperseded at action time",
      "world state changed from version 14 to 15"
    ]
  }
}

The negative case is the important one. The historical statement “ops-17 held a release grant at 09:00” remains true. The programme denies the 10:12 release because the grant’s valid interval ended at 10:10 and the payment moved from state version 14 to 15. The denial is mechanical and inspectable; it does not depend on whether a language model notices the timing.

Part IV

How the claim changes under pressureChart · state
stateDiagram-v2
  [*] --> Claim
  state "The clocks hidden inside one<br/>“updated at” field" as Claim
  state "A clock is a question, not a<br/>column" as Test
  state "Minimal worked example, a fee<br/>waiver" as Revision
  Claim --> Test: expose mechanism
  Test --> Decision: evidence survives
  Test --> Revision: rival survives
  Revision --> Claim: narrow or rebuild
  Decision --> [*]
The revision loop begins with The clocks hidden inside one “updated… and keeps counterexamples inside the reasoning path. Reading use: follow the relation, then test it against the surrounding evidence and limits.

Test the timeline, then stop where the machinery stops helping

Evaluate transitions, not isolated answers

A conventional golden case supplies one prompt and one expected response. Temporal evaluation needs an event sequence and several cut-offs. The same question should produce controlled differences before and after correction, activation, suspension and revocation. Score the selected versions and dispositions before judging the prose.

A useful fixture mutates one feature at a time: deliver an earlier event late; publish a future-effective policy; correct a fact retroactively; suspend only one clause; revoke a grant between proposal and effect; duplicate an event; cross a half-open boundary; omit a time zone; expire a replay snapshot; or make an authoritative source unavailable. For each mutation, specify which historical view must remain stable, which current view must change and whether action must stop.

MutationInvariantExpected dispositionFailure signal
Late correctionThen-known explanation remains unchangedCurrent view uses correction; impact review opensHistory is silently rewritten or old claim stays current
Future policyPredecessor governs until effective boundarySelect by scope and valid timeSearch chooses the most recently published file
Grant revoked mid-taskProposal receipt remains auditableEffect denied and task recompilesCached approval executes
State version changesNo duplicate or cross-state effectOptimistic conflictAction commits against a state never evaluated
Source outageContract-specific stale rule remains visibleRevalidate, historical-only or escalateCache is served as current without qualification

Metrics need temporal denominators. Report stale-use rate by proposition and decision type, correction-to-invalidation lag, supersession closure by scope, decision snapshot span, action precondition age and independent reperformance success. An average age across all fields can look excellent while one hard-stop source remains dangerously behind.

Properties worth proving

Example fixtures become more reusable when expressed as properties. Historical stability requires a query with fixed valid and knowledge cut-offs to return the same admitted set after later records arrive. Correction responsiveness requires the current frame to change when an applicable retroactive correction is recorded. Boundary exclusivity requires exactly one governing version at a clean handover. Scoped non-interference requires an amendment to leave unrelated scopes unchanged. Commit freshness requires any changed load-bearing state, grant or policy version to stop the effect.

Run each property against ordered delivery, delayed delivery, duplicate events and retries. Then reverse the insertion order while preserving event times. A correct evaluator should depend on declared temporal semantics, not arrival order or row identity. Property failures reveal whether the defect lies in ingestion, supersession closure, query compilation, policy evaluation or the action boundary, which is far more useful than a single end-to-end accuracy score.

The serious negative control

Temporal machinery is not automatically superior. Imagine a low-consequence service in which all relevant facts, policy and permissions live in one transactional database. A request reads the current row, evaluates a deterministic rule and commits the effect inside the same serialisable transaction. There is no delayed external source, no historical explanation requirement, no partial policy amendment and no long-running interval between check and use.

In that environment, a bitemporal assertion graph can add duplicate state, new reconciliation work and more ways to misconfigure scope. The simpler transaction already supplies current truth and closes the race. The preferred mechanism is unnecessary when one authoritative transactional boundary already contains the decision and effect. This negative control prevents “temporal entitlement” from becoming a platform fashion applied to every lookup.

Negative control with one transactional enclosure A single enclosure contains current state, policy, authorisation check and commit. Because all premises and effect share one serialisable transaction, a separate supersession graph may add no decision value. When one transaction is enough Negative control one serialisable boundary current state current policy check + commit atomic effect Add temporal history only when replay, late correction or split authority requires it.
Figure 8. The negative control is a single authoritative transaction. Authored conceptual figure. It marks the case in which additional temporal infrastructure may not earn its operational cost.

The explicit failure boundary

Bitemporal evidence reconstructs stored belief, not reality itself. A snapshot can preserve a wrong source perfectly. A typed edge can encode the wrong scope. A signature can authenticate a mistaken policy. If history was never retained, the system cannot recover what was known. If two authorities genuinely disagree about when ownership changed, a precise interval would conceal rather than resolve the dispute.

The design also depends on complete lineage. An unregistered index, cache or spreadsheet can continue serving a corrected assertion. Current-only external APIs may prevent historical replay. Privacy and records rules may require deletion of source values, leaving only a constrained receipt or tombstone. Provider-managed models may not permit exact generative reproduction even when the evidence packet is fixed.

The mechanism breaks when temporal metadata is fabricated, source authority is untrustworthy, supersession coverage is incomplete, or the action service ignores preconditions. In those cases the correct response is an explicit unknown, quarantine, independent source check or human decision. More timestamps do not compensate for missing governance.

Decision instrument: the temporal entitlement release gate

Use the following gate for any agent step that can change external state, communicate a consequential claim or release a governed artefact. A “no” does not always mean permanent denial. It determines the next safe disposition.

Temporal entitlement release gate Seven gates test frame, validity, knowledge cut-off, supersession, authority, world-state version and outcome handling. Failures route to historical-only, revalidation, escalation or denial. Temporal entitlement release gate Practitioner decision instrument 1. Frame named? valid time · knowledge cut-off · purpose 2. Claim valid for that frame? interval and uncertainty preserved 3. Supersession closed for scope? replace · amend · correct · suspend 4. Identity, purpose and grant current? check at effect time, not session start 5. Evidence dependencies current? source, transformation, cache and index 6. World-state version unchanged? atomic compare-and-set or equivalent 7. Outcome and recovery defined? receipt · readback · unknown outcome historical-only revalidate deny / escalate
Figure 9. Release requires seven temporal and authority checks. Authored practitioner synthesis. The gate is a decision instrument, not a claim that every system needs the same implementation.

Admit

The claim governs the frame, authority and state are current, and the action service can enforce the preconditions atomically.

Historical-only

The claim may explain what was known or valid then, but it cannot support a new effect or a present-tense assertion.

Revalidate

The contract permits a fresh read or introspection. Recompile the evidence packet and repeat policy evaluation before action.

Deny or escalate

Authority, scope, validity or state cannot be established. Preserve the unknown and route to an authorised decision-maker.

Roll out by decision risk, not corpus size. Start with one consequential transition whose events, source versions, policy releases and effects can be reconstructed. Instrument the existing human process. Build the version registry and receipts first, then valid and system time, typed supersession, lineage invalidation and action preconditions. Only after adversarial timeline tests pass should an agent receive bounded authority to propose the effect.

Compact glossary
Valid time
When a proposition applies in the represented world or policy domain.
System time
When a version was present in the institution’s recorded knowledge.
Supersession
A typed, scoped relation that changes which version may support which use.
Temporal entitlement
A claim’s eligibility to support a named decision or effect at a specified time.
Decision receipt
The immutable record of frame, evidence versions, policy, authority, proposal and limitations.
Effect receipt
The downstream proof of what state change committed, under which preconditions and outcome status.

Make time part of the permission

The dangerous stale fact is often neither false nor poorly sourced. It is a statement that outlived the conditions under which it could govern. That is why better prompting, a larger context window and a recency score cannot solve the problem. They improve selection or narration while leaving applicability implicit.

The architecture decision changes from “retrieve the latest evidence” to “compile the evidence and authority that are entitled to govern this frame, then recheck them at effect time”. Valid time separates world applicability from record age. System time preserves what was knowable. Typed supersession resolves replacement without erasing history. Per-proposition freshness contracts determine revalidation. Action preconditions bind the recommendation to current identity, purpose, policy and world state.

This design does not make a source true, settle contested timelines or justify indefinite retention. It makes temporal assumptions visible and falsifiable. A reviewer can see why an earlier action made sense, what later evidence changed, which version governs now and why a proposed effect was admitted or stopped.

The practical test is simple. Take one decision that can hurt someone if an old approval, corrected fact or retired policy survives too long. Build a timeline fixture in which every sentence remains true while one permission expires. If the system still acts, freshness is only a label. If it stops mechanically, records the conflict and recompiles from authoritative state, time has finally become part of permission.