From ebb73af16b7c999f20be437fa40c2d3c59235d4c Mon Sep 17 00:00:00 2001
From: Your Name
Date: Thu, 21 May 2026 13:58:17 +0800
Subject: [PATCH] feat(awooop): show source flow in work items
---
apps/web/messages/en.json | 12 ++
apps/web/messages/zh-TW.json | 12 ++
.../app/[locale]/awooop/work-items/page.tsx | 111 ++++++++++++++++++
3 files changed, 135 insertions(+)
diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json
index 464bf9b8..6f3a52bf 100644
--- a/apps/web/messages/en.json
+++ b/apps/web/messages/en.json
@@ -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}",
diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json
index dd29eafc..5f344641 100644
--- a/apps/web/messages/zh-TW.json
+++ b/apps/web/messages/zh-TW.json
@@ -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}",
diff --git a/apps/web/src/app/[locale]/awooop/work-items/page.tsx b/apps/web/src/app/[locale]/awooop/work-items/page.tsx
index 88b60c1e..dbab3613 100644
--- a/apps/web/src/app/[locale]/awooop/work-items/page.tsx
+++ b/apps/web/src/app/[locale]/awooop/work-items/page.tsx
@@ -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,
})}
+
+
+
+ {t("sourceFlow.label", {
+ status: t(`sourceFlow.statuses.${sourceFlowStatus}` as never),
+ })}
+
+
+ {t("sourceFlow.detail", {
+ refs: item.source_ref_total ?? 0,
+ sentry: item.sentry_ref_total ?? 0,
+ signoz: item.signoz_ref_total ?? 0,
+ event: sourceFlowEvent,
+ })}
+
+
{t("workItem", { id: workItem?.work_item_id ?? "--" })}
{t("repair", {