/** * Coverage & curator-quality tab: diversity coverage matrix, confidence * calibration reliability chart, precision/recall/yield/model-value cards and * the recurring-miss improvement report. */ import { useEffect, useState } from 'react'; import Box from '@mui/material/Box'; import Card from '@mui/material/Card'; import CardContent from '@mui/material/CardContent'; import Chip from '@mui/material/Chip'; import Table from '@mui/material/Table'; import TableBody from '@mui/material/TableBody'; import TableCell from '@mui/material/TableCell'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; import Typography from '@mui/material/Typography'; import type { CuratorReport, DiversityReport, ImprovementReport, QuantvalReport } from '../../types/raremine'; import { getCuratorReport, getDiversityReport, getImprovementReport, getQuantvalReport, } from '../../services/raremine'; import { Explainer, SectionLabel } from './shared'; function MetricCard({ label, value, sub }: { label: string; value: string; sub?: string }) { return ( {label} {value} {sub ? ( {sub} ) : null} ); } function CalibrationChart({ report }: { report: CuratorReport }) { const bins = report.calibration; const W = 320; const H = 180; const pad = 34; const bw = (W - pad - 10) / bins.length; return ( {/* perfect-calibration diagonal */} {[0, 0.5, 1].map((v) => ( {(v * 100).toFixed(0)}% ))} {bins.map((b, i) => { const x = pad + i * bw; if (!b.n) { return ( {b.bin} ); } const h = (b.observed_rate ?? 0) * (H - pad - 10); return ( {((b.observed_rate ?? 0) * 100).toFixed(0)}% (n={b.n}) {b.bin} ); })} stated rare-event confidence → observed true rate (vs planted truth) ); } function CoverageMatrix({ report }: { report: DiversityReport }) { const costumes = Object.keys(report.coverage_matrix).sort(); const conditions = Array.from( new Set(costumes.flatMap((c) => Object.keys(report.coverage_matrix[c]))) ).sort(); if (!costumes.length) { return ( No diversity selection yet — run mining first. ); } return ( costume ↓ / condition → {conditions.map((cond) => ( {cond.replace(':', ': ')} ))} {costumes.map((cost) => ( {cost} {conditions.map((cond) => { const n = report.coverage_matrix[cost][cond] ?? 0; return ( {n || '·'} ); })} ))}
); } export default function CoverageQualityTab({ refreshKey }: { refreshKey: number }) { const [curator, setCurator] = useState(null); const [diversity, setDiversity] = useState(null); const [quant, setQuant] = useState(null); const [improvement, setImprovement] = useState(null); useEffect(() => { getCuratorReport().then(setCurator).catch(() => setCurator(null)); getDiversityReport().then(setDiversity).catch(() => setDiversity(null)); getQuantvalReport().then(setQuant).catch(() => setQuant(null)); getImprovementReport().then(setImprovement).catch(() => setImprovement(null)); }, [refreshKey]); const pct = (v: number | null | undefined) => (v === null || v === undefined ? '—' : `${(v * 100).toFixed(1)}%`); return ( This tab measures the MINER, not the scenes: because rare events are planted synthetically, ground truth is known and mining precision/recall are exact. Calibration compares the miner's stated confidence with how often it was actually right — a well-calibrated 80% bin should be right about 80% of the time. None of these statistics change any candidate; they feed the improvement loop for the next run. {curator ? ( {quant ? ( ) : null} ) : null} Confidence calibration (reliability) {curator ? : null} Diversity coverage matrix (selected examples) {diversity ? ( <> ) : null} {quant ? ( Predicted vs observed difficulty (agreement matrix) predicted ↓ / observed → {['EASY', 'MODERATE', 'HARD', 'EXTREME'].map((d) => ( {d} ))} {Object.entries(quant.agreement_matrix).map(([pred, row]) => ( {pred} {['EASY', 'MODERATE', 'HARD', 'EXTREME'].map((obs) => ( {row[obs] || '·'} ))} ))}
) : null} {improvement ? ( Recurring-miss improvement report (feeds the next run) {improvement.recurring_misses.total} planted event(s) missed —{' '} {Object.entries(improvement.recurring_misses.by_costume_type) .map(([k, v]) => `${k}: ${v}`) .join(', ') || 'none'} . Over-fires on confounders: {improvement.over_fires.total}. Suggested next-run sensitivity boosts:{' '} {Object.entries(improvement.next_run_config.sensitivity_boost) .map(([k, v]) => `${k} +${v}`) .join(', ') || 'none'} {improvement.next_run_config.rare_event_threshold ? ` · tighten rare-event threshold to ${improvement.next_run_config.rare_event_threshold}` : ''} Use “Re-mine with improvements” on the Mining Run panel to apply this configuration. ) : null}
); }