import type { ConfidenceLevel, SourceKind } from "./types.js"; export const CONFIDENCE_RANK: Record = { verified: 5, high: 4, moderate: 3, estimated: 2, unverified: 1 }; /** Base confidence by source category (before adjustments). */ export const SOURCE_KIND_BASE: Record = { operator: "high", government: "high", filing: "high", utility: "high", cloud_provider: "high", registry: "high", dataset: "moderate", community: "moderate", secondary: "moderate", news: "moderate", }; export interface ConfidenceInput { sourceKind: SourceKind; sourcePriority?: number; // 1 (best) … 5 extractionCertainty?: number; // 0..1 (structured field = 1, regex on prose = 0.6, llm = 0.4) ageDays?: number; corroborations?: number; // number of independent sources agreeing conflicts?: number; // independent sources disagreeing isEstimate?: boolean; } export function computeConfidence(i: ConfidenceInput): ConfidenceLevel { if (i.isEstimate) return "estimated"; let score = CONFIDENCE_RANK[SOURCE_KIND_BASE[i.sourceKind]]; const cert = i.extractionCertainty ?? 1; if (cert < 0.5) score -= 2; else if (cert < 0.8) score -= 1; if ((i.corroborations ?? 0) >= 2) score += 1; if ((i.conflicts ?? 0) >= 1) score -= 1; if ((i.ageDays ?? 0) > 730) score -= 1; if ((i.sourcePriority ?? 3) >= 5) score -= 1; score = Math.max(1, Math.min(5, score)); // "verified" requires corroboration by ≥2 independent primary-grade sources if (score === 5 && !((i.corroborations ?? 0) >= 2 && cert >= 0.8)) score = 4; return (Object.keys(CONFIDENCE_RANK) as ConfidenceLevel[]).find((k) => CONFIDENCE_RANK[k] === score) ?? "unverified"; } export function bestConfidence(levels: ConfidenceLevel[]): ConfidenceLevel { return levels.reduce((best, l) => (CONFIDENCE_RANK[l] > CONFIDENCE_RANK[best] ? l : best), "unverified"); } export const CONFIDENCE_LABEL: Record = { verified: "Verified", high: "High confidence", moderate: "Moderate confidence", estimated: "Estimated", unverified: "Unverified" };