feat(platform): surface canonical run correlation
This commit is contained in:
@@ -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")} />
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user