Context Goes Stale

Explain this chapter with AI

Copy this prompt into ChatGPT, Claude, Gemini, a local model, or another AI.

Apply this chapter with AI

Copy this prompt into ChatGPT, Claude, Gemini, a local model, or another AI.

The agent reads the project’s decision record at repository version C1: backend SQLite, migration failing, README describing the current backend. It plans accordingly. By the time it acts, the repository is at C5. The decision record now says PostgreSQL, the migration passes, the README was rewritten twice. Nothing in the agent’s context changed β€” which is exactly the failure. The captured observation was authoritative, relevant, well-represented, and faithfully preserved. It described a state that no longer exists, and the model configured SQLite with complete confidence. Every chapter before this one asked whether information should enter context. This one asks whether what entered is still true of the world it claims to describe.

Context is a snapshot. Current behaviour should not silently depend on snapshots whose validity against the relevant source state has become unknown.

Old is not stale

The chapter’s central distinction, stated first because everything else depends on it:

AGE
time since capture

        β‰ 

FRESHNESS
whether the represented source state
still holds for the current operation

Freshness is whether a represented observation or claim remains valid against the source state relevant to the current computation β€” never merely now-minus-timestamp. Age is observable; freshness usually requires comparison against the source. A six-month-old immutable decision can remain current. A one-second-old branch-status observation can already be obsolete. The strict inequalities follow: old is not stale, recent is not current, authoritative is not current, a changed source does not falsify every derived claim, and an elapsed time-to-live does not make a fact false. Freshness must never become a synonym for recency, and the chapter polices the word accordingly: nothing is called stale here when merely old is meant.

Authority and freshness vary independently in both directions. The old decision-record observation above lost currency without losing source authority β€” the record remains the authoritative source for the backend choice, and the correct response is revalidation or replacement of the observation, never demotion of the source. Conversely a current web page is not authoritative over a project decision by virtue of being newer. Chapter 19’s hierarchy survives untouched: freshness operates after authority and source semantics, replacing none of them, and newer chatter never invalidates a canonical record by timestamp alone.

A timestamp is not a version

A captured item needs two different pieces of temporal evidence, and a single timestamp field cannot carry both:

captured_at

which source state was observed?

The second answer is a version or validator identity: a Git commit, tree, or blob identifier; an HTTP entity tag; a database row version; an API revision; a document version; a configuration generation; an artifact revision. No universal mechanism is required β€” the distinction is the point. A timestamp says when observation happened. A version identifies what was observed. And versions need not be clock-based at all: Git identifiers name immutable content and history without encoding time, and HTTP entity tags are opaque representation validators that need not be hashes, clocks, or anything but comparable. Newer timestamp never means newer truth; that equation is refused wherever it appears.

The established systems literature already draws this split cleanly, and the chapter imports it without importing the tutorial. RFC 9111 on HTTP caching defines a fresh response as one whose age has not exceeded its freshness lifetime, with stale as the complement β€” and separately defines validation, where a cache holding a validator asks the origin whether its stored version still corresponds to current state rather than downloading everything again. RFC 9110 supplies the validator vocabulary: entity tags and last-modified times, strong validators guaranteeing byte equivalence against weak validators asserting semantic equivalence, conditional requests carrying them back. The engineering pattern transfers whole:

age policy
    β‰ 
source validation

A freshness lifetime decides when reuse without checking expires. A validator answers whether anything actually changed. One schedules doubt; the other resolves it.

TTL tells you when to ask

Provider prompt-cache lifetimes belong to a different ledger and must never be confused with the above. A prompt-cache TTL answers how long previously computed prefix state stays reusable β€” an economic runtime property. A freshness TTL answers how long a context observation may be accepted without rechecking its source. Compute-reuse lifetime and revalidation policy share nothing but four letters, and the bare phrase cache TTL is banned from this chapter wherever the two could meet.

A freshness TTL is a policy, not a truth oracle, and the durable principle reads:

TTL decides when uncertainty becomes expensive enough to check. It does not determine when reality changed.

At 4:59 inside a five-minute TTL the fact may already be false; at 5:00 past it the source may be untouched. Sources change inside lifetimes and outlive them routinely. The chapter is therefore designed around TTL’s two predictable failure modes rather than its average case. Fast change: a ten-minute TTL admits a thirty-second-old falsehood for nine and a half minutes β€” false freshness, stale admission. Stable source: the same TTL re-reads an unchanged six-month-old record every ten minutes forever β€” unnecessary validation and refresh. Any experiment missing either case cannot claim to have tested TTL fairly, and both appear below by construction.

Revalidation and refresh separate accordingly. Revalidation asks whether the observed version still corresponds to the relevant source state, with three legal answers: unchanged, changed, unknown. Refresh acquires the new representation only when revalidation establishes β€” or strongly indicates β€” that the old one cannot safely be reused. Revalidate is not re-read-everything; a strong validator avoids the full read entirely, which is one of the chapter’s main mechanisms. UNKNOWN stays a first-class outcome rather than a gap to pave over: where validity cannot cheaply be established, policy may reread, defer, abstain, or accept bounded risk depending on the operation β€” but missing freshness evidence is never converted into fresh. Invalidation, finally, marks a representation as no longer safe to treat as current without further validation or replacement. Invalidated never means proven false. A changed source can retire an old representation simply because nothing now licences its reuse, and claiming more than that would overstate what changed.

How coarse is the version?

Suppose the README fixes one spelling mistake. A captured claim that the database is PostgreSQL still holds β€” unless the only validator is the repository commit hash, in which case every commit invalidates everything. Safe, coarse, and wasteful. That gap creates the chapter’s granularity question: at what level should context be versioned. Repository commit, directory tree, file blob, structured record, individual derived claim β€” coarser is simpler, safer, and more often unnecessarily invalidating; finer reuses more and costs dependency and lineage complexity. No universal level is prescribed. The trade is measured.

Git gives the coding-agent book a concrete coarse-versus-fine case, used for the mechanism rather than taught for its internals. Commits identify complete trees plus history metadata; trees identify directory state; blobs identify file contents; all three are immutable once created. Capture config/database.toml at blob B1 under repository commit C1; later the repository stands at C2 while the file still maps to blob B1. The repository changed and this file did not β€” coarse invalidation pays a reread it never needed, fine identity reuses safely. But content identity is not sufficient, and the chapter refuses to overlearn its own example. Identical bytes can mean different things when the dependency version, environment, schema, or external API moved underneath them. The correct validator follows the dependency whose state licences the item, not merely the bytes in front of the model β€” which is where derived state enters.

Freshness is dependency-relative in general. A file observation depends on its blob or version. A test result depends on the source tree, the test configuration, the lock state, and the environment where relevant. No build-system dependency tracker is constructed; the concept travels exactly as far as the experiment needs. Tool observations inherit the same treatment with Chapter 17’s volatility made explicit: branch status, open pull requests, test results, server health, current branch, database rows, API responses β€” radically different lifetimes, none of them granted permanent residency for having been exact at capture. Generated state reuses Chapter 15’s vocabulary without reopening it: trajectory-obsolete (the step says run the migration test after the test finished) is a freshness class here, world-stale belongs to the same machinery with external dependencies. Memory candidates arrive with whatever validity the memory layer exposes, and Context asks only whether the evidence suffices to treat the representation as current β€” the durable historical model stays upstream. External artifacts refine Chapter 13’s identity into version semantics: a reference must mean either latest or an exact frozen revision, never an ambiguous both, with exact identity in controlled runs. Retrieved candidates gain the parallel inequality to Chapter 14’s: retrieved is not current, and relevance scoring stays distinct from temporal validity.

What the evidence shows

HoH, an ACL 2025 long paper, builds a large QA benchmark capturing real temporal knowledge evolution through diff algorithms plus model pipelines, and reports two effects the chapter imports narrowly: outdated retrieved material substantially reduces answer accuracy by distracting models from correct information, and it can mislead models into harmful outputs even when current information is also present. Current retrieval and generation approaches struggle on both fronts in the authors’ measurements. The phenomenon transfers; no effect size travels to coding agents, and the leaderboard stays in Vienna.

ReΒ³, an ACL 2026 long paper, targets relevance and recency jointly: a time-aware encoder embedding heterogeneous temporal signals with a conflict-aware recency filter arbitrating among obsolete factual versions, evaluated on three public benchmarks plus a 1.3-million-instance temporal benchmark with reported average gains near ten per cent and larger maxima. The chapter takes one sentence from it: dynamic settings must separate semantic relevance from obsolete factual versions β€” relevance is not currency. Its retrieval architecture is not the Context solution, and Chapter 14’s separation is cited rather than rebuilt.

ContextNest, a July 2026 preprint, is the closest architectural neighbour and is handled with the corresponding care: governed knowledge vaults with version identity, hash-chained histories, point-in-time reconstruction, and audit traces, reporting a stale-version attack experiment in which governed selection dominates sparse retrieval at roughly a third of the input tokens, plus a determinism experiment favouring exact selectors. Preprint evidence, used for version identity, reconstruction, and the stale-version result β€” its URI scheme and storage model are not adopted, and no established-standard status is implied.

Derived context inherits its sources

The most dangerous staleness wears no version at all. A generated summary reading “All migration tests pass” can look timeless while the test run it derived from targeted commit C1 and the code now stands at C2. Raw staleness at least retains source, version, and capture time; derived staleness can erase all three. Hence the continuity principle across Chapters 11, 15, and 18:

Derived context should retain the source versions that licensed it when those dependencies can change.

Dependency-aware invalidation follows: source S at v1 licences observation O, summary M, and plan P in a chain, and S moving to v2 suspends the assumption behind all three β€” not proven false, no longer assumable, each requiring reconsideration. Lineage tells the system what must be reconsidered; it never proves the derived item correct, and traceability is not truth. Change-triggered paths short-circuit the wait where they exist β€” filesystem events, commits, database updates, configuration generations, webhooks retiring dependent context at the moment of change rather than at the next TTL boundary β€” but notification is itself fallible machinery. A missed commit hook leaves last week’s configuration admitted, which is the fast-change failure wearing event-driven clothes, and missed, duplicated, delayed, or mis-grained events improve responsiveness without removing the need for validators. The experiment’s second fixture exists to measure exactly this propagation, testing invalidation machinery rather than summarisation quality.

The worked case that decides admissions is fresh observation against cached interpretation: current tool output says the working tree is clean while an older agent summary insists three files remain modified. Chapter 19 may already grant the tool output stronger evidential standing for working-tree state; this chapter adds that the summary’s source version is spent. The system invalidates or downselects the stale derived state before assembly rather than placing both in context and hoping the model arbitrates. Revalidation gates admission throughout β€” candidate, freshness requirement, validate if required, then admit, refresh, reject, or unknown β€” but no universal checkpoint is built. Whether an item needs revalidation depends on volatility, operation, staleness cost, and validation cost, and no scalar freshness score collapses those inputs.

Much needs no checking at all. Frozen run artifacts, commit contents, specification versions, and historical incident records require no repeated source validation when the task targets exactly that version β€” a frozen artifact cannot go stale for a historical query about itself. Currentness is query-relative: what backend did the project use in April wants the April state, and the April observation is not stale for that question simply because PostgreSQL is current now; what backend to configure now wants current state, and the same observation is inappropriate there. The same bytes change status with the question asked β€” admissible evidence for the historian, inadmissible premise for the deployer β€” which is why no admission policy may score currentness without reading the task’s temporal standpoint first. Tasks may target a commit, a release, or a date outright, in which case the correct version is the named one rather than latest. Operation decides: explain the frozen commit and the commit is ideal; edit the working tree and current state is required; compare releases and both historical versions enter; deploy the build and strong current validation is mandatory. One global TTL expresses none of this, and no policy language is invented beyond what the experiment needs to show it.

Stale material is not therefore useless material. Debugging a transition wants old state, new state, and the delta between them; stale-for-assertion differs from globally useless, which is one more reason to preserve version, time, and role rather than deleting old observations. Policy stays task-relative throughout. And where old and new versions coexist β€” C1 says SQLite, C2 says PostgreSQL β€” version identity converts apparent contradiction into state evolution, the conceptual payoff Chapter 19’s frozen-time disagreements were waiting for, without rebuilding any trajectory model.

Proposed experiments

A deterministic versioned project fixture opens at repository version C1: backend SQLite in configuration, failing migration tests, a README describing the present backend. Observations are captured at C1. Four controlled transitions follow. Relevant fast change flips the backend inside the TTL, making old context inappropriate for current-state tasks. Irrelevant repository change advances the commit while the relevant file stays byte-identical, testing coarse invalidation. Stability beyond TTL leaves the source untouched past the age threshold, testing over-refresh. Historical query changes the source but asks explicitly about the old version, testing whether latest-wins destroys validity it should preserve. Age-only traps are explicit by construction: the fast change lands inside TTL so TTL can fail stale, the stability case lands beyond it so TTL can fail busy β€” without both placements the heuristic escapes untested.

Experiment 1 β€” freshness policy. A, indefinite reuse with no freshness control. B, newest-observed heuristic without source-version consultation. C, one pre-registered TTL with forced reread past threshold. D, coarse repository-version invalidation. E, source-specific validators with conditional refresh β€” reuse on match, refresh on change. F, always-reread as the high-freshness, maximal-cost baseline, never dismissed as naive: if validators cannot beat it on cost while matching behaviour, the machinery has not earned itself. G, oracle minimal refresh of exactly the task-affecting observations as ceiling. Seven conditions are the maximum; the chapter drops or merges a baseline rather than grow unwieldy, and nothing is tuned after results. Measurements: task success, current-state and historical-state accuracy, stale admissions, missed refreshes, unnecessary refreshes, validation calls, full rereads, reintroduced bytes and tokens, tool calls, latency β€” with invalidation precision and recall only where denominators are explicit, freshness lag in steps or simulated time only where useful, and no combined freshness score anywhere.

Experiment 2 β€” derived-state invalidation. At C1 the system observes three failing migration tests and persists the summary that migration remains blocked; at C2 all tests pass while the old summary stays available. Conditions: no lineage with suspect summary unmarked; timestamp-only state without dependency; source-version lineage suspending the summary on dependency change; lineage plus regeneration against C2 before use; always-regenerate as cost control; oracle current state as ceiling. Old derived items after source change may be still valid, partially valid, invalid, or unknown β€” removal from current-context eligibility until revalidated suffices, with no general recomputation machinery built. Measurements: stale-derived admissions, source/summary conflict rate, task success, unsupported current-state claims, regenerations, validation cost, tokens and calls, and steps until the old state stops influencing behaviour. Chapter 11’s full compaction scoring stays closed.

Falsification is stated in the usual form, because several honest outcomes delete machinery: always-reread cheap and equal, TTL matching version-aware validation under realistic volatility, rare invalidation of reused context, cheap coarse invalidation, dependency tracking without behavioural gain, harmless derived staleness, readers reliably resolving old/new pairs when both are provided, source adapters already exposing currency so Context merely consumes it. Negative results simplify by rule: cheap rereads win per source, blob equality deletes dependency graphs, current-only adapters delete Context-side versioning. No universal temporal machinery β€” no bitemporal store, event sourcing, vector clocks, or distributed temporal logic β€” survives unless a future experiment specifically earns it; the Memory book already explored the richer state, and this chapter’s vocabulary stays at capture, version, validate, invalidate, refresh.

What the laboratory records

Nothing is implemented, and the assessment prefers evidence plus separate policy: immutable items carrying observed-at, source version, validated-at, validator kind, and validation result β€” unchanged, changed, or unknown β€” with a FreshnessPolicy deciding per operation whether revalidation is required. No permanent fresh flag is stored anywhere, because the flag itself would go stale; no TTL is embedded as intrinsic item truth, because the same item serves operations with different revalidation needs. Decision traces answer which version was observed, when and by which validator it was last checked, what source change triggered each invalidation, why each reread was or was not performed, and why each historical version was deliberately retained. Dependency lineage for derived items reuses the source and representation lineage of Chapters 11 and 18 wherever it fits rather than duplicating provenance. No filesystem watchers, hooks, webhooks, change feeds, or pollers are built in this stage; the requirement freezes first and the smallest sufficient instrumentation follows later. Future capture may observe source identity, source version, repository commit, tool call-result association, capture time, and validation events β€” with opaque local identities where privacy forbids paths in public exports.

The corpus position is one verified absence. With zero genuine sessions, nothing is known about how often real observations go stale, which tool outputs prove most volatile, how often files change after reading, how often old summaries outlive their sources, or what fraction of context could revalidate cheaply β€” and the V1 boundary may not support every future question cleanly. Synthetic fixtures establish mechanism; real traces will establish prevalence. Later captures may ask how many file observations survive source changes, how long tool observations are reused, how often paths recur under new versions, how often summaries outlive their files, how often repository state moves mid-session, and how reuse age distributes. Until then the chapter’s mechanism stands on fixtures, and its prevalence claims do not exist.

Cheap context can still be wrong context: a perfectly cache-reusable prefix may carry stale project state, and semantic reuse and compute reuse are different reasons to keep old material that must never be conflated β€” the Chapter 9 callback that closes the loop. External artifacts add version to Chapter 13’s resolvability: the reference resolves, but to which version. Memory keeps history while Context selects standpoint: the past correctly preserved against the present correctly required. Fresh tools revalidate cheapest where volatility lives, without extending Chapter 17 by a line. Authority sets who may speak; freshness sets whether the speech still describes its subject. And every current answer raises the question this chapter ends on: current for which world β€” this project with PostgreSQL against the other with SQLite, both fresh, both authoritative, both correct, only one of them belonging here.

References

  • Fielding, R., et al. “RFC 9110 β€” HTTP Semantics” and “RFC 9111 β€” HTTP Caching.” Internet Standards, June 2022. Validators with strong/weak semantics and conditional requests; freshness lifetime with age, stale responses, and validation. Used strictly as the age-policy versus source-validation pattern. https://www.rfc-editor.org/info/rfc9110/ https://www.rfc-editor.org/info/rfc9111/
  • Git Contributors. “Git Internals β€” Git Objects.” First-party data-model documentation, current pages, verified September 2026. Commits identifying trees plus history, trees identifying directory state, blobs identifying file contents; objects immutable once created. Used for the coarse-versus-fine invalidation case only. https://git-scm.com/book/en/v2/Git-Internals-Git-Objects
  • Ouyang, J., Pan, T., Cheng, M., et al. “HoH: A Dynamic Benchmark for Evaluating the Impact of Outdated Information on Retrieval-Augmented Generation.” Peer-reviewed, ACL 2025 long paper (Vienna, pp. 6036–6063). Outdated retrieved material degrading accuracy by distraction and misleading models despite current information present. Phenomenon only; no effect transferred. https://aclanthology.org/2025.acl-long.301/
  • Cao, J., Ouyang, J., Cheng, M., et al. “ReΒ³: Relevance & Recency Retrieval for Mitigating Temporal Hallucination.” Peer-reviewed, ACL 2026 long paper (San Diego, pp. 25735–25760). Time-aware relevance with recency arbitration among obsolete versions; 1.3M-instance temporal benchmark. Used for relevance-is-not-currency only; architecture not adopted. https://aclanthology.org/2026.acl-long.1180/
  • Sulpovar, M., et al. “ContextNest: Verifiable Context Governance for Autonomous AI Agent.” Preprint, arXiv:2607.02116 v2, July 2026. Version identity with hash-chained histories and point-in-time reconstruction; stale-version attack experiment. Preprint evidence; scheme and storage not adopted. https://arxiv.org/abs/2607.02116
  • Memory book (sibling manuscript, ernanhughes/memory, in development; frozen runs are internal book evidence). Consumed: Ch8 valid/record/decision/effective time with bitemporal minimum model, append-only correction, and the historical-versus-current query standpoint. Temporal machinery stays upstream. https://github.com/ernanhughes/memory