contradiction-judge
The memory auditor: semantic contradiction detection for AI memory systems.
AI agents accumulate facts about the user over time — "you are 20", "you
love pizza", "you live in Pasadena". When a new memory contradicts an old
one ("you are 21", "you hate pizza"), something is wrong: a stale entry, a
misheard sentence, a bug upstream. contradiction-judge finds those pairs
and suggests how to arbitrate them.
Two detection layers:
- Rule-based (stdlib only): numeric conflicts ("20 years old" vs "21 years old", unit-aware: "240 months old" == "20 years old"), date conflicts ("birthday May 5, 2006" vs "2006-06-01"), factual conflicts (name, location), polarity conflicts ("I love pizza" vs "I hate pizza", "I am a student" vs "I am not a student").
- Pluggable LLM judge hook: register your own judge function
(
set_judge/--hook module:func) for semantic contradictions rules cannot see ("I live with my parents" vs "my apartment lease renews in June"). The hook only runs on pairs the rules did not flag.
Every reported contradiction carries an arbitration suggestion: recency wins when both entries are timestamped; otherwise it is flagged for manual review.
Install
pip install contradiction-judge
Requires Python 3.9+. No dependencies — stdlib only.
Usage
Feed it a JSON file of memory entries:
[
{"id": "m1", "text": "I am 20 years old.", "created_at": "2025-03-01T10:00:00"},
{"id": "m2", "text": "I am 21 years old.", "created_at": "2026-09-15T10:00:00"}
]
contradiction-judge check memory.json
Output is a JSON report on stdout:
{
"entries": 2,
"pairs_checked": 1,
"skipped": [],
"contradictions": [
{
"entry_a": "m1",
"entry_b": "m2",
"kind": "numeric",
"engine": "rules",
"facts": [...],
"explanation": "'I am 20 years old.' vs 'I am 21 years old.': person.age cannot be both 20.0 and 21.0.",
"arbitration": {
"strategy": "recency",
"recommendation": "keep m2, drop or correct m1",
"reason": "Both entries are timestamped; the newer record (m2) is more likely to be current. Verify before deleting."
}
}
]
}
Flags:
--fail— exit 1 when any contradiction is found (CI-friendly).--hook MODULE:FUNC— attach an LLM judge for semantic pairs.
Python API:
from contradiction_judge import check_memories, set_judge
report = check_memories([
{"id": "m1", "text": "I am 20 years old."},
{"id": "m2", "text": "I am 21 years old."},
])
def gpt_judge(text_a, text_b):
# call your model here; return {"contradiction": bool, "explanation": str}
...
set_judge(gpt_judge)
report = check_memories(entries) # semantic pairs also get judged
How it differs from memgovern
memgovern is a governance framework for AI agent memory: it governs where memories come from — provenance tracking, source trust levels, write policies, retention rules. It answers "should this memory be trusted and kept?"
contradiction-judge does one thing memgovern does not: semantic
fact-contradiction detection. Given a set of memory entries — trusted or
not — it audits whether they agree with each other, pinpoints the exact
conflicting pair ("you are 20" vs "you are 21"), and suggests how to
arbitrate it. It answers "do these memories contradict each other, and
which one should win?"
Think of memgovern as the memory system's governor (who may write, what may stay) and contradiction-judge as its auditor (do the records agree). They compose well: govern with memgovern, audit with contradiction-judge.
Roadmap
- Embedding-based topic alignment for preference matching ("pizza" vs "pizzas", "the Bay Area" vs "San Francisco")
- Confidence scores per contradiction
- Auto-fix mode: rewrite the stale entry instead of just flagging it
- Streaming/watch mode for live memory stores
License
MIT. See LICENSE.
Metadata
Release files for contradiction-judge 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| contradiction_judge-0.1.0.tar.gz | 12.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| contradiction_judge-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 24.5 kB
Release files / contradiction_judge-0.1.0.tar.gz
| Download URL | contradiction_judge-0.1.0.tar.gz |
|---|---|
| Size | 12.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ec33820835d831b1575f9225a8778d0505b1eaed73c01677c8c8d63bf14f2428
|
|
BLAKE2b-256 checksum How to use checksums |
34c63abeb27f6ddc1e73fa40a0e2c984723d784e1a9b3a2775d4336ed9a1c8dd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / contradiction_judge-0.1.0-py3-none-any.whl
| Download URL | contradiction_judge-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2ab840c7a2a20ce69774f0672dd30aaa469dcc26953867ee8d5951277431ddf0
|
|
BLAKE2b-256 checksum How to use checksums |
c469e1b833607b1ac030960f63a11ef706a9447084d9692ffb5289e95c3f460b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Security for contradiction-judge 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.