This document explains how the Worker actually works, from input request to final verdict, including the core formulas for ranking, trust, truthfulness, and confidence.
Audience:
- New engineers with zero system context
- Researchers evaluating scoring behavior
- Developers debugging verdict quality issues
Primary code references:
worker/app/main.pyworker/app/services/corrective/pipeline/__init__.pyworker/app/services/ranking/hybrid_ranker.pyworker/app/services/ranking/adaptive_trust_policy.pyworker/app/services/verdict/verdict_generator.pyworker/app/constants/config.py
The Worker is the claim-verification core. It does four jobs:
- Retrieve evidence (Vector DB + Knowledge Graph + optional web expansion)
- Rank evidence with deterministic scoring
- Compute adaptive trust sufficiency for the claim
- Generate a verdict package with rationale and analysis metadata
Output is structured, not just text:
verdicttruthfulness_percentconfidenceevidence,evidence_map,claim_breakdown- trust and ranking diagnostics
Main endpoint:
POST /worker/verify
Key request fields:
job_id(required)claim(required)room_id,source(optional)domain(defaultgeneral)top_k(default5, bounded1..20)
Key response signals:
verdict,verdict_confidence,truthfulness_percent- ranking:
top_ranking_score,avg_ranking_score - trust:
trust_policy_mode,trust_metric_value,trust_threshold_met,coverage,diversity - observability:
data_source,used_web_search, signal counts, andanalysis_counts
Runtime path is implemented in CorrectivePipeline.run(...).
- Parse claim and run deterministic/LLM-assisted entity extraction.
- Build retrieval queries from full claim plus decomposed subclaims.
- Retrieve initial candidates from VDB and KG (
retrieve_candidates). - Rank candidates (
rank_candidates->hybrid_rank). - Convert ranked rows to trust evidence objects and compute adaptive trust.
- If adaptive trust is sufficient, run a cache verdict precheck.
- If precheck passes strict gates, exit as
completed_from_cache. - If insufficient, generate search queries for incremental web expansion.
- For each query:
- Search URLs, filter already-processed URLs, and cap per-query URLs.
- Scrape pages and extract facts/entities/relations.
- Ingest extracted facts/triples into VDB and KG.
- Re-retrieve and re-rank with updated evidence.
- Recompute adaptive trust and stop early when sufficient.
- After search loop ends, run final verdict generation.
- Return final payload with full scoring diagnostics.
Ranking constants come from worker/app/constants/config.py:
w_semantic = 0.31w_kg = 0.12w_entity = 0.20w_claim_overlap = 0.15w_recency = 0.05w_credibility = 0.17
For each candidate:
final_score_base = (w_sem * sem_norm) + (w_kg * kg_norm) + (w_entity * entity_overlap) + (w_claim_overlap * claim_overlap) + (w_recency * recency_boost) + (w_cred * credibility)
Where:
sem_norm,kg_normare min-max normalized across current candidate setrecency_boost = 0.5^(days_since_publish / RECENCY_HALF_LIFE_DAYS)with half-life365entity_overlapandclaim_overlapare lexical/entity recall-like overlaps
After base score:
+ 0.05 * min(1, kg_raw)ifkg_raw > 0andclaim_overlap >= 0.08+ 0.10ifkg_norm > 0,entity_overlap >= 0.34,claim_overlap >= 0.10+ 0.08if candidate is KG,kg_raw >= 0.40, and anchors pass
Important score reductions:
- Anchor weak:
- KG candidate:
* 0.30whenanchor_match_score < 0.20 - non-KG:
* 0.70whenanchor_match_score < 0.20
- KG candidate:
- Backfill weak item:
* 0.85 - Object mismatch:
* 0.55 - Claim focus mismatch:
* 0.75 - Subject mismatch:
* 0.60 - Relation object mismatch:
* 0.70 - Claim-mention/reporting style in non-belief claims:
* 0.65 - Uncertainty penalty: subtract
0.12for assertive claims with uncertain wording
- Floor: if
sem_norm == 0,kg_norm == 0, andcredibility >= 0.9, thenfinal_score >= 0.2 - Final clamp:
[0, 1] - Strict candidate filters remove low-overlap/low-signal items before final ranking
Adaptive trust is computed in AdaptiveTrustPolicy.compute_adaptive_trust(...).
coverage: weighted subclaim coverage fromcompute_subclaim_coveragediversity: source-domain diversity scoreagreement: fraction of evidence not markedcontradicts
Coverage calculation:
coverage = sum(detail.weight) / number_of_subclaims
Sufficiency can pass by multiple routes:
- Low-count override when diversity and relevance are very high
- Confidence-mode relaxed gate
- Adaptive override when no contradicted subclaims and one of:
coverage >= 0.25 and diversity >= 0.75strong_covered >= 1avg_relevance >= 0.55
- Strict gates:
- high coverage + high agreement
- medium coverage + high diversity + high agreement
Default thresholds (normal mode):
COVERAGE_THRESHOLD_HIGH = 0.60COVERAGE_THRESHOLD_MEDIUM = 0.40DIVERSITY_THRESHOLD_HIGH = 0.70AGREEMENT_THRESHOLD_HIGH = 0.80MIN_EVIDENCE_COUNT = 3
Confidence mode lowers several thresholds and minimum evidence count.
If evidence exists:
- Build
subclaim_trusts = best_evidence_trust * subclaim_weightfor covered subclaims. - If non-empty:
mean_subclaim_trust = average(subclaim_trusts)
trust_post = mean_subclaim_trust * (0.5 + 0.5 * coverage)
- Else fallback:
trust_post = top_trust * coverage
- Additional consistency floor may re-apply
top_trust * coveragewhen needed.
Verdict state from trust:
evidence_insufficiencyif not sufficientconfirmediftrust_post >= 0.8provisionaliftrust_post >= 0.6- else
revoked
Weak-relevance guard can flip a pass back to insufficiency when trust/semantic/top-trust are weak.
There are two truth-related outputs inside verdict generation:
truth_score_percent(status-driven, used as outputtruthfulness_percent)evidence_quality_percent(evidence-driven quality signal)
Status weights:
STRONGLY_VALID = 1.0VALID = 1.0PARTIALLY_VALID = 0.75UNKNOWN = 0.45PARTIALLY_INVALID = 0.25INVALID = 0.0
Base score:
base = average(status_weight(segment_i))
Then penalties:
- 0.30 * contradict_ratio- 0.10 * unresolved_ratio
Then guards:
- unresolved support-only claims capped below full certainty
- fully resolved strong TRUE can be lifted near certainty
- pure contradiction FALSE can be forced low
Final:
truth_score_percent = clamp(score, 0, 1) * 100
Then additional pipeline-level caps/overrides apply:
- diversity ceiling:
ceiling_percent = (0.85 + 0.10 * diversity) * 100 - numeric override paths
- UNVERIFIABLE and absolute-quantifier guardrails
Important:
- Final response field
truthfulness_percentis this status-driven truth score. evidence_quality_percentis returned separately for diagnostics.
_calculate_truthfulness_from_evidence(...) computes segment-level support with:
- semantic+kg relevance:
0.7*sem + 0.3*kg - anchor overlap
- lexical overlap
- credibility
- contradiction penalties
- uncertainty/reporting penalties
Segment support core:
support = 0.70*rel + 0.15*anchor_overlap + 0.10*overlap_ratio + 0.05*cred
Global evidence quality:
avg_segment_support * (0.85 + 0.15*diversity)
with a ceiling:
<= 0.85 + 0.10*diversity
Converted to percent and returned as evidence_quality_percent.
Primary final confidence in active path:
confidence = 0.30*truthfulness + 0.25*coverage + 0.20*agreement + 0.15*diversity + 0.10*adaptive_trust_post
Then:
- cap at
0.95 - if
coverage >= 0.8, enforceconfidence >= truthfulness * 0.75 - apply contract/policy cap function (
_cap_confidence_with_contract) - additional hard overrides for strong contradiction votes, UNVERIFIABLE locks, and numeric gates
Contract cap behavior includes:
- unresolved segments lower max confidence
- policy insufficiency lowers cap further
- UNVERIFIABLE hard cap (
0.35or0.45for comparative claims) - contradiction-only fully resolved FALSE gets a minimum floor (not underconfident)
Note:
- There is also
_calculate_confidence(...)helper in the file with a detailed formula, but the current primary output path uses the composite confidence formula above in the verdict generation flow.
Worker does not blindly trust raw LLM verdict text. It reconciles verdict with:
- claim breakdown statuses
- admissible evidence stance
- evidence-map support/contradiction signal strengths
- rationale polarity hints
Hard guards:
- Strong contradiction stance can force FALSE
- Strong entailment can force TRUE (with constraints)
- Weak/mixed signal bands can force UNVERIFIABLE
- Binary verdicts require stronger quality gates, else downgraded to UNVERIFIABLE
- Absolute-quantifier claims (
always,never,all, etc.) are guarded from overconfident TRUE
Worker tracks:
- Adaptive trust (
trust_post_adaptive): subclaim/coverage-aware sufficiency logic - Fixed trust (
trust_post_fixed): traditional post-trust score for comparability
Output includes both plus gate metadata so downstream systems can audit decisions.
If verdict looks wrong, inspect in this order:
analysis_counts.admissible_evidence_ratioclaim_breakdownstatuses and unresolved segmentscoverage,diversity,agreement,trust_post- top evidence anchors and claim overlap
- binary gate and UNVERIFIABLE lock conditions
This sequence usually identifies whether the problem is retrieval quality, ranking bias, trust gating, or verdict reconciliation.
docs/README.mddocs/worker-pipeline.mddocs/interfaces-and-contracts.mddocs/testing-and-validation.md
New claim strictness / override tuning variables:
STRICTNESS_HIGH_THRESHOLD(default0.70)STRICTNESS_VERY_HIGH_THRESHOLD(default0.82)STRICTNESS_MEDIUM_THRESHOLD(default0.52)REFUTE_COVERAGE_FORCE_FALSE(default0.50)REFUTE_DIVERSITY_FORCE_FALSE(default0.35)PREDICATE_MATCH_THRESHOLD(default0.45)ANCHOR_THRESHOLD(default0.30)CONTRADICTION_THRESHOLD(default0.55)CONTRADICT_RATIO_FOR_FORCE_FALSE(default0.50)CONTRADICT_RATIO_FORCE_FALSE(default0.50)DIVERSITY_FORCE_FALSE(default0.40)UNVERIFIABLE_CONFIDENCE_CAP(default0.60)HEDGE_PENALTY_BLOCK_TRUE(default0.45)DIVERSITY_CONFIDENCE_CAP_LOW(default0.70)DIVERSITY_CONFIDENCE_CAP_MID(default0.80)NEGATION_ANCHOR_BOOST_WEIGHT(default0.07)MULTIHOP_KG_HINT_MAX_BOOST(default0.15)
Supporting confidence-cap controls:
STRICTNESS_MIN_EVIDENCE_COUNT(default3)STRICTNESS_DIVERSITY_LOW_THRESHOLD(default0.10)STRICTNESS_DIVERSITY_MID_THRESHOLD(default0.20)STRICTNESS_AGREEMENT_MIN(default0.70)STRICTNESS_LOW_EVIDENCE_CONFIDENCE_CAP(default0.75)STRICTNESS_LOW_AGREEMENT_CONFIDENCE_CAP(default0.75)STRICTNESS_HIGH_CLAIM_LOW_DIVERSITY_CAP(default0.72)FALSE_VERDICT_MIN_CONFIDENCE(default0.55)
Last verified against code: February 13, 2026