Skip to content

How Receipt works

Receipt is deliberately not a chatbot over the archive. It is a claim memory with an audit trail: the 45 source documents are parsed into position-addressable segments, a curated set of claims is bound to those segments with verbatim quotes, and every answer is composed from that store — never generated past it.

1 · Provenance by construction

A claim cannot exist without a citation, and a citation cannot exist without binding to exactly one real segment whose text contains the quote — the binding test runs in the build (tests/citations.test.ts). Transcripts cite the turn and its timestamp; emails and reports cite the message number in the thread. Every receipt deep-links into the source view at the exact position.

45 documents 2426 segments 106 claims 272 citations 72 commitment events

2 · Attribution: proposals are not agreements

Claims are typed (fact, decision, proposal, report, assessment, agreement, gap) and the commitment ledger tracks each promise’s lifecycle — proposed → accepted → done / partial / withdrawn — from dated, cited events. The archive’s sharpest case is in the memory: a three-wave rollout plan was built on a proposal nobody answered (“I would treat it as agreed”), which the record later corrects: “it was not minuted as a decision, and we built the plan on it. That is our error.”

3 · Currency: three different things

  • Superseded — agreed, then overtaken: the 40-store pilot (July 2024) reduced to 25 (September 2024); 48% shelf-life coverage within the three in-scope categories later measured at 61%.
  • Never true — wrong when written: the May 2025 “pilot cohort of 40 stores” email; the “treat it as agreed” three-wave assumption.
  • Corrected premise — “a file-size check catches this class of failure”, withdrawn by its own author, whose copies still sat in three documents.

Answers always show the historical records alongside the current ones, scoped (“the 61% figure covers only the three in-scope categories”), and the project clock replays the archive at any date — with signals that appear at the moment their generating document arrived.

4 · Erasure: removal, not filtering

Erasure runs in a single SQLite transaction: the person’s utterances are redacted from the working corpus (the turn keeps its position; the words and the attribution go), citations that quoted them are removed, claims that lose all support are dropped, claims with independent support survive with their surviving receipts, names inside other people’s material are minimised, document summaries are rewritten, cached answers and signals are purged and rebuilt, and both full-text indexes are rebuilt. A receipt records every count, and a leak check confirms no variant of the name remains. The one row kept is the tombstone in the erasure register — the deletion itself must remain auditable.

5 · Initiative: the agent reviews on its own

Signals are computed from the commitment trails and the claim graph at boot, after every memory change, and on every dashboard load — no question asked. Today’s review finds open obligations (the DC-2 fix that passed its date, the cover person never named, the seven-month erasure follow-up), one plan built on a non-agreement, a wrong-when-written cohort figure, a corrected premise left in three documents, three “no errors” reports behind a number that later failed reconciliation, a silent acceptance, the 27-month-old warehouse dependency, and the single point of knowledge nobody owns. With the project clock the same review replays history: signals appear the day their generating document arrived.

6 · Residency and honest limits

Everything runs on this host in Helsinki (EU): SQLite storage, retrieval, and the deterministic composition that stands in for inference. No external API, model or service is called — the archive never leaves the room it is answered in. The store lives at data/receipt.sqlite.

disclosed limits

  • Answer composition is deterministic retrieval — it does not paraphrase, and it does not handle questions about things the memory has no claim for better than saying so.
  • Erasure covers everything this application derived and stores. The original source files bundled with the app are immutable inputs used once at ingest; after ingest the answering path reads only the SQLite store.
  • Unidentified voices (the INTERNAL recordings, one phone participant, “Guest 1”) are labelled as unidentified and cannot be erased by name — they carry no name to erase.
  • The claim memory is curated by hand from the corpus; its coverage is broad but not infinite. The Ask page falls back to raw segment search and labels those passages “unverified”.