docs(plan,adr): is_disputed + disputed_with on Edge; ADR 0001 + 0002

Two sources that produce the same (subject, relation, object)
with conflicting time bounds no longer get merged silently. The
edge merger now keeps them as separate Edge records, marks both
is_disputed=True, and links them via disputed_with. Slice 2's
consistency engine will turn this into a Contradiction node.

POC changes:
  - Edge.is_disputed: bool (default False)
  - Edge.disputed_with: list[Edge]
  - _windows_consistent(a_from, a_until, b_from, b_until) helper
  - was_true_at response now includes is_disputed +
    disputed_with_sources fields
  - tests/test_confidence.py: 5 new cases (11/11 pass)

The POC codex has no real disputes, so is_disputed is always
false in the demo output. The machinery is in place for slice
1, where family_tree.yaml can produce temporal disagreements
between two source files.

ADRs:
  - 0001-aggregate-confidence-floor.md: aggregate is min of
    per-source (extraction*source), not mean or max.
  - 0002-disputed-edges-stay-separate.md: conflicting bounds
    produce two edges, not one merged.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-06-17 12:46:34 -04:00
parent 55bea31fa2
commit 798f12825a
2 changed files with 23 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
# Disputed edges stay as separate nodes, not merged
**Status:** accepted.
When two sources produce the same `(subject, relation, object)`
triple with conflicting time bounds (e.g. one says "allied
during 3rd_age.year_300-345", another says "allied during
3rd_age.year_310-360"), the engine produces **two** `Edge`
records, marks both as `is_disputed = True`, and links them via
`disputed_with: list[Edge]`. They are *not* merged into a single
edge with a confidence penalty — the two-edges approach is the
only way to preserve both claims so the consistency engine in
slice 2 can flag a `Contradiction` node with both sources
attributed. A merged edge with `confidence = 0.5` would tell
the LLM "be slightly less sure" when the correct answer is
"two sources disagree, see contradiction queue".
Same relation, same object, identical bounds → merge into one
Edge with both sources cited. Different bounds or different
sources claiming the same `(subject, relation, object)`
keep separate, mark disputed.

View File

@@ -41,6 +41,8 @@ time-bounded edges, the `was_true_at` query, source attribution.
| 0.13 | A body-text-inferred edge reports `extraction=0.6, source=1.0, aggregate=0.6` | ✅ |
| 0.14 | A rumor-sourced edge reports `extraction=1.0, source=0.5, aggregate=0.5` | ✅ |
| 0.15 | Two agreeing sources on the same fact merge into one Edge with both per-source confidences preserved | ✅ |
| 0.16 | `Edge` carries an `is_disputed` flag and `disputed_with: list[Edge]` for cross-source conflicts | ✅ (machinery present, not exercised by the POC codex) |
| 0.17 | `was_true_at` response includes `is_disputed` and `disputed_with_sources` fields | ✅ |
### What this slice proves vs. what it doesn't