Where did this come from?

A citation that names a document is nearly useless six months later. Provable Memory pins a claim to the exact character range of the exact quote it rests on, hashes that quote, and grades the claim against it.

  • Character, line and page offsets
  • SHA-256 quote hash
  • 10 operations
  • No model, no key, no latency

The span, not the document

A source span is a small, boring record that answers one question exactly. It is the unit everything else on this page is built from.

SOURCE · kb_document doc_4471 · terms-v3.md …a grace period of 30 days… char 1180–1244 · line 42 page 3 · source_uri set CLAIM · c_88a1 The grace period is 30 days. partially_supported overlap 0.43 · deterministic-local quote_hash · sha256 4f9c1d20…e11b rehash the quote; a mismatch means it moved
A source span records where a quote came from — source type and id, the URI, character, line and page offsets — and stores the SHA-256 hash of the quote itself. The claim that rests on that span is graded against it and carries the grade, so “where did this come from?” resolves to an offset range rather than a document name.

What a span stores

source_type and source_id say which system and which object. source_uri is where to go and look. Three independent offset pairs are available and all are optional — char_start/char_end for text, line_start/line_end for code and configuration, page_start/page_end for anything paginated. Use whichever the source actually has.

The quote itself is stored, up to 200,000 characters, and hashed with SHA-256 into quote_hash. That hash is the point: re-read the source, rehash the text at those offsets, and if the digest differs the source has been edited underneath you. A second content_hash covers the span identity even when no quote was supplied.

A span with a quote is written as verification_state: supported with confidence 1.0, because the quote is the evidence. A span without one drops to unverified and confidence 0.4 — you recorded a pointer, not a proof, and the record says which.

source_span

A span as stored

source_type
kb_document
source_id
doc_4471
source_uri
kb://terms-v3.md
char_start · end
1180 · 1244
line_start · end
42 · 42
quote
“…a grace period of 30 days…”
quote_hash
sha256:4f9c1d20…e11b
authority
raw
verification_state
supported

POST /v1/provenance/source-spans

Grading a claim without a model

POST /v1/provenance/claims/verify takes a claim and a list of span ids and returns a grade. It does this with arithmetic, and it tells you so in the record it writes.

The check takes every word in the claim longer than four characters, strips punctuation, lowercases it, and counts how many of those terms appear anywhere in the concatenated text of the attached spans. The ratio of matched terms to total terms is the grade, and it is also stored as the record's confidence.

That is lexical overlap. It is not semantic entailment, and it will not catch a claim that contradicts its evidence using the same vocabulary. The record is honest about this: it self-reports model_used: deterministic-local and a rationale of “Deterministic lexical support check.” Nothing on this page is pretending to be a reasoning step.

What you get in return is worth having. It runs with no API key and no provider account. It costs nothing per call and adds no network latency. It returns the same grade for the same inputs every time, so a verification from March can be recomputed in September and checked. And if you do have a judge you trust, pass your own status, confidence, rationale and model_used and the service records yours instead of computing its own.

supported
Ratio ≥ 0.60. The record is written with status approved and truth_state fact.
partially_supported
Ratio ≥ 0.25. Status approved, but truth_state stays hypothesis — the evidence touches the claim without covering it.
unsupported
Below 0.25 with spans attached. Status needs_review, truth_state hypothesis. Somebody has to look.
unverified
No spans were attached at all. Nothing was checked, and the record says so rather than implying a negative result.

GET /v1/provenance/claims/report rolls this up: how many verifications exist, how they are distributed across states, how many evidence references they carry between them, and an evidence-coverage figure — the share of verifications that came back supported or partially supported. Pass a claim_id to narrow it to one claim's history.

Memory Wiki: records in, pages out

Raw records are the right shape for machines and the wrong shape for people. /v1/memory-wiki/pages/compile turns a set of records into one Markdown page — a summary section listing each source, an evidence section listing the record ids behind it — and gives it a path-shaped slug built from the page type and the title.

Compilation is an upsert on that slug, so recompiling a topic replaces the page rather than growing a pile of near-duplicates. The body is hashed into content_hash, the inputs are kept in input_refs, and a freshness_score rides along. Supply your own body if you would rather write the prose yourself; everything else still happens.

While it compiles, it extracts claims. Every substantive line becomes its own record — up to twenty per page — written as needs_review, hypothesis, authority derived, confidence 0.5, with evidence references pointing back at the inputs. The page can then be checked claim by claim rather than as one undifferentiated blob of prose.

Did the compression lose anything?

Every summary is a lossy compression of its sources. The WiCER-style check makes that loss measurable instead of assumed.

  1. State what must survive

    Send preserve_facts — the specific strings the compiled page is not allowed to have dropped. A date, a threshold, a party name, a licence term.

  2. Check the compiled body

    Each fact is looked for in the page as compiled. Coverage is one minus the proportion missing, and the ones that went missing come back by name in missing_facts.

  3. Grade the page

    Coverage of 0.8 or better writes the evaluation as approved and supported. Below that it is needs_review and partially_supported, and the page stops being something you can quietly rely on.

  4. Probe it

    Supply probe_questions, or let the service generate them from the most frequent long words on the page — “What does this page say about …?” — as a reading list for a human reviewer.

POST /v1/memory-wiki/evaluate. The evaluation is itself a record, with the page as its evidence reference, so the history of checks against a page is queryable.

The wiki-wide view

GET /v1/memory-wiki/report answers the maintenance question across every page at once: how many pages and claims exist, how the claims are distributed across verification states, which pages have gone stale — a freshness score under 0.4 — which extracted claims are actually open questions, because they end in a question mark, and which have come back contradicted.

Handing it to a model

GET /v1/memory-wiki/digest exports the compiled set as an llms.txt bundle: every page as a title, a slug, the first 800 characters and the ids of its claims. It is the compact form to paste into a context window or serve to a crawler, and because the claim ids travel with it, anything built on top can still ask what the evidence was.

Ten operations

Nine paths across two API families, with one job between them: never lose the trail back to the source.

EndpointWhat it does
POST /v1/provenance/source-spans Record where a quote came from: source type, source id, URI, character, line and page offsets, the quote itself and free-form metadata.
GET /v1/provenance/source-spans List spans, filtered by source type, source id or a substring query. Up to 500 per call.
POST /v1/provenance/claims/verify Grade a claim against a set of span ids. Returns supported, partially supported, unsupported or unverified, with the ratio as its confidence.
GET /v1/provenance/claims/report Counts by verification state, the number of evidence references, and evidence coverage across every verification — optionally for one claim.
POST /v1/memory-wiki/pages/compile Compile chosen records into a Markdown page with a slug, a content hash, input lineage and one extracted claim record per substantive line.
GET /v1/memory-wiki/pages Search compiled pages by text and page type.
GET /v1/memory-wiki/pages/{id_or_slug} Fetch one page by record id or by its slug, which is path-shaped: topic/grace-period.
POST /v1/memory-wiki/evaluate The WiCER check: assert a list of facts survived compilation, get a coverage score and the list of the ones that did not.
GET /v1/memory-wiki/report Page and claim totals, claim states, stale pages, open questions and contradictions across the wiki.
GET /v1/memory-wiki/digest An llms.txt bundle: every page as a slug, a title, the first 800 characters and its claim ids.

Give your agents a memory you can audit

Run the whole system on your own hardware under the MIT licence, or ask us about hosted access. Both start from the same place.