Case Study: Contradiction Detection and Hypothesis Sandboxing
Problem: A knowledge graph can accumulate logically inconsistent statements — for example, the same source–target pair might be linked by both confirms and refutes relations, or a planet might be asserted to orbit two different stars. Standard structural and even type‑level validation passes such graphs without complaint, because every individual edge looks well‑formed. The contradiction only becomes visible when multiple relations are read together.
CKS solution: The new mutual_exclusion and functional_relation extension constraints (introduced in cks-core 1.13.0) let a graph declare what counts as a contradiction, and the detect_contradictions tool surfaces those violations in a compact, machine‑readable form. The fork_sandbox tool provides an isolated “what‑if” branch — apply a hypothesis, see the diff, and keep or discard the result — without ever touching the parent session. Together with the existing suggest_evolution preview mode, these tools give LLMs a full explore–detect–fix–validate loop inside a single conversation.
Scenario
We built a small scientific graph about the exoplanet candidate Kepler‑22b:
- Kepler‑22b (Planet) orbits Kepler‑22 (Star).
- Two ConfirmationReport objects represent independent analyses of the planet.
- A
MutualExclusionRuledeclares thatconfirmsandrefutesare mutually exclusive — a planet cannot be both confirmed and refuted by the same report. - Deliberately, we added both a
confirmsand arefutesrelation from Kepler‑22b to each report, creating exactly the kind of joint nonsense the rule exists to catch.
We then used the new tools to detect the contradictions, fix one in a sandbox, preview an unrelated evolution, and verify that the parent session remained untouched.
Tools Used
validate_knowledge— initial session creationevolve_knowledge— graph constructiondetect_contradictions— surface mutual‑exclusion and functional‑relation violationsfork_sandbox— isolated branch with hypothesis + diff from fork pointsuggest_evolution(preview mode) — dry‑run candidate operationsclose_session— discard the sandbox
What Happened
1. Contradiction detection — mutual exclusion
With the MutualExclusionRule in place, calling detect_contradictions on the session returned:
{
"contradiction_count": 2,
"contradictions": [
{
"code": "CKS-EXT-MUTUAL-EXCLUSION",
"severity": "error",
"message": "Relation '…' (type 'confirms') and relation '…' (type 'refutes') both connect 'kepler-22b' to 'report-A', but a MutualExclusionRule declares these relation_types mutually exclusive."
},
{
"code": "CKS-EXT-MUTUAL-EXCLUSION",
"severity": "error",
"message": "… same for report-B …"
}
]
}
Two contradictions — one per report — exactly as expected.
2. Contradiction detection — functional relation
A separate test with a FunctionalRelationRule for orbits and two orbits edges from Earth to different stars also returned:
{
"contradiction_count": 1,
"contradictions": [
{
"code": "CKS-EXT-FUNCTIONAL-RELATION",
"severity": "error",
"message": "Source 'earth' has 2 distinct targets via functional relation_type 'orbits' …"
}
]
}
3. Sandbox fix with fork_sandbox
We asked fork_sandbox to create a branch and remove the refutes relation to report‑A:
{
"sandbox_session_id": "d42dcc57-…",
"operations_applied": 1,
"diff_from_fork_point": {
"summary": {"added_objects": 0, "removed_objects": 0, "added_relations": 0, "removed_relations": 1},
"operations": [{"type": "remove_relation", "relation_id": "rel-refutes-1"}]
},
"message": "Sandbox session '…' is an isolated fork … nothing here affects the parent."
}
Re‑running detect_contradictions inside the sandbox showed 1 contradiction (report‑B still conflicted), while the parent session still reported 2 — proving full isolation.
4. Preview mode with suggest_evolution
Passing a candidate operation list (add a moon “Kepler‑22b‑I” + an orbits relation) to suggest_evolution in preview mode returned:
{
"would_apply": true,
"operations_previewed": 2
}
No version was created — the preview mode validated the structure without committing anything.
5. Error handling in the sandbox
When we attempted to add a duplicate object ID inside a sandbox, the tool immediately returned:
{
"error": "evolution_failed",
"message": "Hypothesis could not be applied: Object 'obj-1' already exists."
}
The sandbox was automatically discarded, leaving the parent session untouched.
6. Ontology validation still works alongside contradictions
As a regression check, we validated a graph where Earth orbits Pasta (type Food) with type_hierarchy and relation_type extensions enabled. The system correctly returned valid: false with diagnostic code CKS-EXT-RELATION-TYPE, confirming that the new contradiction layer composes cleanly with the existing ontology layer.
Key Takeaways
- Contradictions are explicit, not guessed.
MutualExclusionRuleandFunctionalRelationRuleobjects define what counts as a contradiction, so the system never flags something the domain expert didn't declare. - Sandboxes are safe by construction.
fork_sandboxnever mutates the parent; a failed hypothesis automatically discards the branch. - Preview saves versions.
suggest_evolutionin preview mode validates candidate operations without committing — no wasted versions or sessions. - Isolation is guaranteed. The parent session's contradiction count did not change while the sandbox fixed its copy.
- Composability. Contradiction detection works alongside the existing ontology, provenance, and structural validators — all opt‑in, all additive.
Reproduce It Yourself
- Install
cks‑mcp(v1.12.1+) and connect it to Claude Desktop. - Start a chat and say:
Use cks‑mcp to build a small graph about an exoplanet candidate.
Include a MutualExclusionRule that declares “confirms” and “refutes” as mutually exclusive.
Link the planet to two ConfirmationReport objects using both relation types, then calldetect_contradictionsand show me the result.
Next,fork_sandboxto remove one conflicting relation and prove the parent session is untouched.
Finally, preview adding a new moon withsuggest_evolution.
- Observe the contradiction count drop in the sandbox, the isolation from the parent, and the preview response — all without writing a single line of code.