Neither happens automatically. On write, invalidate_thought() closes a fact's valid-time window, and it's documented as doing no similarity search and no inference of any kind - your code has to call it, the store never notices on its own that a new fact conflicts with an old one. Retrieval doesn't flag it either. Hybrid search ranks by keyword, vector similarity, recency, priority and graph signals - nothing in there compares two results against each other for agreement. If both facts are still valid-time-live, both can come back with no signal marking them as conflicting. There's one adjacent thing, narrower than it sounds: the deterministic consolidation pass has a gate that skips building a summary over a cluster whose members look internally contradictory, but it's a small English sentiment lexicon (stopped/started, hate/love, can't/can) - a location change like Berlin to Lisbon wouldn't trip it, and it only decides whether a synthesized memory gets built, not what the raw facts return on a normal search. So it's the caller's call, both times. Is anyone doing this well without a model in the loop, or is that the honest floor right now?
