Skip to main content

Auditing Memory

StateCore does not just store what it currently believes about a user — it keeps the record of how it came to believe it. This page covers the endpoints that let you ask.

Evolving surface

These three endpoints are not part of the frozen /v1 contract. They work today and are safe to use, but their response shapes may change while the model matures — so they are documented here rather than in the generated API Reference. Everything in the API Reference is frozen; nothing here is yet.

What is recorded

Every fact in the fact registry carries:

  • evidenceId / evidenceType — the event or document the fact was taken from. A fact sourced from an uploaded document carries higher authority (0.85) than one taken from conversation (0.6).
  • supersededBy — the id of the fact that replaced this one. Corrections never overwrite; they create a new version and link back.
  • retiredAt / retiredReason — set when a fact left the active set without a replacement, for example because its facet hit capacity or consolidation dropped it. The record stays.

POST /v1/memory/retrieve returns only active facts — those with neither supersededBy nor retiredAt. The history is reachable through the endpoints below.

Why is this fact believed?

curl "https://api.statecore.io/v1/memory/facts/<factId>/provenance?scopeId=<scopeId>" \
-H "Authorization: Bearer sc_live_..."
{
"fact": {
"id": "fact-1785961957740-jg1hn",
"content": "Skills: TypeScript, Go, PostgreSQL, Rust",
"facet": "identity",
"confidence": 0.85,
"evidenceId": "40db6cdf-cdc6-410b-a3d9-1817d3eb0dcf",
"evidenceType": "document",
"supersededBy": "fact-1785962411882-046dq"
},
"chain": [
{ "id": "fact-1785961957740-jg1hn", "content": "Skills: TypeScript, Go, PostgreSQL, Rust" },
{ "id": "fact-1785962411882-046dq", "content": "Skills: TypeScript, Go, PostgreSQL, Rust, Zig" }
]
}

chain is ordered oldest first and spans every version, so you can call this with any id in the chain — including one you cached before a correction — and get the whole history back.

Returns 404 if the scope has no digest state yet, or the fact id is unknown.

What did this digest discard?

A digest cannot keep everything: budgets bind, facets fill up, and duplicates get merged. Every discard is recorded rather than silently dropped.

curl "https://api.statecore.io/v1/memory/digests/<digestId>/selection" \
-H "Authorization: Bearer sc_live_..."
{
"rationale": ["selected_docs:1", "selected_stream:4", "char_budget_dropped:2"],
"drops": [
{
"reason": "cap_evicted",
"detail": { "facet": "notes", "value": "…", "cap": 30 }
}
]
}

rationale describes what the selection stage kept. drops lists information that did not make it into the state, with a reason:

reasonmeaning
facet_not_registeredThe extracted fact named a facet this account's ontology does not define.
cap_evictedThe facet was full; its oldest entry was retired to make room.
cap_rejected_incomingThe facet was full and write-protected, so the incoming fact lost.
protected_lower_authorityA write-protected fact would have been overwritten by a lower-authority source.
no_document_evidenceA document-only facet received a fact with no document behind it.
no_display_groupThe fact is stored but its facet is never surfaced through the facts API.
consolidation_skippedThe facet was not eligible for consolidation this run.

An empty drops array means the run discarded nothing. A digest created before this feature shipped returns empty arrays for both fields — absence of a log is not the same as a run that dropped nothing.

Retention

Selection logs live on the digest they describe, and digests are retained for 90 days — so this endpoint answers for recent digests, not for all time. The most recent digest of a scope is never deleted.

A fact's version chain is not subject to this: it lives in the current state, not in old digests, so .../provenance reaches back past the digest retention window.

What kinds of fact does this account store?

curl https://api.statecore.io/v1/facet-pack \
-H "Authorization: Bearer sc_live_..."
{
"name": "personal",
"isDefault": true,
"facets": [
{
"name": "identity",
"cap": 15,
"writeProtected": true,
"documentAuthority": true,
"displayGroup": null,
"routesFrom": ["personal_detail"],
"description": "durable personal facts from documents (resume/bio)"
}
]
}

A facet pack is the vocabulary of fact types an account stores. Each facet declares:

  • cap — how many facts of this kind stay active at once.
  • writeProtected — conversation cannot overwrite these; only an equal or higher-authority source can.
  • documentAuthority — facts here come from uploaded documents. A fact extracted from chat with no document present is rejected, and the rejection appears in the selection log as no_document_evidence.
  • displayGroup — the group this facet appears under in GET /v1/memory/facts. null means it is stored but never surfaced there.
  • routesFrom — the classifier labels that route into this facet.

isDefault: true means the account runs the built-in personal-assistant ontology. Accounts can be configured with a different pack — a legal or clinical deployment stores entirely different kinds of fact. Packs are installed by StateCore; contact support if the default vocabulary does not fit your domain.

caution

Changing a pack is not reversible in effect. Facts in facets the new pack does not define stop being surfaced, and newly extracted facts naming them are rejected. This is why packs are not self-service.