feat(platform): surface canonical run correlation

This commit is contained in:
Your Name
2026-07-22 18:05:38 +08:00
parent 7b3b7786c7
commit 873c7aa388
6 changed files with 156 additions and 34 deletions

View File

@@ -52,6 +52,8 @@ interface RunDetail {
state: string;
is_shadow: boolean;
trace_id?: string | null;
work_item_id?: string | null;
correlation_status?: "canonical" | "legacy_or_invalid_trace" | null;
trigger_type?: string | null;
trigger_ref?: string | null;
cost_usd: number | string;
@@ -1522,7 +1524,15 @@ export default function RunDetailPage({
<div className="px-4">
<DetailField label={t("summary.project")} value={run ? publicProjectText(run.project_id) : null} emptyLabel={t("empty")} />
<DetailField label={t("summary.agent")} value={run ? publicAgentText(run.agent_id) : null} emptyLabel={t("empty")} />
<DetailField label={t("summary.traceId")} value={run?.trace_id ? "已脫敏追蹤碼" : null} emptyLabel={t("empty")} />
<DetailField label={t("summary.workItem")} value={run?.work_item_id} emptyLabel={t("empty")} />
<DetailField label={t("summary.traceId")} value={run?.trace_id} emptyLabel={t("empty")} />
<DetailField
label={t("summary.correlation")}
value={run?.correlation_status
? t(`summary.correlationStatuses.${run.correlation_status}` as never)
: null}
emptyLabel={t("empty")}
/>
<DetailField label={t("summary.trigger")} value={publicInternalCodeSummary(run?.trigger_type, t("empty"))} emptyLabel={t("empty")} />
<DetailField label={t("summary.triggerRef")} value={publicInternalCodeSummary(run?.trigger_ref, t("empty"))} emptyLabel={t("empty")} />
<DetailField label={t("summary.cost")} value={run ? `$${Number(run.cost_usd ?? 0).toFixed(4)}` : null} emptyLabel={t("empty")} />

View File

@@ -288,6 +288,9 @@ interface Run {
agent_id: string;
state: RunState;
is_shadow: boolean;
trace_id?: string | null;
work_item_id?: string | null;
correlation_status?: "canonical" | "legacy_or_invalid_trace" | null;
cost_usd: number | string;
step_count: number;
created_at: string;
@@ -2030,6 +2033,7 @@ function RunRow({
statusChain?: AwoooPStatusChain | null;
sourceFlowLoading: boolean;
}) {
const tCorrelation = useTranslations("awooop.listEvidence.correlation");
const formattedDate = run.created_at
? new Date(run.created_at).toLocaleDateString("zh-TW", {
month: "2-digit",
@@ -2041,16 +2045,39 @@ function RunRow({
const cost = Number(run.cost_usd ?? 0);
const incidentIds = linkedIncidentIds(run.remediation_summary);
const correlationStatus = run.correlation_status ?? "missing";
const correlationTone = correlationStatus === "canonical"
? "border-[#9bc7a4] bg-[#f0faf2] text-[#17602a]"
: "border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]";
return (
<tr className="border-b border-border hover:bg-accent/30 transition-colors">
<td className="px-4 py-3">
<Link
href={`/awooop/runs/${run.run_id}?project_id=${encodeURIComponent(run.project_id)}` as never}
className="font-mono text-xs text-brand-accent bg-brand-accent/10 px-2 py-1 rounded border border-brand-accent/20 hover:bg-brand-accent/15"
>
{run.run_id.slice(0, 8)}
</Link>
<div className="min-w-[220px] max-w-[280px]">
<Link
href={`/awooop/runs/${run.run_id}?project_id=${encodeURIComponent(run.project_id)}` as never}
className="inline-flex rounded border border-brand-accent/20 bg-brand-accent/10 px-2 py-1 font-mono text-xs text-brand-accent hover:bg-brand-accent/15"
>
{run.run_id.slice(0, 8)}
</Link>
<p
className="mt-1 truncate font-mono text-[11px] leading-4 text-[#5f5b52]"
title={run.work_item_id ?? tCorrelation("workItemMissing")}
>
{run.work_item_id ?? tCorrelation("workItemMissing")}
</p>
<div className="mt-1 flex min-w-0 items-center gap-1.5">
<span className={cn("shrink-0 border px-1.5 py-0.5 text-[10px] font-semibold", correlationTone)}>
{tCorrelation(`statuses.${correlationStatus}` as never)}
</span>
<span
className="truncate font-mono text-[10px] text-[#77736a]"
title={run.trace_id ?? tCorrelation("traceMissing")}
>
{run.trace_id ?? tCorrelation("traceMissing")}
</span>
</div>
</div>
</td>
<td className="px-4 py-3">
<span className="text-sm text-muted-foreground">
@@ -5481,7 +5508,7 @@ export default function RunsPage() {
<thead>
<tr className="border-b border-border bg-muted/50">
<th className="text-left px-4 py-3 text-xs font-medium text-muted-foreground uppercase tracking-wider">
Run ID
{tEvidence("correlation.column")}
</th>
<th className="text-left px-4 py-3 text-xs font-medium text-muted-foreground uppercase tracking-wider">
Project ID