Tensions & contradictions
A tension is a pair of engrams asserting incompatible things: one says “deploys go through Caddy,” the other says “deploys go through nginx.” Memory that contradicts itself is worse than no memory — the agent picks one at random and sounds confident either way. PLUR treats contradictions as first-class records with a lifecycle, not silent data corruption.
Detection
Section titled “Detection”plur tensions --scan (CLI) or plur_tensions with scan: true (MCP) runs the contradiction scan:
- Pre-filter. Candidate pairs are built cheaply through three stages: scope partition (no scope overlap → skip), domain filter (domain hierarchies don’t touch → skip), and subject overlap (subject noun phrases don’t intersect → skip). Survivors are ranked by shared-token overlap, so the likeliest contradictions are judged first under the pair cap.
- LLM judge. Each surviving pair is judged for genuine contradiction (default: confidence ≥ 0.7, max 50 pairs per scan). Scan mode requires an LLM —
OPENAI_API_KEYorOPENROUTER_API_KEY, or an explicit endpoint. - Persist. New detections become tension records (
T-YYYY-MMDD-NNN). Already-recorded pairs are never re-judged.
The judge is date-aware: both statements’ recorded dates go into the prompt, because “the deploy was green on Monday” and “the deploy was red on Friday” is an event log, not a contradiction. Snapshot-domain pairs and engrams whose validity window has closed are gated out before judging.
Updates are not contradictions
Section titled “Updates are not contradictions”When knowledge legitimately changes, say so: plur_learn with supersedes: ["ENG-..."] (CLI: plur learn --supersedes). Supersedes-linked pairs are skipped by tension scans in both directions — an intentional update is a replacement, not a conflict. Reserve tensions for the case where you didn’t know the store disagreed with itself.
Lifecycle
Section titled “Lifecycle”Shipped in 0.11.0. Every detection starts as detected and moves through explicit review:
| Action | Effect |
|---|---|
confirm | Marks the tension as a real conflict, pending resolution. |
dismiss | False positive — the pair is suppressed from all future scans. |
resolve + --winner <engram-id> | The winner is kept; the losing engram is retired. |
plur tensions # list unresolved recordsplur tensions --scan # detect new onesplur tensions resolve T-2026-0703-001 --winner ENG-2026-0630-004Injection-time warnings
Section titled “Injection-time warnings”Unresolved tensions follow the engrams they touch: when injection selects an engram that is party to an unresolved tension, the inject result carries a warning. Contradicted context is flagged, never silently injected — the agent can hedge or ask instead of confidently asserting one side.
- MCP:
plur_tensions(list / scan / confirm / dismiss / resolve),plur_tensions_purge(clear legacy unvalidated conflict edges left by old importers). - CLI:
plur tensions --scanand lifecycle subcommands, plusplur audit— which checks a runtime’s working memory (e.g. Claude Code auto-memory files) against the engram store and flags conflicts there too.
Next: Activation & decay →