A contract you can verify, not a promise to believe.
Every question the archive answers, refuses, or scrubs is logged with its diagnostics. The five checks below run between a question and an answer, and any of them can fail the whole reply.
Five checks. Any one of them can stop the answer.
Retrieval before model.
The question is matched against the archive's index first. The language model isn't invoked until retrieval has found something to point at. If the archive is empty on a topic, the model is never asked.
A floor, not a hope.
An answer grounds on either a strong vector match or a literal overlap with the question. Either alone misses too much.
Every citation, checked.
Each claim in a streamed answer must point at a capture that retrieval actually returned. A citation outside that set fails the entire answer. There is no partial salvage.
No first person.
Any answer that says I or my outside a quote fails. The system describes what the creator said. It does not become the person who said it.
One refusal sentence.
When the contract fails, the answer collapses to one line, the same one every time: "I don't have that in the archive. Try asking another way?" No graceful filler. No suggested alternatives the system cannot back up.
From a sentence to a citation.
What runs, where, and why.
The model gets the words. Never the people.
The retrieval and synthesis prompts include only the capture's text and the date it was captured. No names. No nominee list. No life events. No anchor dates. No biography. The model has the words, never the social graph around them.
Face recognition runs entirely in the browser. The descriptors never leave the device. When a face match later changes, every photo's caption is quietly re-rendered without the wrong name.
The whole thing is open under Apache 2.0.
You don't have to take our word for any of this. The contract is short, the code is public, and the design choices behind it are written out plainly.
