Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Enterprise-grade research with multi-source synthesis, citation tracking, and verification. 8-phase pipeline with auto-continuation.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/source_evaluator.py
1#!/usr/bin/env python32"""3Source Credibility Evaluator4Assesses source quality, credibility, and potential biases5"""67from dataclasses import dataclass8from typing import List, Dict, Optional9from urllib.parse import urlparse10from datetime import datetime, timedelta11import re121314@dataclass15class CredibilityScore:16"""Represents source credibility assessment"""17overall_score: float # 0-10018domain_authority: float # 0-10019recency: float # 0-10020expertise: float # 0-10021bias_score: float # 0-100 (higher = more neutral)22factors: Dict[str, str]23recommendation: str # "high_trust", "moderate_trust", "low_trust", "verify"242526class SourceEvaluator:27"""Evaluates source credibility and quality"""2829# Domain reputation tiers30HIGH_AUTHORITY_DOMAINS = {31# Academic & Research32'arxiv.org', 'nature.com', 'science.org', 'cell.com', 'nejm.org',33'thelancet.com', 'springer.com', 'sciencedirect.com', 'plos.org',34'ieee.org', 'acm.org', 'pubmed.ncbi.nlm.nih.gov',3536# Government & International Organizations37'nih.gov', 'cdc.gov', 'who.int', 'fda.gov', 'nasa.gov',38'gov.uk', 'europa.eu', 'un.org',3940# Established Tech Documentation41'docs.python.org', 'developer.mozilla.org', 'docs.microsoft.com',42'cloud.google.com', 'aws.amazon.com', 'kubernetes.io',4344# Reputable News (Fact-check verified)45'reuters.com', 'apnews.com', 'bbc.com', 'economist.com',46'nature.com/news', 'scientificamerican.com'47}4849MODERATE_AUTHORITY_DOMAINS = {50# Tech News & Analysis51'techcrunch.com', 'theverge.com', 'arstechnica.com', 'wired.com',52'zdnet.com', 'cnet.com',5354# Industry Publications55'forbes.com', 'bloomberg.com', 'wsj.com', 'ft.com',5657# Educational58'wikipedia.org', 'britannica.com', 'khanacademy.org',5960# Tech Blogs (established)61'medium.com', 'dev.to', 'stackoverflow.com', 'github.com'62}6364LOW_AUTHORITY_INDICATORS = [65'blogspot.com', 'wordpress.com', 'wix.com', 'substack.com'66]6768def __init__(self):69pass7071def evaluate_source(72self,73url: str,74title: str,75content: Optional[str] = None,76publication_date: Optional[str] = None,77author: Optional[str] = None78) -> CredibilityScore:79"""Evaluate source credibility"""8081domain = self._extract_domain(url)8283# Calculate component scores84domain_score = self._evaluate_domain_authority(domain)85recency_score = self._evaluate_recency(publication_date)86expertise_score = self._evaluate_expertise(domain, title, author)87bias_score = self._evaluate_bias(domain, title, content)8889# Calculate overall score (weighted average)90overall = (91domain_score * 0.35 +92recency_score * 0.20 +93expertise_score * 0.25 +94bias_score * 0.2095)9697# Determine factors98factors = self._identify_factors(99domain, domain_score, recency_score, expertise_score, bias_score100)101102# Generate recommendation103recommendation = self._generate_recommendation(overall)104105return CredibilityScore(106overall_score=round(overall, 2),107domain_authority=round(domain_score, 2),108recency=round(recency_score, 2),109expertise=round(expertise_score, 2),110bias_score=round(bias_score, 2),111factors=factors,112recommendation=recommendation113)114115def _extract_domain(self, url: str) -> str:116"""Extract domain from URL"""117parsed = urlparse(url)118domain = parsed.netloc.lower()119# Remove www prefix120domain = domain.replace('www.', '')121return domain122123def _evaluate_domain_authority(self, domain: str) -> float:124"""Evaluate domain authority (0-100)"""125if domain in self.HIGH_AUTHORITY_DOMAINS:126return 90.0127elif domain in self.MODERATE_AUTHORITY_DOMAINS:128return 70.0129elif any(indicator in domain for indicator in self.LOW_AUTHORITY_INDICATORS):130return 40.0131else:132# Unknown domain - moderate skepticism133return 55.0134135def _evaluate_recency(self, publication_date: Optional[str]) -> float:136"""Evaluate information recency (0-100)"""137if not publication_date:138return 50.0 # Unknown date139140try:141pub_date = datetime.fromisoformat(publication_date.replace('Z', '+00:00'))142age = datetime.now() - pub_date143144# Recency scoring145if age < timedelta(days=90): # < 3 months146return 100.0147elif age < timedelta(days=365): # < 1 year148return 85.0149elif age < timedelta(days=730): # < 2 years150return 70.0151elif age < timedelta(days=1825): # < 5 years152return 50.0153else:154return 30.0155156except Exception:157return 50.0158159def _evaluate_expertise(160self,161domain: str,162title: str,163author: Optional[str]164) -> float:165"""Evaluate source expertise (0-100)"""166score = 50.0167168# Academic/research domains get high expertise169if any(d in domain for d in ['arxiv', 'nature', 'science', 'ieee', 'acm']):170score += 30171172# Government/official sources173if '.gov' in domain or 'who.int' in domain:174score += 25175176# Technical documentation177if 'docs.' in domain or 'documentation' in title.lower():178score += 20179180# Author credentials (if available)181if author:182if any(title in author.lower() for title in ['dr.', 'phd', 'professor']):183score += 15184185return min(score, 100.0)186187def _evaluate_bias(188self,189domain: str,190title: str,191content: Optional[str]192) -> float:193"""Evaluate potential bias (0-100, higher = more neutral)"""194score = 70.0 # Start neutral195196# Check for sensationalism in title197sensational_indicators = [198'!', 'shocking', 'unbelievable', 'you won\'t believe',199'secret', 'they don\'t want you to know'200]201title_lower = title.lower()202if any(indicator in title_lower for indicator in sensational_indicators):203score -= 20204205# Academic sources are typically less biased206if any(d in domain for d in ['arxiv', 'nature', 'science', 'ieee']):207score += 20208209# Check for balance in content (if available)210if content:211# Look for balanced language212balanced_indicators = ['however', 'although', 'on the other hand', 'critics argue']213if any(indicator in content.lower() for indicator in balanced_indicators):214score += 10215216return min(max(score, 0), 100.0)217218def _identify_factors(219self,220domain: str,221domain_score: float,222recency_score: float,223expertise_score: float,224bias_score: float225) -> Dict[str, str]:226"""Identify key credibility factors"""227factors = {}228229if domain_score >= 85:230factors['domain'] = "High authority domain"231elif domain_score <= 45:232factors['domain'] = "Low authority domain - verify claims"233234if recency_score >= 85:235factors['recency'] = "Recent information"236elif recency_score <= 40:237factors['recency'] = "Outdated information - verify currency"238239if expertise_score >= 80:240factors['expertise'] = "Expert source"241elif expertise_score <= 45:242factors['expertise'] = "Limited expertise indicators"243244if bias_score >= 80:245factors['bias'] = "Balanced perspective"246elif bias_score <= 50:247factors['bias'] = "Potential bias detected"248249return factors250251def _generate_recommendation(self, overall_score: float) -> str:252"""Generate trust recommendation"""253if overall_score >= 80:254return "high_trust"255elif overall_score >= 60:256return "moderate_trust"257elif overall_score >= 40:258return "low_trust"259else:260return "verify"261262263# Example usage264if __name__ == '__main__':265evaluator = SourceEvaluator()266267# Test sources268test_sources = [269{270'url': 'https://www.nature.com/articles/s41586-2025-12345',271'title': 'Breakthrough in Quantum Computing',272'publication_date': '2025-10-15'273},274{275'url': 'https://someblog.wordpress.com/shocking-discovery',276'title': 'SHOCKING! You Won\'t Believe This Discovery!',277'publication_date': '2020-01-01'278},279{280'url': 'https://docs.python.org/3/library/asyncio.html',281'title': 'asyncio — Asynchronous I/O',282'publication_date': '2025-11-01'283}284]285286for source in test_sources:287score = evaluator.evaluate_source(**source)288print(f"\nSource: {source['title']}")289print(f"URL: {source['url']}")290print(f"Overall Score: {score.overall_score}/100")291print(f"Recommendation: {score.recommendation}")292print(f"Factors: {score.factors}")293