Receipts
Every read has a receipt.
Anjo will not tell you something about yourself that it cannot date. Every person, pattern, contradiction and change it holds carries the moment it came from — and you can press “not me” on any of it.
The unit
A receipt is three fields.
Anjo keeps a structured model of you — the people you talk about, the patterns it thinks it sees, the places your stated values and your described behaviour pull apart. Nothing enters that model as a free-floating assertion. Each element carries the moment it came from.
Receipt( summary # what was actually said or done observed_at # when, to the second, in UTC source_session_id # which conversation it came from )
This is not a display convention layered on at the end. It is the type the model is built out of, so an observation without provenance is not a lower-quality observation — it is one that cannot be constructed.
anjo/core/user_model.pyCoverage
What carries one.
| In your model | Holds | Example from the code |
|---|---|---|
| People | Relationship, sentiment, themes, mention counts, first and last mentioned | “mother” · “complicated” · guilt |
| Patterns | Recurring behaviour with an evidence count and confidence | “deflects when career comes up” |
| Contradictions | What you have stated set beside what has been observed | “says they want independence” / “keeps returning to a controlling relationship” |
| Growth edges | A movement from stuck to exploring to progressing | “setting boundaries with family” |
| Shifts | An old value, a new value, the date, and the receipt | “how they hold Mom” |
A contradiction is the sharpest thing in that list, and the one a validation engine would never keep. It is kept here because the point of the model is not to agree with you.
The correction loop
It is built to be corrected.
Anjo can be wrong about you, and it is designed on that assumption. When you tell it that a read is wrong, the correction is weighted more heavily than agreement — deliberately, and by a factor of two.
CONF_REINFORCE = 0.15 # another session showed it again CONF_ACCEPT = 0.15 # you said it resonates CONF_REJECT = 0.30 # you said "not me" — the loudest signal CONF_SURFACE_FLOOR = 0.20 # below this, it is not shown at all
There is a second honesty rule underneath. The function that records your feedback returns success only when the model actually changed as a result — so the app can never show you a confirmation for a correction that went nowhere.
anjo/core/user_model.py · anjo/core/mirror.pyWhere you see it
Receipts are user-facing, not internal.
Reflection cards
Observations arrive in chat one at a time, with a plain-language “how I know this” beside each and a “not me” you can press. Your Inner World →
Provenance chips
Replies can name the memory pages they drew on, so you can open the source instead of trusting the sentence.
Your data, correctable
Inner World pages are editable, any observation can be rejected with “not me,” and you can export your data or erase everything Anjo holds with one control.
FAQ
Quick answers
What is a receipt in Anjo?
A receipt is the provenance record attached to everything Anjo believes about you: a short summary of what was actually said or done, the UTC timestamp it was observed at, and the ID of the conversation it came from. Every person, pattern, contradiction, growth edge and change in your model carries one, so any observation can be traced back to a real dated moment.
Can Anjo tell me something about myself with no evidence behind it?
No. Observations are selected from structured evidence before any language model phrases them, and anything below a 0.20 confidence floor is withheld rather than shown. When there is not enough evidence yet, Anjo says the read is still forming rather than inventing one.
What happens when Anjo is wrong about me?
You mark the observation as “not me.” That lowers its confidence by 0.30 and suppresses it — twice the weight of agreeing with an observation, which moves it 0.15. The API that records your feedback reports success only when the underlying model actually changed, so you are never shown a confirmation for a correction that had no effect.
Why does rejection count for more than agreement?
Because agreement is cheap and easy to elicit, and a system that treats the two equally will drift toward telling you what you want to hear. Weighting rejection twice as heavily makes disagreement the strongest signal in the loop and keeps the model correctable over time.
Does Anjo send my conversations to build these observations?
The observations shown to you are assembled only from structured, abstracted fields of your model and your stored facts. Raw conversation transcripts never pass through that path. Your chat history is stored encrypted at rest, and no human at Anjo can access your conversations by default.