feat: redesign assurance reports for production
This commit is contained in:
@@ -1,53 +1,114 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { api, type HarnessRunRecord } from '../lib/api';
|
||||
import { Card, StatusBadge } from '../components/ui/Card';
|
||||
import { Link, useSearchParams } from 'react-router-dom';
|
||||
import { ReportHero, ReportPanel, SignalMetric, reportActionPrimary } from '../components/report/ReportPrimitives';
|
||||
import { TraceExplorer } from '../components/trace/TraceExplorer';
|
||||
import { StatusBadge } from '../components/ui/Card';
|
||||
import { api, type HarnessRunRecord } from '../lib/api';
|
||||
|
||||
const integer = (value: number): string => new Intl.NumberFormat('en-US').format(value);
|
||||
|
||||
export function Runs() {
|
||||
const { data, isLoading } = useQuery({ queryKey: ['runs'], queryFn: () => api.runs(100) });
|
||||
const { data, isLoading, isError } = useQuery({ queryKey: ['runs'], queryFn: () => api.runs(100) });
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const selectedTrace = searchParams.get('trace') ?? '';
|
||||
const runs = data?.runs ?? [];
|
||||
const failures = runs.filter((run) => run.status === 'failed').length;
|
||||
const attributedCost = runs.filter((run) => run.cost_estimate != null).length;
|
||||
const latencyValues = runs.map((run) => Number(run.latency_ms)).filter((value) => Number.isFinite(value) && value > 0);
|
||||
const averageLatency = latencyValues.length > 0
|
||||
? Math.round(latencyValues.reduce((sum, value) => sum + value, 0) / latencyValues.length)
|
||||
: null;
|
||||
|
||||
if (isLoading || !data) return <div className="text-slate-500">Loading…</div>;
|
||||
return (
|
||||
<div className="space-y-5">
|
||||
<ReportHero
|
||||
eyebrow="Run assurance registry"
|
||||
title="Every governed run, one evidence trail."
|
||||
description="Select a lifecycle record to reconstruct H1–H7 decisions, inspect sanitized evidence and export an independent assurance dossier."
|
||||
verdict={failures > 0 ? 'attention' : data ? 'operational' : undefined}
|
||||
meta={data ? (
|
||||
<>
|
||||
<span>{data.count} records in current registry</span>
|
||||
<span>{failures} failures</span>
|
||||
<span>{attributedCost}/{runs.length} cost-attributed</span>
|
||||
</>
|
||||
) : <span>Loading governed run registry…</span>}
|
||||
actions={<Link to="/reports/h6" className={reportActionPrimary}>Open H6 dossier</Link>}
|
||||
/>
|
||||
|
||||
{selectedTrace && <TraceExplorer traceId={selectedTrace} onClose={() => setSearchParams({})} />}
|
||||
<Card
|
||||
title={`Recent runs (${data.count})`}
|
||||
right={<span className="text-xs font-normal normal-case tracking-normal text-slate-400">Select a run to inspect H1–H7</span>}
|
||||
>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-sm">
|
||||
<thead><tr className="border-b border-slate-200 text-left text-slate-500">
|
||||
<th className="py-2">time</th><th>step</th><th>status</th><th>latency</th><th>tokens</th><th>cost</th><th className="text-right">trace</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
{data.runs.map((run: HarnessRunRecord, index: number) => (
|
||||
<tr key={`${run.trace_id ?? 'run'}-${index}`} className="border-b border-slate-100 transition-colors hover:bg-slate-50/80">
|
||||
<td className="py-2 text-slate-500">{run.timestamp?.replace('T', ' ').replace('Z', '')}</td>
|
||||
<td className="text-slate-700">{run.step ?? run.harness}</td>
|
||||
<td><StatusBadge value={run.status ?? '—'} /></td>
|
||||
<td>{run.latency_ms ?? '—'} ms</td>
|
||||
<td>{run.total_tokens ?? '—'}</td>
|
||||
<td>{run.cost_estimate == null ? <span className="font-medium text-amber-600">Unavailable</span> : `$${Number(run.cost_estimate).toFixed(5)}`}</td>
|
||||
<td className="py-2 text-right">
|
||||
{run.trace_id ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setSearchParams({ trace: run.trace_id ?? '' })}
|
||||
className="rounded-lg border border-blue-200 bg-blue-50 px-3 py-1.5 text-xs font-semibold text-blue-700 transition-colors hover:bg-blue-100"
|
||||
>
|
||||
Open H1–H7
|
||||
</button>
|
||||
) : <span className="text-slate-300">—</span>}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{isLoading && (
|
||||
<div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
|
||||
{Array.from({ length: 4 }, (_, index) => <div key={index} className="h-32 animate-pulse rounded-2xl bg-slate-200" />)}
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
{isError && <div role="alert" className="rounded-2xl border border-rose-200 bg-rose-50 p-5 text-sm text-rose-800">The governed run registry could not be loaded.</div>}
|
||||
|
||||
{data && (
|
||||
<>
|
||||
<section className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
|
||||
<SignalMetric label="Governed records" value={integer(data.count)} detail="Latest 100 lifecycle records" tone="info" />
|
||||
<SignalMetric label="Failures" value={integer(failures)} detail={`${data.count ? Math.round((failures / data.count) * 100) : 0}% observed failure rate`} tone={failures > 0 ? 'danger' : 'success'} />
|
||||
<SignalMetric label="Average latency" value={averageLatency === null ? 'Unavailable' : `${integer(averageLatency)} ms`} detail={`${latencyValues.length}/${runs.length} records measured`} tone="neutral" />
|
||||
<SignalMetric label="Cost attribution" value={`${runs.length ? Math.round((attributedCost / runs.length) * 100) : 0}%`} detail={`${attributedCost}/${runs.length} records`} tone={attributedCost === runs.length && runs.length > 0 ? 'success' : 'warning'} />
|
||||
</section>
|
||||
|
||||
<ReportPanel
|
||||
eyebrow="Evidence index"
|
||||
title="Recent governed runs"
|
||||
description="Operational values are shown only when present in canonical telemetry. Select a trace to open the evidence spine."
|
||||
right={<span className="text-xs text-slate-400">{data.count} total records</span>}
|
||||
>
|
||||
<div className="-mx-5 overflow-x-auto sm:-mx-6">
|
||||
<table className="w-full min-w-[900px] text-sm">
|
||||
<thead>
|
||||
<tr className="border-y border-slate-100 bg-slate-50 text-left text-[10px] font-black uppercase tracking-[0.12em] text-slate-500">
|
||||
<th className="px-5 py-3 sm:pl-6">Observed at</th>
|
||||
<th className="px-3 py-3">Lifecycle step</th>
|
||||
<th className="px-3 py-3">Verdict</th>
|
||||
<th className="px-3 py-3 text-right">Latency</th>
|
||||
<th className="px-3 py-3 text-right">Tokens</th>
|
||||
<th className="px-3 py-3 text-right">Cost</th>
|
||||
<th className="px-5 py-3 text-right sm:pr-6">Evidence</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{runs.map((run: HarnessRunRecord, index: number) => (
|
||||
<tr key={`${run.trace_id ?? 'run'}-${index}`} className="border-b border-slate-100 transition-colors last:border-0 hover:bg-cyan-50/30">
|
||||
<td className="whitespace-nowrap px-5 py-4 font-mono text-[11px] text-slate-500 sm:pl-6">{run.timestamp?.replace('T', ' ').replace('Z', ' UTC') ?? 'Unavailable'}</td>
|
||||
<td className="px-3 py-4 font-semibold text-slate-900">{run.step ?? run.harness}</td>
|
||||
<td className="px-3 py-4"><StatusBadge value={run.status ?? 'unknown'} /></td>
|
||||
<td className="px-3 py-4 text-right font-mono text-xs text-slate-600">{run.latency_ms == null ? 'Unavailable' : `${integer(Number(run.latency_ms))} ms`}</td>
|
||||
<td className="px-3 py-4 text-right font-mono text-xs text-slate-600">{run.total_tokens ?? 'Unavailable'}</td>
|
||||
<td className="px-3 py-4 text-right font-mono text-xs text-slate-600">{run.cost_estimate == null ? <span className="font-sans text-amber-700">Unavailable</span> : `$${Number(run.cost_estimate).toFixed(5)}`}</td>
|
||||
<td className="px-5 py-4 text-right sm:pr-6">
|
||||
{run.trace_id ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setSearchParams({ trace: run.trace_id ?? '' });
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}}
|
||||
className="min-h-11 rounded-xl border border-slate-300 bg-white px-4 py-2 text-xs font-bold text-slate-700 transition hover:-translate-y-px hover:border-cyan-400 hover:text-cyan-800 focus:outline-none focus:ring-4 focus:ring-cyan-100"
|
||||
>
|
||||
Inspect H1–H7
|
||||
</button>
|
||||
) : <span className="text-slate-300">—</span>}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
{runs.length === 0 && (
|
||||
<tr>
|
||||
<td colSpan={7} className="px-6 py-16 text-center text-sm text-slate-500">No governed run has been recorded yet.</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</ReportPanel>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user