0009: Uniqueness Coexists with Contestation
Date: 2026-06-28
Status
Section titled “Status”Accepted — implemented. The reload-time uniqueness validator and the dent8 contradict verb both treat an explicitly contested set as a single flagged conflict, not
a uniqueness violation.
Context
Section titled “Context”The coding-agent predicate registry marks facts like repo.database unique: at most
one believed fact per subject+predicate (registry).
Independently, dent8’s belief-revision identity is paraconsistent: a fact.contradicted
moves the incumbent to Contested and preserves both the fact and its
contradicted_by edge — “localize the contradiction, keep the store non-trivial, surface
it” (ADR 0005, belief-revision.md).
These collide. The sanctioned way to flag a conflict — dent8 contradict — asserts an
opposing fact and contests the incumbent, leaving two believed facts (the Contested
incumbent and its Active contradictor) for one unique subject+predicate. A naïve
uniqueness rule (“at most one believed fact, full stop”) would either forbid contradiction
entirely or reject a legitimately-contested log on reload (the same false-positive class as
the ADR 0008 SupersededByInvalidated regression).
Decision
Section titled “Decision”Uniqueness is over mutually-consistent believed facts, and contestation is the explicit exception. Concretely:
- A unique predicate is violated only when more than one fresh believed fact exists
and none of them is
Contested— i.e. a silent duplication, the corruption the invariant exists to catch. - When at least one believed fact is
Contested, the set is a surfaced conflict, not a violation. The firewall has done its job (the disagreement is visible and auditable); resolving it is a separate, deliberate act (supersedeinstalls a winner;retractremoves one side). - Contradiction is dissent, so it is not authority-gated (a low-authority source may
contest a high-authority fact), with the one exception that a contradiction against a
Canonicalfact is a hard alarm, not a soft contest (ADR 0007). This is the deliberate asymmetry: dissent (contradict) is cheap; override (supersede) and removal (retract) must out-rank the incumbent.
Consequences
Section titled “Consequences”Positive:
dent8 contradictis runnable without weakening uniqueness: a low-privilege actor can flag a wrong fact (forcing itContested) but still cannot override or delete it — completing the assert / supersede / retract / contradict surface.- The reload validator stays sound: silent duplication is still rejected; a flagged contestation reloads cleanly.
Negative:
- “At least one
Contested” is a coarse exemption: it permits a believed set larger than two if multiple contradictors pile on. That is acceptable (every member is an audited part of the surfaced conflict) but means uniqueness no longer implies “≤2 believed”. - A plain
assertinto a contested predicate is still blocked by registry uniqueness (the believed set is non-empty); the user must resolve the contest (supersede/retract) first. This is intended — you do not silently add a third opinion.
Follow-Up
Section titled “Follow-Up”- [DONE]
dent8 contradict(asserts the opposing fact + aContradictedevent on the incumbent, atomically; aCanonicalincumbent hard-alarms). - [DONE]
validate_unique_logexempts a set containing aContestedfact. - Future: a
dent8 resolveshortcut (supersede that also clears the contest), and surfacing the full contradictor list inexplainrather than just a count. - Grounded in ADR 0005 (paraconsistent contested state) and ADR 0007 (dissent is not authority-gated; canonical is the exception).