// History Details / Forensics — full pipeline view per company const { useState: useStateHD, useEffect: useEffectHD } = React; function HistoryDetailsView({ tweaks, initialEntityId, initialDate }) { const companies = window.DATA?.companies || []; const initialId = initialEntityId || window.DATA.todaysBrief?.entityId || companies[0]?.id; const [selectedId, setSelectedId] = useStateHD(initialId); const [search, setSearch] = useStateHD(""); const [openRunId, setOpenRunId] = useStateHD(null); const [expandedRejection, setExpandedRejection] = useStateHD(null); const [expandedPubCitation, setExpandedPubCitation] = useStateHD(null); const [forensicsData, setForensicsData] = useStateHD(null); const [loading, setLoading] = useStateHD(false); const summaries = window.DATA.companySummaries || {}; useEffectHD(() => { loadForensics(initialId, initialDate); }, []); function loadForensics(id, targetDate) { setSelectedId(id); setLoading(true); setOpenRunId(null); setExpandedPubCitation(null); fetch(`/api/frontend/entity/${id}/forensics`) .then(r => r.json()) .then(d => { setForensicsData(d); if (!d.days || d.days.length === 0) return; // If a target date is provided, open the run for that date; otherwise open the latest const targetDay = targetDate ? d.days.find(day => day.date === targetDate) : d.days[0]; const day = targetDay || d.days[0]; setOpenRunId(null); // Scroll to the target day after render if (targetDate) { requestAnimationFrame(() => { const el = document.getElementById(`hd-day-${targetDate}`); if (el) el.scrollIntoView({ behavior: "smooth", block: "start" }); }); } }) .catch(console.error) .finally(() => setLoading(false)); } const filtered = companies.filter(c => c.name.toLowerCase().includes(search.toLowerCase()) || c.ticker.toLowerCase().includes(search.toLowerCase()) ); const days = forensicsData?.days || []; const entityName = forensicsData?.entityName || companies.find(c => c.id === selectedId)?.name || selectedId; const ticker = forensicsData?.ticker || companies.find(c => c.id === selectedId)?.ticker || ""; return (
{_tk(ticker)} · AUDIT

{loading ? Loading… : entityName}

Every bullet considered, kept or cut, with the pipeline's full reasoning.

Published Rewritten Rejected — relevance Rejected — novelty Rejected — grounding
{days.map(d => { const dt = new Date(d.date + "T00:00:00Z"); const dayNum = String(dt.getUTCDate()).padStart(2, "0"); const month3 = dt.toLocaleDateString("en-US", { month: "short", timeZone: "UTC" }); const wd = dt.toLocaleDateString("en-US", { weekday: "short", timeZone: "UTC" }); const isMulti = d.runs.length > 1; if (!isMulti) { // Single run: original single-row layout const r = d.runs[0]; const isOpen = openRunId === r.runId; return (
{isOpen && (
)}
); } // Multiple runs on the same day: static date header + individual run rows const totalPub = d.runs.reduce((s, r) => s + r.published, 0); const totalRej = d.runs.reduce((s, r) => s + r.rejected, 0); return (
{/* Static date header — not a toggle */}
{dayNum}
{month3}
{wd}
{d.runs.length} runs · {totalPub} published · {totalRej} rejected
{/* One expandable row per run */} {d.runs.map(r => { const isOpen = openRunId === r.runId; return ( {isOpen && (
)}
); })}
); })} {days.length === 0 && !loading && (

No runs found for this entity.

)}
); } /** Shared body content (published bullets + rejection groups) for a single run. */ function RunBody({ r, expandedRejection, setExpandedRejection, expandedPubCitation, setExpandedPubCitation }) { return ( {r.narrative && (
Narrative

{r.narrative}

)} {/* Published bullets */}
Published bullets {r.published} kept
{r.bullets && r.bullets.length > 0 ? (
{r.bullets.map((b, i) => (
{String(i + 1).padStart(2, "0")} {b.theme} {b.novelty === "rewritten" && rewritten}

{b.text}

{b.novelty === "rewritten" && b.rewriteReason && (
Why rewritten {b.rewriteReason}
)} {b.citations?.length > 0 && (
Sources
    {_groupCitations(b.citations).map((sg, si) => (
  • {sg.source} {sg.date && · {sg.date}}
    {sg.headlineGroups.map((hg, hi) => { const citeKey = `${r.runId}-${i}-${si}-${hi}`; const open = expandedPubCitation === citeKey; return (
    {hg.headline} {hg.excerpts.length > 0 && ( <> {open && (
    {hg.excerpts.length === 1 ? hg.excerpts[0] : hg.excerpts.map((ex, xi) => (
    Text {xi + 1}:
    {ex}
    )) }
    )} )}
    ); })}
  • ))}
)}
))}
) : (

No active bullets for this day.

)}
{/* Rejected, grouped by stage */} {r.rejectionGroups?.length > 0 && (
Rejected candidates {r.rejected} discarded across {r.rejectionGroups.length} pipeline stages
{r.rejectionGroups.map(g => (
{stageNumber(g.stage)}
{g.stageLabel}
{g.count} cut
    {g.items.map(item => { const isExp = expandedRejection === item.id; return (
  • {isExp && (
    )}
  • ); })}
))}
)}
); } /** Same order as ``_DISCARD_STAGE_ORDER`` in ``ui.py`` (HTML discarded section). */ const _DISCARD_STAGE_ORDER = [ "relevance_score", "grounding", "novelty_embedding", "novelty_embedding_relevance", "novelty_search", "novelty_search_relevance", "unknown", ]; function stageNumber(stage) { const i = _DISCARD_STAGE_ORDER.indexOf(stage); return i >= 0 ? String(i + 1).padStart(2, "0") : "··"; } /** Expanded body — fields mirror ``_load_bullets_for_run`` / ``_render_discarded_detail_body`` (HTML). */ function ForensicsDiscardDetail({ item }) { const d = item.discarded; if (!d || typeof d !== "object") { return ( {item.scoreReason && (
Why filtered

{item.scoreReason}

)} {item.evidence && (
Pipeline detail

{item.evidence}

)}
); } const reason = (d.reason || "").trim(); const claims = Array.isArray(d.claim_verdicts) ? d.claim_verdicts : []; const evals = Array.isArray(d.evaluator_details) ? d.evaluator_details : []; const evidenceMap = (d.evidence_map && typeof d.evidence_map === "object") ? d.evidence_map : {}; return ( {reason !== "" && (
Why filtered

{d.reason}

)} {d.score != null && d.score !== undefined && (
Relevance score

{d.score}/5

)} {(d.overall_verdict || "").trim() !== "" && (
Novelty verdict

{d.overall_verdict}

)} {claims.length > 0 && (
Claim review
)} {evals.length > 0 && d.stage !== "novelty_search" && ( {evals.map((ev, i) => { const retrieved = Array.isArray(ev.retrieved_bullets) ? ev.retrieved_bullets : []; return ( {retrieved.length > 0 && (
Similar prior bullets {retrieved.map((rb, j) => ( ))}
Date Text Score
{rb.date ? rb.date.slice(0, 10) : "—"} {rb.text} {(rb.score * 100).toFixed(1)}%
)}
); })}
)}
); } function PipelineStageBar({ published, rejected, groups }) { const segments = [ { label: "kept", count: published, cls: "stage-kept" }, ...(groups || []).map(g => ({ label: g.stage, count: g.count, cls: "stage-cut-" + g.stage })), ]; return (
{segments.map((s, i) => (
{s.count >= 3 && {s.count}}
))}
); } window.HistoryDetailsView = HistoryDetailsView;