Contradiction Engine
method · geometry/householder/v2
One detector, version-stamped
The firm previously combined six contradiction heuristics (language, argument-shape, probability, geometry, compression, LLM-rationality) and voted across their outputs. The founder ruled that engine “really bad, don't make sense.” This page describes its replacement: one canonical method, lifted directly from the QH benchmark and the Householder-ablation work. New detections carry a detection method string so future benchmark rolls can cut a new version without invalidating prior rows.
How it works
- Resolve embeddings. Both principles are embedded under the family the benchmark selected (sentence-transformers; cached). Stored embeddings are used when present.
- Estimate the contradiction direction. An uncentered local PCA over held-out contradicting exemplar pairs produces a unit vector d̂ — the direction in which contradictions concentrate.
- Reflect across the hyperplane. A Householder reflection of b through the plane perpendicular to d̂:
b' = b − 2(b · d̂) d̂. - Score sparsity. The Hoyer sparsity of
b' − ais the raw contradiction signal. High sparsity = the disagreement concentrates in few dimensions = contradiction. Low sparsity = the disagreement is diffuse = independence or coherence. - Calibrate. The raw signal is mapped through the QH-v1 reliability bins to a calibrated probability with a two-sided confidence band. Bands match actual reliability to within ± 0.10, verified by a benchmark integration test.
- Explain (geometry detects, language explains). When the score exceeds the threshold the engine asks a brief Haiku call to name the axis of disagreement and quote verbatim fragments from both texts. If the LLM cannot ground its explanation, the axis falls back to a geometric label and the human explanation is null. The engine never auto-resolves a contradiction — resolution is source-driven (prompt 08).
Benchmark numbers (cross-model study)
Pulled from the frozen Cross-Model Geometry Study. The leaderboard is the source of truth; this page mirrors a slice for context.
| Model | Runner | Accuracy | AUROC | ECE |
|---|---|---|---|---|
st:BAAI/bge-large-en-v1.5 | contradiction_geometry | 0.4096 | 0.5641 | 0.2586 |
st:sentence-transformers/all-MiniLM-L6-v2 | contradiction_geometry | 0.3951 | 0.6093 | 0.2513 |
hash-det:qh-cross-v1 | contradiction_geometry | 0.2877 | 0.6101 | 0.3120 |
Companion: Householder Reflection Ablation — recommendation KEEP-WITH-FURTHER-WORK, which is why the reflection step ships here as canonical pending a powered re-run.
The reflection ablation, in full
The reflection step is the engine's most distinctive claim — that contradicting claims live in a learned reflection direction in embedding space. It is also the step most likely to be inherited from an earlier prototype rather than carrying its own weight. The firm ran an ablation study to answer that honestly, against the same frozen QH-v1 benchmark the public leaderboard runs on.
Five variants were compared: the production pipeline (control), the same pipeline with the reflection skipped, the same pipeline with the learned direction replaced by a random unit vector, an asymmetric variant that reflects only the antagonistic half (cosine < 0), and a variant that scores the reflected raw embedding rather than the difference vector. Per-item correctness was compared via paired McNemar, a bootstrap confidence interval on the accuracy delta with a Cohen's h effect size, and a score-shift analysis; the recommendation is then derived from those numbers by an explicit rule.
Finding (QH-v1, hash-det embedder): the ablation is a structural null — the frozen v1 sparsity threshold is saturated, so every variant constant-predicts the same label and the label-level test has zero power to confirm or refute the reflection step. Recommendation: KEEP-WITH-FURTHER-WORK — the production path is left unchanged pending a powered re-run on embedders whose sparsity range straddles the threshold.
Numbers in the PDF are regenerated from the run-stamped results.json on every run; no number is hand-edited. The recommendation is signed by an author identifier and is a conclusion the firm publishes. A REMOVE recommendation would not itself change production code — it would file a follow-up prompt for founder consideration with a full review trail. This research output is not a refactor.
Worked example
Equity returns are driven primarily by the discount rate; cash-flow news is secondary.
Equity returns are driven primarily by cash-flow news; the discount rate is a residual.
- Raw Hoyer sparsity of b' − a: 0.78
- Calibrated contradiction score: 0.74 (above the 0.65 threshold)
- Axis: causal direction
- Explanation: Principle A locates the dominant cause in 'discount rate' while principle B locates it in 'cash-flow news' — the two reverse the causal hierarchy.
What the engine does NOT do
- It does not vote across multiple heuristics. One method ships; the six legacy heuristics are demoted to a compat shim and slated for removal in prompt 16.
- It does not auto-resolve a contradiction. Resolution is source-driven (prompt 08).
- It does not invent disagreements. If the explainer LLM cannot quote verbatim fragments from both principles, the human explanation is left null and the row surfaces with only the geometric axis label.
We don't test every pair
The detector above is O(N²) if you naïvely test every new principle against every old one. We don't. A cluster index sits between the principle add event and the engine and decides which pairs get the engine's CPU-seconds. The engine remains the source of truth for the verdict; the index just scopes its work.
The geometry of pair selection:
- Same cluster. Principles whose embeddings are close (cosine ≥
0.72) live in the same “domain of applicability.” A new principle is tested against every other principle in its cluster first — this is where the yield per CPU-second is highest. - Neighboring clusters. We sample
5%of the principles in the top-3 nearest other clusters. These are the principles whose disagreement is plausible by adjacency but not by direct similarity. - Distant clusters. We sample
1%of the principles in far clusters as a surprise check. The founder's caveat is authoritative here: “language is not ideas, but it tracks for semantic.” The rare cross-domain contradiction the embedding space can't see is what this rail exists to catch. Setting either cross-cluster fraction to zero is a config error — the engine refuses to start.
The full topology — counts, sizes, burndown, intra-vs-cross disposition — is on the operator cost monitor. A nightly k-means resweep over all principle embeddings checks whether the incremental assignment has drifted from the global structure; if drift > 0.15, the operator sees a ClusterReindexProposaland accepts or rejects it explicitly. The index is versioned, so a replay query can answer “which cluster was principle X in on date Y?”
Disputes feed calibration
Operators can DISPUTE a contradiction from the queue. Each dispute logs the detection method version; when the same version accumulates disputes past a threshold the calibration review is triggered. That review is what licenses cutting a new method version (e.g. geometry/householder/v3) — never a silent threshold tweak.
Lifecycle of a contradiction
We removed the “Resolve” button. Contradictions are resolved only by the sources themselves. A contradiction in this firm is a first-class entity — once detected, it stands until new evidence shifts it. The database becomes a faithful crystallisation of what the sources jointly imply, not a curated narrative.
Each contradiction occupies one of six states. Transitions are append-only — earlier entries on the event log are never overwritten — and every transition records the triggering source, the score change, and a rationale.
- DETECTED — the engine flagged the pair. Awaits acknowledgement or further evidence.
- STANDING — the founder confirms the contradiction is genuine; the firm holds both positions until evidence accumulates. This is not a resolution.
- WEAKENED — a new principle scores significantly closer to one side than the other; the contradiction is shifted but not yet closed.
- RESOLVED_BY_SOURCE — a new principle aligns strongly with one side (calibrated score ≤ 0.30) and contradicts the other (≥ 0.65). The contradiction is resolved in favor of the low-scoring side. This is reversible: if the supporting source is revoked, the lifecycle falls back to STANDING.
- DISPUTED_AS_ERROR (terminal) — the founder believes the engine got it wrong. The dispute feeds calibration review for that method version.
- SUBSUMED_BY_SYNTHESIS (terminal) — the synthesis engine produced a principle that supersedes both sides; the founder explicitly confirmed it from the subsumption triage queue. The agent never auto-applies this transition.
The auto-resolver runs on every principle add and revoke. It iterates standing contradictions whose sides share a cluster with the new principle and applies the rule above. A single dispute never auto-retires a detection method — disputes are calibration signal, not a kill switch.