/** * BureauSnapshot — homepage panel surfacing the Investigation Bureau's * live artefact stack. * * Reads counts + the 3 most-recent items from each table directly via pg. * Server component — renders straight into the homepage shell, no client * hydration cost. */ import Link from "next/link"; import { pgQuery } from "@/lib/retrieval/db"; interface CountRow { c: string } interface RecentEvidence { evidence_id: string; grade: string; verbatim_excerpt: string; source_page_id: string; confidence_band: string | null } interface RecentHypothesis { hypothesis_id: string; position: string; posterior: number | string | null; confidence_band: string | null; reviewed_by: string | null } interface RecentContradiction { contradiction_id: string; topic: string; resolution_status: string } interface RecentGap { gap_id: string; description: string; scope: unknown } interface RecentWitness { witness_id: string; canonical_name: string | null; credibility: string | null; verdict: string | null } interface RecentJob { job_id: string; kind: string; status: string; created_at: string; payload: Record | null } const DETECTIVES = [ { slug: "holmes", name: "Holmes", role: "Hypothesis tournament", tone: "text-[#7fdbff] border-[#7fdbff]" }, { slug: "locard", name: "Locard", role: "Evidence chain", tone: "text-[#06d6a0] border-[#06d6a0]" }, { slug: "dupin", name: "Dupin", role: "Contradiction scan", tone: "text-[#ff8a4d] border-[#ff8a4d]" }, { slug: "schneier", name: "Schneier", role: "Red-team review", tone: "text-[#ff3344] border-[#ff3344]" }, { slug: "poirot", name: "Poirot", role: "Witness analysis", tone: "text-[#9b5de5] border-[#9b5de5]" }, { slug: "taleb", name: "Taleb", role: "Outlier hunter", tone: "text-[#ffd23f] border-[#ffd23f]" }, { slug: "tetlock", name: "Tetlock", role: "Posterior calibration", tone: "text-[#26d4cc] border-[#26d4cc]" }, { slug: "case-writer", name: "Case-Writer", role: "Five-act narrative", tone: "text-[#e0c080] border-[#e0c080]" }, ] as const; const BAND_TONE: Record = { high: "text-[#06d6a0]", medium: "text-[#3fde6a]", low: "text-[#ffa500]", speculation: "text-[#ff6ec7]", }; const GRADE_TONE: Record = { A: "text-[#06d6a0] border-[#06d6a0]", B: "text-[#3fde6a] border-[#3fde6a]", C: "text-[#ffa500] border-[#ffa500]", }; async function loadSnapshot() { // Counts come from a single round-trip via UNION ALL. const counts = await pgQuery( `SELECT 'evidence' AS k, COUNT(*)::text AS c FROM public.evidence UNION ALL SELECT 'hypotheses', COUNT(*)::text FROM public.hypotheses UNION ALL SELECT 'contradictions', COUNT(*)::text FROM public.contradictions UNION ALL SELECT 'witnesses', COUNT(*)::text FROM public.witnesses UNION ALL SELECT 'gaps', COUNT(*)::text FROM public.gaps UNION ALL SELECT 'open_hyp', COUNT(*)::text FROM public.hypotheses WHERE status='open' UNION ALL SELECT 'jobs_running', COUNT(*)::text FROM public.investigation_jobs WHERE status IN ('queued','running') UNION ALL SELECT 'jobs_complete_24h', COUNT(*)::text FROM public.investigation_jobs WHERE status='complete' AND finished_at > NOW() - INTERVAL '24 hours'`, ).catch(() => [] as Array); const byKey: Record = {}; for (const r of counts) byKey[r.k] = Number(r.c); const [hyp, ev, ctr, gap, wit, jobs] = await Promise.all([ pgQuery( `SELECT hypothesis_id, position, posterior, confidence_band, reviewed_by FROM public.hypotheses ORDER BY created_at DESC LIMIT 4`, ).catch(() => []), pgQuery( `SELECT evidence_id, grade, verbatim_excerpt, source_page_id, confidence_band FROM public.evidence ORDER BY created_at DESC LIMIT 3`, ).catch(() => []), pgQuery( `SELECT contradiction_id, topic, resolution_status FROM public.contradictions ORDER BY created_at DESC LIMIT 3`, ).catch(() => []), pgQuery( `SELECT gap_id, description, scope FROM public.gaps ORDER BY created_at DESC LIMIT 3`, ).catch(() => []), pgQuery( `SELECT w.witness_id, e.canonical_name, w.credibility, w.verdict FROM public.witnesses w LEFT JOIN public.entities e ON e.entity_pk = w.person_entity_pk ORDER BY w.created_at DESC LIMIT 3`, ).catch(() => []), pgQuery( `SELECT job_id, kind, status, created_at, payload FROM public.investigation_jobs ORDER BY created_at DESC LIMIT 6`, ).catch(() => []), ]); // Case reports live on disk. Read the reports dir. const { readdir, stat } = await import("node:fs/promises"); const path = await import("node:path"); const reportsDir = path.join(process.env.CASE_ROOT || "/data/ufo/case", "reports"); let reports: Array<{ slug: string; mtimeMs: number }> = []; try { const files = await readdir(reportsDir); const items = await Promise.all( files.filter((f) => f.endsWith(".md")).map(async (f) => { const st = await stat(path.join(reportsDir, f)); return { slug: f.replace(/\.md$/, ""), mtimeMs: st.mtimeMs }; }), ); reports = items.sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0, 4); } catch { /* no reports yet — fine */ } return { counts: byKey, hyp, ev, ctr, gap, wit, jobs, reports }; } export async function BureauSnapshot() { const snap = await loadSnapshot().catch(() => null); if (!snap) { return (
Investigation Bureau snapshot unavailable (db unreachable).
); } const { counts, hyp, ev, ctr, gap, wit, jobs, reports } = snap; const totalArtefacts = (counts.evidence ?? 0) + (counts.hypotheses ?? 0) + (counts.contradictions ?? 0) + (counts.witnesses ?? 0) + (counts.gaps ?? 0) + reports.length; const running = counts.jobs_running ?? 0; return (
{/* Section heading */}

The Investigation Bureau

8 AI detectives · {totalArtefacts} artefacts in the case folder {running > 0 && · {running} job{running === 1 ? "" : "s"} in progress}

→ open the bureau
{/* Detective tiles */}
{DETECTIVES.map((d) => (
{d.name} {d.slug}
{d.role}
))}
{/* Counter row */}
{/* Recent artefacts grid: hypotheses + contradictions + outliers + reports */}
{hyp.length > 0 && ( {hyp.map((h) => { const post = h.posterior !== null ? Number(h.posterior) : null; const bandTone = (h.confidence_band && BAND_TONE[h.confidence_band]) || "text-[#9aa6b8]"; return (
{h.hypothesis_id} {h.confidence_band ?? "—"}{post !== null && ` · ${post.toFixed(2)}`}
{h.position}
{h.reviewed_by && (
↳ reviewed by {h.reviewed_by}
)} ); })}
)} {ctr.length > 0 && ( {ctr.map((c) => (
{c.contradiction_id} {c.resolution_status}
{c.topic}
))}
)} {ev.length > 0 && ( {ev.map((e) => { const tone = (e.grade && GRADE_TONE[e.grade]) || "text-[#9aa6b8]"; return (
{e.evidence_id} Grade {e.grade}
“{(e.verbatim_excerpt || "").slice(0, 140)}…”
); })}
)} {gap.length > 0 && ( {gap.map((g) => { const s = (g.scope ?? {}) as Record; const title = (s.title as string) || g.description; return (
{g.gap_id} {s.kind === "outlier" && ( outlier )}
{title}
); })}
)} {wit.length > 0 && ( {wit.map((w) => (
{w.witness_id} {w.credibility ?? "—"}
{w.canonical_name ?? "—"}
{w.verdict &&
{w.verdict.slice(0, 200)}
}
))}
)} {reports.length > 0 && ( {reports.map((r) => (
case-report
/c/{r.slug}
Watson five-act narrative →
))}
)}
{/* Job activity strip */} {jobs.length > 0 && (
Recent jobs:{" "} {jobs.slice(0, 4).map((j, i) => ( {i > 0 && · } {j.kind}/{j.status} ))}
)}
); } function Counter({ label, value, color, href }: { label: string; value: number; color: string; href: string }) { return (
{value}
{label}
); } function ArtefactColumn({ title, color, border, children, }: { title: string; color: string; border: string; children: React.ReactNode }) { return (
{title}
{children}
); }