Skip to content

Research agent P1: N-source corroboration + contradiction surfacing + KB promotion gate #12623

Closed

Description

@mrveiss

Part of #12621 (Phase 1 — precision layer + quarantine release).

Goal

Add multi-source corroboration so facts earn confidence, surface disagreement instead of hiding it, and promote corroborated facts from the quarantined research collection into the general KB.

Scope

Extend services/claim_verifier.py (do not fork): upgrade the current 2-source arbitration (ClaimVerifier.verify, claim_verifier.py:365) to N-independent-source verification.

  • Gather ≥K independent sources for each material claim (materiality tag comes from synthesis; verify only asserted claims — cost control).
  • Agreement → raise fact confidence (function of independent-source count + independence).
  • Disagreement → create a contradicts Relation (fact↔fact) and set the fact's verification / requires_human_review field (reuse existing flag).
  • Add a refutation prompt ("what evidence would contradict this?") — port the pattern the deep-research skill already uses.

Promotion gate: facts in the research collection that reach the corroboration/confidence threshold are promoted (moved/copied) into the general KB collection so chat/RAG can see them. Below threshold → stay quarantined. Never assert single-source claims as verified.

Acceptance criteria

  • A material claim with ≥K agreeing independent sources gets raised confidence + is promoted to the general KB collection.
  • Conflicting sources produce a contradicts relation + requires_human_review, and the claim is NOT promoted.
  • /research response confidence/contradictions[] reflects the corroboration outcome.
  • Single-source claims are never marked verified.
  • Unit tests for agreement / disagreement / below-threshold paths; integration test asserting promotion visibility in RAG.

Depends on

Phase 0 (#12622) — facts + research collection must exist.

Activity

  1. mrveiss commented on Jul 30, 2026

    @mrveiss
    OwnerAuthor

    Opened PR #13011 implementing N-source corroboration + contradiction surfacing + KB promotion gate. See PR body for premise verification (deep-research skill pattern doesn't exist as described; ported the real refutation-prompt pattern from agent_loop/pre_action_verifier.py instead), what was built, and quarantine-boundary proof.

  2. github-actions commented on Jul 30, 2026

    @github-actions
    Contributor

    PR #13011 (merged to Dev_new_gui) references this issue with a close keyword.

    feat(research): N-source corroboration + contradiction surfacing + KB promotion gate (#12623)

    If this issue is fully resolved, close it manually. If work remains, no action is needed.

  3. mrveiss commented on Jul 30, 2026

    @mrveiss
    OwnerAuthor

    Closed by PR #13011, merged to Dev_new_gui as 1db2568e5.

    Delivered: N-source corroboration extending ClaimVerifier in place (not forked) — SourceAgreement, CorroborationResult, corroborate(), classify_agreement(); contradiction surfacing as contradicts fact↔fact relations; and the promotion gate releasing corroborated facts from the research quarantine collection into general KB visibility. Seven tunables (K threshold, confidence-formula parameters, promotion threshold, collection name, search top-k, classify timeout) are env-sourced ssot_config constants, not literals.

    A latent defect made this feature a no-op, and was caught only by probing the mechanism. knowledge/facts.py::update_fact() synced ChromaDB only when content also changed. Promotion is by definition a metadata-only update — so every promotion would have been written to Redis and never reached the vector store. The gate would have reported success while promoting nothing, and no test at the time would have failed. Fixed in-scope via _sync_fact_metadata_in_chromadb, with knowledge/facts_metadata_sync_test.py driving the real production path rather than a mock.

    Two of this issue's own pointers were wrong:

    1. The instruction to port the refutation prompt from "the deep-research skill" — no such skill has prompt logic. skills/builtin/research/SKILL.md is an unrelated slash-command skill, and onboarding/presets.py's "deep-research" entry is a starter-preset system-prompt string. The genuine adversarial-refutation pattern lives in agent_loop/pre_action_verifier.py (structured response, low temperature, fail-open); ported that, applied to claim-vs-source instead of action-vs-safety.
    2. requires_human_review existed as a result-object field (VerifiedClaim, ConflictResolutionResult, GroundedResponse, LLC review_gate) but had never been fact metadata. Reused the name for the new fact-level flag rather than inventing a second vocabulary.

    Confirmed as described: contradicts in knowledge/relations.py:43 (KB_RELATION_TYPES) via create_fact_relation(), and ClaimVerifier.verify at services/claim_verifier.py:365 as the 2-source arbitration to extend.

    Quarantine boundary proven end-to-end, not described. services/research/quarantine_boundary_test.py drives a real where-filter through the production code path: quarantined fact excluded, promoted fact included, legacy fact lacking the collection field still visible, disputed fact still excluded. memory_adapter._match_where gained $ne/$eq (its own docstring invited the extension) so the proof runs without live ChromaDB, which conftest.py stubs globally.

    Verification: py_compile / flake8 --max-line-length=120 / black --check --line-length=120 clean on every touched file; cp-swapped baseline (never git stash) gave an identical failing set before and after, with 22 new tests and zero regressions; tests/test_startup_imports.py 350/350 unchanged; a 3898-test sweep across services/ + knowledge/ showed every file this PR touches 100% green, with the pre-existing failures confirmed environmental (live backend_url fixture, npu_pipeline, rag_service_kb_synthesis).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions