brain-bitemporal — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited brain-bitemporal (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Brain is a bitemporal store. Every fact carries two time axes — when it was true in the real world (validFrom/validUntil) and when brain knew about it (recordedAt/retractedAt). Most agent code can stay on the "actual now" default; this skill is for when the user's question demands otherwise.
| Axis | Field pair | Meaning |
|---|---|---|
| Valid time | validFrom / validUntil | When the fact was true in the world. validUntil open-ended (null) means "still true". |
| Transaction time | recordedAt / retractedAt | When brain learned the fact / when brain learned it was wrong. retractedAt = null means "still believed". |
Examples:
validFrom/validUntil. Neither is wrong; one succeeds the other.Without asOf, every brain query returns only facts currently true in the world AND currently believed by brain:
validFrom <= now AND (validUntil IS NULL OR validUntil > now)
AND status NOT IN ('superseded', 'retracted', 'compacted')
AND (retractedAt IS NULL OR retractedAt > now)This matches the Datomic / Zep convention and is almost always what callers want. If you're not sure whether to pass asOf, don't.
When the user asks "what's new since last time" / "what changed in the last week" / "diff between two points in time", don't fetch the timeline and diff it yourself — use memory_diff:
memory_diff({
from: "2026-05-15T00:00:00Z",
to: "2026-05-22T00:00:00Z",
entityIds: undefined, // optional — scope to a set of entities
predicates: ["status", "tier"], // optional — scope to a predicate family
})Returns five buckets for the half-open window [from, to):
createdFacts — net-new active facts (excludes rows that were superseded in-window — those go in changedFacts so consecutive diffs never double-count)retractedFacts — pure retracts with no successorchangedFacts — superseded transitions, each carrying { before, after }newEntities — knowledge_entity.createdAt in-windowforgottenEntities — GDPR-erased tombstones in-windowThe killer use case: a session-resume agent fetches memory_diff(lastSessionEnd, now) and uses the result to brief the user on what brain learned while they were away. Cheaper than re-fetching every relevant profile from scratch.
Consecutive diffs over adjacent windows compose: diff(T0, T1) + diff(T1, T2) covers [T0, T2) without double-counting because the window is half-open.
asOf is also available on search_multi_hop — the planner threads the cursor through every hop, so a historical multi-hop question (e.g. "what tenants in April had been complaining since March?") works the same way as a single-hop search.
asOfThree legitimate cases:
"What was Alice's tier on March 15?"
→ search_knowledge({ query: "Alice tier", asOf: "2026-03-15T00:00:00Z" })Returns the fact that was valid on that date.
"On April 1, what did brain believe about this dispute?"
→ get_entity_profile({ entityId: "...", asOf: "2026-04-01T00:00:00Z" })Returns the snapshot of beliefs as of that wall-clock moment — including facts that have since been retracted but were believed then.
"Before the migration on May 5, what status was tenant X in?"
→ get_entity_profile({ entityId: "...", asOf: "2026-05-04T23:59:59Z" })Same as case 2 but with a sharper temporal frame — useful for postmortems where you need to prove "the data we were acting on said Y".
get_entity_timeline returns the audit trail — retracted facts included. Each row carries:
{
"factId": "...",
"predicate": "tier",
"object": "platinum",
"validFrom": "2026-04-01T00:00:00Z",
"validUntil": null,
"recordedAt": "2026-04-02T08:33:00Z",
"retractedAt": "2026-04-10T14:00:00Z", // ← present means retracted
"retractionReason": "Source misattributed; was Bob, not Alice.",
"status": "retracted"
}How to surface to the user:
(retracted: <reason>) suffix. Never claim it never existed.predicate. Each predicate's currently-active fact is the head of a chain; older versions sit behind it."What was true in March" (valid time) is different from "what brain knew in March" (transaction time). The asOf parameter in brain currently filters on the valid-time axis with retracted-row gating against the same instant. If you genuinely need a transaction-time-only query (rare — usually only postmortems), pull the full timeline and filter by recordedAt client-side.
asOf from a previous turnIf the user asked an as-of question, then asks a follow-up "and what about her email?", drop the `asOf` unless they say "still on April 1". Sticky asOf is a footgun.
validUntil as "expired"A fact with validUntil = 2026-04-01 was true up to that moment. It's not "stale data" — it's bitemporally correct. Don't filter it out client-side; brain already did the right thing.
single_active predicates like bitemporalSome predicates are single_active (e.g. name, email, phone): there can be only one active value at a time. New value supersedes old, no overlapping windows. Other predicates are bitemporal (status, intent, address): values are explicitly tagged with a window and can overlap with retracted but never with active. Conflict resolver scores both kinds the same; the semantics differ only at read time. Full table at /docs/concepts/predicates.
Default to no asOf. Brain's "actual now" answers ~95% of agent questions correctly. Reach for asOf only when the user's question explicitly contains a date / "before X" / "what did we know" phrasing.
The recordedAt axis on get_entity_timeline is the transaction-time question. Sorting the timeline by recordedAt gives you brain's learning order; sorting by validFrom gives the real-world order. They're often different — a fact "valid from 2026-01-01" might be recordedAt = 2026-05-12 if a backfill landed late.
/docs/concepts/bitemporal — full semantics with Allen-interval-algebra examples/docs/concepts/conflict-resolution — how brain decides which fact wins when two ingests overlap~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.