feat(awooop): show source flow in work items
All checks were successful
Code Review / ai-code-review (push) Successful in 11s
CD Pipeline / tests (push) Successful in 4m0s
CD Pipeline / build-and-deploy (push) Successful in 3m54s
CD Pipeline / post-deploy-checks (push) Successful in 2m2s

This commit is contained in:
Your Name
2026-05-21 13:58:17 +08:00
parent 2380d6f555
commit ebb73af16b
3 changed files with 135 additions and 0 deletions

View File

@@ -2167,6 +2167,18 @@
"stage": "Stage: {stage}",
"sourceEvent": "Source event: {event}",
"sourceRefs": "Source refs: {refs} (Sentry {sentry} / SignOz {signoz})",
"sourceFlow": {
"label": "Source flow: {status}",
"detail": "refs={refs}; Sentry={sentry}; SignOz={signoz}; event={event}",
"statuses": {
"applied": "Applied",
"reviewed": "Review recorded",
"review": "Awaiting match review",
"evidence": "Source evidence found",
"provider": "Provider received",
"waiting": "Waiting for source"
}
},
"workItem": "Work item: {id}",
"repair": "Repair status: {status}",
"reason": "Reason: {reason}",

View File

@@ -2168,6 +2168,18 @@
"stage": "階段:{stage}",
"sourceEvent": "來源事件:{event}",
"sourceRefs": "來源 refs{refs}Sentry {sentry} / SignOz {signoz}",
"sourceFlow": {
"label": "來源流程:{status}",
"detail": "refs={refs}; Sentry={sentry}; SignOz={signoz}; event={event}",
"statuses": {
"applied": "已套用",
"reviewed": "審核已記錄",
"review": "待審核配對",
"evidence": "來源證據已到",
"provider": "Provider 已接收",
"waiting": "等待來源"
}
},
"workItem": "Work item{id}",
"repair": "修復狀態:{status}",
"reason": "原因:{reason}",

View File

@@ -247,6 +247,14 @@ type RecurrenceWorkItemActionState = {
error?: string | null;
};
type RecurrenceSourceFlowStatus =
| "applied"
| "reviewed"
| "review"
| "evidence"
| "provider"
| "waiting";
type SloResponse = {
adr100?: {
verification_coverage?: {
@@ -936,6 +944,67 @@ function sourceApplyStatusKey(status?: string | null) {
return "unknown";
}
function recurrenceSourceFlowStatus({
item,
actionResult,
sourceApplyStatus,
sourceDecision,
reviewStatus,
}: {
item: RecurrenceItem;
actionResult?: RecurrenceWorkItemActionResult | null;
sourceApplyStatus: string;
sourceDecision: string;
reviewStatus: string;
}): RecurrenceSourceFlowStatus {
const hasAppliedLink =
sourceApplyStatus === "applied" ||
sourceApplyStatus === "partial" ||
Boolean(
actionResult?.source_event_provider_event_id ||
item.source_correlation_apply?.source_event_provider_event_id
);
if (hasAppliedLink) return "applied";
const hasRecordedReview =
sourceDecision !== "unknown" ||
reviewStatus === "recorded" ||
reviewStatus === "accepted" ||
reviewStatus === "rejected" ||
reviewStatus === "needs_more_evidence";
if (hasRecordedReview) return "reviewed";
if (item.work_item?.kind === "source_correlation_review" || item.source_correlation_review) {
return "review";
}
const sourceRefTotal =
(item.source_ref_total ?? 0) +
(item.sentry_ref_total ?? 0) +
(item.signoz_ref_total ?? 0);
if (sourceRefTotal > 0) return "evidence";
if (item.latest_provider_event_id) return "provider";
return "waiting";
}
function recurrenceSourceFlowClass(status: RecurrenceSourceFlowStatus) {
if (status === "applied") return "border-[#9bc7a4] bg-[#f0faf2] text-[#17602a]";
if (status === "reviewed") return "border-[#9bb6d9] bg-[#eef5ff] text-[#1f5b9b]";
if (status === "review" || status === "evidence") {
return "border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]";
}
if (status === "provider") return "border-[#d8d3c7] bg-[#faf9f3] text-[#5f5b52]";
return "border-[#e0ddd4] bg-white text-[#77736a]";
}
function recurrenceSourceFlowIcon(status: RecurrenceSourceFlowStatus) {
if (status === "applied") return ShieldCheck;
if (status === "reviewed") return GitBranch;
if (status === "review" || status === "evidence") return SearchCheck;
if (status === "provider") return Network;
return Database;
}
function formatStaleRatio(value: number) {
return `${(value * 100).toFixed(1)}%`;
}
@@ -1556,6 +1625,19 @@ function RecurrenceWorkQueuePanel({
);
const sourceApplyStatus = actionResult?.apply_status ?? sourceApply?.apply_status;
const sourceApplyStatusKeyValue = sourceApplyStatusKey(sourceApplyStatus);
const sourceFlowStatus = recurrenceSourceFlowStatus({
item,
actionResult,
sourceApplyStatus: sourceApplyStatusKeyValue,
sourceDecision: sourceDecisionKey,
reviewStatus: reviewRecordStatusKey,
});
const SourceFlowIcon = recurrenceSourceFlowIcon(sourceFlowStatus);
const sourceFlowEvent =
actionResult?.source_event_provider_event_id ??
sourceApply?.source_event_provider_event_id ??
item.latest_provider_event_id ??
"--";
const canApplySource =
isSourceReview &&
sourceReview?.decision === "accepted" &&
@@ -1605,6 +1687,35 @@ function RecurrenceWorkQueuePanel({
signoz: item.signoz_ref_total ?? 0,
})}
</p>
<div className="grid gap-1">
<span
className={cn(
"inline-flex w-fit items-center gap-1.5 border px-2 py-1 font-semibold",
recurrenceSourceFlowClass(sourceFlowStatus)
)}
>
<SourceFlowIcon className="h-3.5 w-3.5" aria-hidden="true" />
{t("sourceFlow.label", {
status: t(`sourceFlow.statuses.${sourceFlowStatus}` as never),
})}
</span>
<p
className="truncate font-mono text-xs text-[#77736a]"
title={t("sourceFlow.detail", {
refs: item.source_ref_total ?? 0,
sentry: item.sentry_ref_total ?? 0,
signoz: item.signoz_ref_total ?? 0,
event: sourceFlowEvent,
})}
>
{t("sourceFlow.detail", {
refs: item.source_ref_total ?? 0,
sentry: item.sentry_ref_total ?? 0,
signoz: item.signoz_ref_total ?? 0,
event: sourceFlowEvent,
})}
</p>
</div>
<p>{t("workItem", { id: workItem?.work_item_id ?? "--" })}</p>
<p>
{t("repair", {