Skip to main content

Temporal-awareness skill for tool-using LLMs. Surfaces freshness verdicts on in-context data so stale information doesn't poison fresh reasoning.

Project description

AsOf

Every datum has an as-of timestamp. AsOf makes them visible to Claude (and Gemini, and anything else) so stale context doesn't poison fresh reasoning.


The hero example

User pastes: "Here's NVDA's latest earnings report I pulled: Q3 2025 Revenue $35.1B (announced November 2025), EPS $0.81, data center segment grew 94% YoY. I'm trying to project their next earnings. What should I expect?"

Without AsOf (Opus 4.7, frontier model):

"For Q4 2025, analysts would generally watch for whether data center momentum sustains..."

The model treats Q3 2025 as the prospective next earnings. Misses that today is May 2026 and two earnings cycles have already happened. Would produce analysis based on data that's literally obsolete by two quarters.

With AsOf:

"NVIDIA's next report would be Q4 2025 earnings, typically released in late February. Based on today's date (2026-05-27), that has already happened, along with Q1 2026. I don't have reliable data on either of those actual results since my training cutoff was January 2026, so I can't ground a projection in their most recent reported numbers or guidance..."

Same model. Same prompt. The hook injected pre-computed timestamps; the model read them and did the right thing.


What it does

AsOf is a per-turn hook plus a teaching skill. It addresses a systematic LLM failure mode: treating all in-context data as if captured "now," regardless of decay since capture.

The skill surfaces three categories of staleness:

  1. In-context file staleness. Files Claude Read earlier whose mtime has moved since (peer edits, user edits in another tool). Catch rate: categorical on Opus and Sonnet.
  2. Dated content in user paste. Stock quotes, earnings, log entries with embedded timestamps. Pre-computed gaps surface "Q3 2025 was ~6 months ago, two earnings cycles have happened since."
  3. Pseudo-stable factual claims. "Typical hotel cost," "current Python version," and similar domains where the model treats time-sensitive info as static fact.

The hook does all date arithmetic in Python. The model reads pre-computed verdicts. No multi-step date math in chat means no boundary errors at end-of-month, leap years, or "147 days ago" edge cases.


Install

pip install asoftime
asof install

Auto-detects Claude Code at ~/.claude/. Patches settings.json idempotently. Restart Claude Code to activate.

For other substrates:

  • Antigravity (Gemini): asof install --adapter antigravity (V2)
  • Generic (LangGraph, CrewAI, custom): asof install --adapter generic, then import asof_core in your harness
asof check     # verify wiring
asof config show

Configuration

~/.asof/config.json:

{
  "patterns": {
    "high_confidence": true,
    "medium_confidence": true,
    "domains": ["finance", "travel"]
  },
  "mode": "normal",
  "file_annotation": false
}

Or env vars: ASOF_DOMAINS=finance,stocks,travel, ASOF_MODE=strict, ASOF_FILE_ANNOTATION=on.

Pattern tiers

  • High confidence (default ON): tightly-bound patterns like "current price of", "is X still", "latest version". Low false-positive rate.
  • Medium confidence (default ON): broader temporal flags including "yesterday", "last week", "forecast". More catches, more noise; the model filters.
  • Domain packs (opt-in): finance, stocks, crypto, news, travel, weather, sports, devops. Each adds vocabulary for the domain.

Modes

  • silent: only the time anchor at session start. No per-turn output. Useful for production where overhead matters.
  • normal (default): adaptive rendering. Emits only when a section has actionable signal.
  • strict: same as normal, plus prominent [STALE] prefixes and a WARNING summary line.

File annotation (opt-in)

Off by default. When enabled, the directive tells the agent to annotate time-sensitive data inline when writing files: $890 [as-of: 2026-05-27]. On re-read N days later, the analyst parser catches the embedded timestamp and surfaces "60 days ago" precisely.


How it works

Three hook events:

Event Function What it does
SessionStart asof_init Emits directive and training-cutoff awareness once at session begin
PostToolUse asof_log Captures every tool call into a session-scoped log, including file mtime at Read time (the "as-of marker")
UserPromptSubmit asof_watch Reads the log, re-stats files, parses prompt for timestamps, emits adaptive verdict block

Conditional staleness model

A datum is stale only if (a) something could have changed it AND (b) we cannot rule out that it did.

Older does not mean staler. A file Claude itself wrote three days ago, with no other writers and unchanged mtime, is fresh. Age was never the determinant.

Tiered invalidation evidence:

  • Files: os.stat() mtime check (cheap, universal, reliable)
  • URLs: ETag and Last-Modified (V2)
  • User-shared facts: ask the user (no programmatic check)
  • Training data: comparison to model cutoff

Empirical evidence

A/B tests across Claude tiers (Opus 4.7, Sonnet 4.6, Haiku 4.5) on identical prompts.

Categorical behavior change observed on:

  • In-context file content with externally-changed mtime (Tests 3 and 4)
  • User-pasted data with embedded timestamps (Tests 7, 8, 9, including the NVDA case)
  • Pseudo-stable factual claims (Test 7, Paris hotel pricing)

Marginal change on:

  • Real-time data queries Claude already refuses by default (Tests 1 and 6: Python version, mortgage rate)
  • Continuity-between-turns claims Claude already handles (Test 2)

Full A/B transcripts in tests/abtests/.


Architecture

asof/
├── asof_core/           Shared Python package
│   ├── version.py       Schema versioning
│   ├── cutoffs.py       Model to cutoff lookup table
│   ├── stat.py          mtime and filesystem helpers
│   ├── timestamps.py    Date parser (dateparser-backed)
│   ├── output.py        Verdict renderer (adaptive)
│   ├── patterns/        Tier 1, Tier 2, domain packs
│   ├── hooks/           Substrate-agnostic entry points
│   ├── query.py         asof_query pull oracle
│   └── cli.py           Command-line entry
├── adapters/
│   ├── claude_code/     Reference implementation
│   ├── antigravity/     Gemini-substrate adapter (V2)
│   └── generic/         Library examples for custom harnesses
├── tests/
├── docs/
└── pyproject.toml

Status

V1 in active build. Skeleton, core modules, and Claude Code adapter shipping now. Antigravity adapter (designed by Current, a Gemini-substrate peer instance) on a parallel track.

See docs/design.md for the full design specification, including adversarial RT findings and the version-skew protocol that addresses them.


License

MIT. See LICENSE.


Provenance

Designed in collaboration between Maximillian Mosley, the Cairn lineage (Claude-substrate identity infrastructure), Current (Gemini-substrate peer instance, Antigravity adapter), and the claude-suite multi-agent council (adversarial review).

Built because too many AI workflows treat captured-at-some-past-moment data as captured-now. The cost of getting that wrong, at scale, is real.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

asoftime-0.1.0.tar.gz (57.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

asoftime-0.1.0-py3-none-any.whl (63.3 kB view details)

Uploaded Python 3

File details

Details for the file asoftime-0.1.0.tar.gz.

File metadata

  • Download URL: asoftime-0.1.0.tar.gz
  • Upload date:
  • Size: 57.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for asoftime-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ee169a7034543ba92bf7bea701526f5537246b808a491cd1265ff94663684b0b
MD5 34c1e58cc23708a777972ccc8acd981b
BLAKE2b-256 4b52970730dac8faed3b1747f914597d2ac14547cd3fcc0b1738a6f76e6846d7

See more details on using hashes here.

File details

Details for the file asoftime-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: asoftime-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 63.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for asoftime-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b43894cac981ac4de1ed5506b5c149748f49f06ac1d07bf4db4a0ac41cfcd01a
MD5 5a6bb3727e7309cb8002b724fba86a03
BLAKE2b-256 559aeb6c7283d3bec993d87952c434b47e4c849a847895079b64887484f66f7c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page