/** Stage 12: recommended experiments, minimum-additional-evidence answer, * rendered final report with remediation tiers, JSON/markdown export, and the * training-mode reveal. */ import { useState } from 'react'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import Chip from '@mui/material/Chip'; import Collapse from '@mui/material/Collapse'; import Typography from '@mui/material/Typography'; import { Download, Eye, FileJson } from 'lucide-react'; import type { Experiments, Investigation, RcaReport, RevealResponse } from '../../types/rca'; import { BORDER, CONFIDENCE_COLORS, Explainer, SectionCard, StatusPill, tableSx } from './common'; function download(filename: string, text: string, mime: string) { const blob = new Blob([text], { type: mime }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; a.click(); URL.revokeObjectURL(url); } const COST_COLORS: Record = { low: '#66bb6a', medium: '#ffb74d', high: '#ef5350' }; export function ExperimentsView({ exp }: { exp: Experiments }) { return ( <> {exp.minimum_additional_evidence} Current effective n: {exp.power.effective_n.toLocaleString()} Needed for the {exp.power.practical_margin_pp.toFixed(1)}pp margin:{' '} {exp.power.needed_effective_n.toLocaleString()} #DesignInstantiated for this investigation DiscriminatesCostGainPriority {exp.experiments.map((d) => ( {d.rank} {d.design} {d.description} {d.discriminates.map((h) => ( ))} {d.information_gain.toFixed(1)} {d.priority.toFixed(1)} ))} ); } export function ReportView({ report, inv, reveal, onReveal }: { report: RcaReport; inv: Investigation; reveal: RevealResponse | null; onReveal: () => void; }) { const [showMd, setShowMd] = useState(false); const ef = report.executive_finding; const confColor = CONFIDENCE_COLORS[ef.confidence]; return ( <> } > {ef.conclusion ?? ef.top_hypothesis} {ef.label} — score {ef.score} (gap to runner-up {ef.score_gap_to_runner_up}). Claims under investigation: offline {report.claims.offline_delta_pp >= 0 ? '+' : ''}{report.claims.offline_delta_pp}pp vs shadow{' '} {report.claims.shadow_delta_pp}pp on {report.claims.metric}. StageQuestionVerdictMismatches / unknowns {report.stage_summaries.map((s) => ( {s.stage} {s.headline} {[...s.mismatches, ...s.unknowns].join('; ') || '—'} ))} {(['containment', 'short_term', 'long_term'] as const).map((tier) => ( {report.remediation[tier].map((x) => ( • {x} ))} ))} {report.acknowledged_unknowns.length ? ( {report.acknowledged_unknowns.map((e, i) => ( ⚠ {e.message} — note: {String((e.data as any)?.note ?? '')} ))} ) : null} setShowMd((s) => !s)}>{showMd ? 'hide' : 'show'}} > {report.markdown} {inv.training_mode ? ( {reveal ? ( Planted cause: {reveal.cause}{' '} {reveal.cause === ef.top_hypothesis ? '— your board got it right ✓' : `— your board's top pick was ${ef.top_hypothesis} ✗`} {reveal.explanation} ) : ( )} ) : null} ); }