Skip to content

Standalone conflict detection for propositions #12

@jimador

Description

@jimador

Observation

PropositionReviser classifies incoming propositions as CONTRADICTORY when they conflict with existing ones, but this is part of the revision pipeline — it requires the full LLM classification flow and produces a RevisionResult. There's no way to ask "does this proposition conflict with existing knowledge?" outside of revision.

Use cases that need conflict detection without full revision:

  • Pre-persistence validation — check before committing
  • Real-time monitoring — detect contradictions in a conversation stream without modifying the repository
  • Batch auditing — scan existing propositions for internal contradictions
  • Domain-specific rules — some applications need lexical/structural conflict checks (negation detection) alongside semantic ones, with different performance/cost tradeoffs

Additionally, PropositionReviser.classify() treats all conflicts as binary (CONTRADICTORY or not). Real-world conflicts have nuance — a "revision" (updating a fact) differs from a "contradiction" (asserting the opposite), which differs from "world progression" (the situation changed, not an error).

What DICE already has

  • PropositionReviserclassify() returns ClassifiedProposition with PropositionRelation.CONTRADICTORY, but it's coupled to the revision pipeline
  • PropositionRelation enum — IDENTICAL, SIMILAR, UNRELATED, CONTRADICTORY, GENERALIZES
  • RevisionResult.Contradicted — stores both original and new proposition
  • PropositionRepository.findSimilar() — vector similarity search that could identify candidates for conflict checking

The question

Should conflict detection be separable from revision?

Some possibilities:

  1. Extract from PropositionReviser — make classify() usable standalone. It's already an interface method, but it returns ClassifiedProposition tied to the revision model. Could be sufficient if the only need is "check for conflicts before revising."

  2. ConflictDetector SPI — a separate interface for conflict-only checks:

    interface ConflictDetector {
        fun detect(text: String, candidates: List<Proposition>): List<ConflictResult>
    }

    With implementations ranging from cheap (negation keyword detection + text overlap) to expensive (LLM semantic analysis). A composite detector could chain cheap-then-expensive.

  3. Richer conflict types — extend PropositionRelation or introduce a ConflictType that distinguishes contradiction, revision, and world progression. This would benefit PropositionReviser too.

  4. Detection quality tracking — when LLM-based detection fails (parse error, timeout), signal degraded quality rather than silently returning no conflicts. Consumers can route degraded results to human review.

Open questions

  • Is separating detection from revision worth the API surface? If most consumers run conflict detection as part of revision anyway, a standalone SPI may be overhead.
  • How reliable is negation-based detection? Cheap lexical checks ("not", "never", "no longer") catch obvious contradictions but miss semantic ones ("the door is locked" vs. "you can walk through the door").
  • Should conflict resolution be part of this? Detection tells you that a conflict exists. Resolution tells you what to do about it. These could be separate SPIs or combined.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions