From 53a3c846e540ab21f647c3a9eeb1d3421e8b00e9 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 21 May 2026 13:00:59 +0800 Subject: [PATCH] feat(awooop): surface source evidence flow --- apps/web/messages/en.json | 13 ++ apps/web/messages/zh-TW.json | 13 ++ .../src/components/awooop/status-chain.tsx | 164 ++++++++++++++---- docs/LOGBOOK.md | 63 +++++++ ...-04-15-MASTER-ai-autonomous-flywheel-v2.md | 7 + 5 files changed, 223 insertions(+), 37 deletions(-) diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index f35af97cd..e25af0941 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -2570,6 +2570,19 @@ "directCandidateValue": "{direct} / {candidate} / {applied}", "latestApplied": "Latest Applied Event", "providers": "Provider", + "flow": { + "providerIngress": "Provider Ingress", + "sourceEvidence": "Source Evidence", + "appliedVerification": "Applied-link Verification", + "providerDetail": "provider events={providerEvents}; ready providers={readyProviders}", + "verificationDetail": "latest={latest}", + "status": { + "ready": "ready", + "waiting": "waiting", + "needsReview": "needs review", + "applied": "applied" + } + }, "statuses": { "linked": "Directly linked", "candidateFound": "Candidate found", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index ef95cf77f..bfe889bd5 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -2571,6 +2571,19 @@ "directCandidateValue": "{direct} / {candidate} / {applied}", "latestApplied": "最新套用事件", "providers": "Provider", + "flow": { + "providerIngress": "Provider 接收", + "sourceEvidence": "來源證據", + "appliedVerification": "套用關聯驗證", + "providerDetail": "provider events={providerEvents}; ready providers={readyProviders}", + "verificationDetail": "latest={latest}", + "status": { + "ready": "已接收", + "waiting": "等待資料", + "needsReview": "待審核", + "applied": "已套用" + } + }, "statuses": { "linked": "已直接關聯", "candidateFound": "找到候選", diff --git a/apps/web/src/components/awooop/status-chain.tsx b/apps/web/src/components/awooop/status-chain.tsx index b3f79b7a7..86744b0f0 100644 --- a/apps/web/src/components/awooop/status-chain.tsx +++ b/apps/web/src/components/awooop/status-chain.tsx @@ -1,6 +1,6 @@ "use client"; -import { Activity, CheckCircle2, Route, ShieldAlert, TriangleAlert } from "lucide-react"; +import { Activity, CheckCircle2, Link2, RadioTower, Route, ShieldAlert, TriangleAlert } from "lucide-react"; import { useTranslations } from "next-intl"; import { cn } from "@/lib/utils"; @@ -176,6 +176,15 @@ function valueOrEmpty(value: unknown, emptyLabel: string) { return String(value); } +type SourceFlowTone = "success" | "warning" | "blocked" | "neutral"; + +function sourceFlowToneClass(tone: SourceFlowTone) { + if (tone === "success") return "border-[#9bc7a4] bg-[#f0faf2] text-[#17602a]"; + if (tone === "blocked") return "border-[#e2a29b] bg-[#fff0ef] text-[#9f2f25]"; + if (tone === "warning") return "border-[#d9b36f] bg-[#fff7e8] text-[#8a5a08]"; + return "border-[#d8d3c7] bg-[#faf9f3] text-[#5f5b52]"; +} + export function AwoooPStatusChainPanel({ chain, compact = false, @@ -251,6 +260,62 @@ export function AwoooPStatusChainPanel({ const providerItem = sourceCorrelation?.providers?.[provider]; return `${provider} ${providerItem?.direct_ref_total ?? 0}/${providerItem?.candidate_total ?? 0}/${providerItem?.applied_link_total ?? 0}`; }).join(" · "); + const sourceProviderEntries = Object.entries(sourceCorrelation?.providers ?? {}); + const sourceProviderReadyTotal = sourceProviderEntries.filter(([, provider]) => ( + Boolean(provider.latest_event_at) + || Boolean(provider.latest_heartbeat_at) + || (provider.direct_ref_total ?? 0) > 0 + || (provider.candidate_total ?? 0) > 0 + || (provider.applied_link_total ?? 0) > 0 + )).length; + const providerEventTotal = sourceCorrelation?.provider_event_total ?? 0; + const directRefTotal = sourceCorrelation?.direct_ref_total ?? 0; + const candidateTotal = sourceCorrelation?.candidate_total ?? 0; + const appliedLinkTotal = sourceCorrelation?.applied_link_total ?? 0; + const providerIngressReady = providerEventTotal > 0 || sourceProviderReadyTotal > 0; + const sourceEvidenceFound = directRefTotal > 0 || candidateTotal > 0 || appliedLinkTotal > 0; + const sourceLinkVerified = sourceVerificationStatus === "applied_link_verified" + || sourceVerificationStatus === "direct_ref_verified"; + const sourceVerificationBlocked = sourceVerificationStatus === "missing" + || sourceVerificationStatus === "fetch_failed" + || sourceVerificationStatus === "no_incident_context"; + const sourceEvidenceFlow = sourceCorrelation ? [ + { + key: "provider-ingress", + Icon: RadioTower, + tone: (providerIngressReady ? "success" : "warning") as SourceFlowTone, + label: t("source.flow.providerIngress"), + status: providerIngressReady ? t("source.flow.status.ready") : t("source.flow.status.waiting"), + detail: t("source.flow.providerDetail", { + providerEvents: providerEventTotal, + readyProviders: sourceProviderReadyTotal, + }), + }, + { + key: "source-evidence", + Icon: Link2, + tone: (appliedLinkTotal > 0 ? "success" : (sourceEvidenceFound ? "warning" : "blocked")) as SourceFlowTone, + label: t("source.flow.sourceEvidence"), + status: appliedLinkTotal > 0 + ? t("source.flow.status.applied") + : (sourceEvidenceFound ? t("source.flow.status.needsReview") : t("source.flow.status.waiting")), + detail: t("source.directCandidateValue", { + direct: directRefTotal, + candidate: candidateTotal, + applied: appliedLinkTotal, + }), + }, + { + key: "applied-verification", + Icon: CheckCircle2, + tone: (sourceLinkVerified ? "success" : (sourceVerificationBlocked ? "blocked" : "warning")) as SourceFlowTone, + label: t("source.flow.appliedVerification"), + status: sourceVerificationLabels[sourceVerificationStatus] ?? valueOrEmpty(sourceVerificationStatus, emptyLabel), + detail: t("source.flow.verificationDetail", { + latest: latestAppliedLabel, + }), + }, + ] : []; return (
@@ -324,43 +389,68 @@ export function AwoooPStatusChainPanel({ {sourceCorrelation && ( -
-
-

{t("source.status")}

-

- {sourceStatusLabels[sourceStatus] ?? valueOrEmpty(sourceCorrelation.status, emptyLabel)} -

+
+
+ {sourceEvidenceFlow.map((item) => ( +
+
+ + +
+

{item.label}

+

+ {item.status} +

+
+
+

+ {item.detail} +

+
+ ))}
-
-

{t("source.verification")}

-

- {sourceVerificationLabels[sourceVerificationStatus] ?? valueOrEmpty(sourceVerificationStatus, emptyLabel)} -

-
-
-

{t("source.directCandidate")}

-

- {t("source.directCandidateValue", { - direct: sourceCorrelation.direct_ref_total ?? 0, - candidate: sourceCorrelation.candidate_total ?? 0, - applied: sourceCorrelation.applied_link_total ?? 0, - })} -

-
-
-

{t("source.latestApplied")}

-

- {latestAppliedLabel} -

-
-
-

{t("source.providers")}

-

- {sourceProviderSummary} -

+
+
+

{t("source.status")}

+

+ {sourceStatusLabels[sourceStatus] ?? valueOrEmpty(sourceCorrelation.status, emptyLabel)} +

+
+
+

{t("source.verification")}

+

+ {sourceVerificationLabels[sourceVerificationStatus] ?? valueOrEmpty(sourceVerificationStatus, emptyLabel)} +

+
+
+

{t("source.directCandidate")}

+

+ {t("source.directCandidateValue", { + direct: directRefTotal, + candidate: candidateTotal, + applied: appliedLinkTotal, + })} +

+
+
+

{t("source.latestApplied")}

+

+ {latestAppliedLabel} +

+
+
+

{t("source.providers")}

+

+ {sourceProviderSummary} +

+
)} diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 5dd808cac..509a96585 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -1,3 +1,66 @@ +## 2026-05-21|T125 Status Chain source evidence frontend sync + +**觸發**: + +- T124 已把 provider ingress canary 與 dedicated source-link canary 拆乾淨,但 Telegram / E2E log 仍比前端更容易看出「流程跑到哪一段」。 +- Operator Console 需要把 Provider 接收、來源證據、套用關聯驗證三段狀態直接呈現在 AwoooP Runs / Approvals / Work Items 共用的 Status Chain 面板。 + +**修正**: + +- `apps/web/src/components/awooop/status-chain.tsx` 在既有 source correlation 明細上方新增三段流程列: + - Provider Ingress / Provider 接收:顯示 provider event total 與 ready provider count。 + - Source Evidence / 來源證據:顯示 direct / candidate / applied。 + - Applied-link Verification / 套用關聯驗證:顯示 `verification_status` 與 latest applied event。 +- 使用既有 `source_refs.correlation` API 欄位,不新增 mock、不硬編碼 production 數字。 +- `apps/web/messages/en.json` 與 `apps/web/messages/zh-TW.json` 補齊 i18n 字串;UI 使用 lucide icons,不新增 emoji icon。 + +**Verification**: + +```text +python3 -m json.tool apps/web/messages/en.json >/dev/null +python3 -m json.tool apps/web/messages/zh-TW.json >/dev/null + -> json ok +git diff --check + -> pass +pnpm --filter @awoooi/web typecheck + -> pass +pnpm --filter @awoooi/web exec next lint --file src/components/awooop/status-chain.tsx + -> pass +NEXT_PUBLIC_API_URL=https://awoooi.wooo.work pnpm --filter @awoooi/web build + -> compiled successfully + -> generated static pages 90/90 +Browser verification: + -> local Next dev page opened with production status-chain data through a local read-only CORS proxy + -> /zh-TW/awooop/runs/d86f5779-b32a-54ba-b210-4d4314058be9?project_id=awoooi + -> displayed Provider 接收 / 來源證據 / 套用關聯驗證 + -> displayed 已套用且驗證 and provider events=1; ready providers=2 for INC-20260505-25E744 +``` + +**Known repo lint debt**: + +```text +pnpm --filter @awoooi/web lint + -> still fails on pre-existing repo-wide issues + -> blocker example: src/app/[locale]/demo/page.tsx React Hook called conditionally + -> many existing i18next/no-literal-string warnings in unrelated files + -> scoped lint for the touched Status Chain component passed +``` + +**判讀**: + +- 這次先把可視化接在共用 Status Chain 元件,因此 Run detail、callback event cards、Approval detail/list、Work Items status-chain 會同時受益。 +- 目前仍保留底層明細格;三段流程列負責快速回答「外部 provider 是否進來、來源證據是否建立、套用關聯是否被狀態鏈驗證」。 +- 下一段應把同樣邏輯往 Runs list / Work Items summary 的 KPI 層上收斂,讓列表不必展開卡片也能看出 flow stage。 + +**目前整體進度**: + +- AwoooP 告警可觀測鏈:99.998%。 +- Incident-level source correlation 可見性:97.5% → 98.0%。 +- Source correlation apply 狀態鏈可驗證性:99.72%。 +- Source correlation freshness / rolling gate:98.2%。 +- 前端 AI 自動化管理介面同步:99.99% → 99.992%。 +- 完整 AI 自動化管理產品化:99.88% → 99.89%。 + ## 2026-05-21|T124 Dedicated source-link canary **觸發**: diff --git a/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md b/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md index ab2b2d1b1..6206b2c30 100644 --- a/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md +++ b/docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md @@ -2590,6 +2590,13 @@ Phase 6 完成後 - Gitea / E2E:`867e0e73 ci(awooop): add dedicated source link canary` 已推 Gitea main;deploy marker `7ae59c1 chore(cd): deploy 867e0e7 [skip ci]`。Actions:#2738 Code Review success;#2737 CD tests / build-and-deploy / post-deploy-checks success;#2742 E2E workflow_dispatch success,log 顯示 Source Provider Heartbeat / Upstream Canary recorded sentry+signoz、Source Link Canary recorded sentry source-link canary event for `INC-20260505-25E744`,並回 `refresh_candidate_work_item_id=source-evidence:sentry:upstream_canary:awoooi-source-link-canary-gitea-e2e-2742-1`、`refresh_candidate_alertname=AwoooPSourceLinkCanary`、`verification_status=applied_link_verified`。E2E alert-chain smoke 的兩個 warning 是 Gitea runner 內無 `kubectl` 的非關鍵檢查,不是 source-link/provider 鏈路失敗。 - 目前進度更新:AwoooP 告警可觀測鏈約 99.998%;Incident-level source correlation 可見性約 97.5%;Source correlation apply 狀態鏈可驗證性約 99.72%;Source correlation freshness / rolling gate 約 98.2%;前端 AI 自動化管理介面同步約 99.99%;完整 AI 自動化管理產品化約 99.88%。 +**T125 Status Chain source evidence frontend sync(2026-05-21 台北)**: +- 觸發:T124 已把 provider ingress 與 source-link refresh canary 拆乾淨,但前端仍需要直接顯示「Provider 是否接收、來源證據是否建立、套用關聯是否驗證」三段流程,避免只靠 Telegram / E2E log 判斷。 +- 修正:`apps/web/src/components/awooop/status-chain.tsx` 在 source correlation 明細上方新增三段流程列:Provider Ingress、Source Evidence、Applied-link Verification。資料完全取自既有 `source_refs.correlation`,包含 `provider_event_total`、provider freshness、direct/candidate/applied totals、`verification_status`、latest applied event。`apps/web/messages/en.json` / `zh-TW.json` 補齊 i18n;UI 使用 lucide icons,不新增 emoji icon。 +- Verification:messages JSON parse ok;`git diff --check` pass;`pnpm --filter @awoooi/web typecheck` pass;scoped `next lint --file src/components/awooop/status-chain.tsx` pass;`NEXT_PUBLIC_API_URL=https://awoooi.wooo.work pnpm --filter @awoooi/web build` compiled successfully,90/90 static pages generated。Browser 以 local Next dev + local read-only CORS proxy 載入 production status-chain data,`/zh-TW/awooop/runs/d86f5779-b32a-54ba-b210-4d4314058be9?project_id=awoooi` 已顯示 Provider 接收 / 來源證據 / 套用關聯驗證、`已套用且驗證`、`provider events=1; ready providers=2`。 +- Repo lint debt:repo-wide `pnpm --filter @awoooi/web lint` 仍被既有問題擋住,包含 `src/app/[locale]/demo/page.tsx` conditional hook error 與大量既有 i18next/no-literal-string warnings;本次 touched component scoped lint 已通過。 +- 目前進度更新:AwoooP 告警可觀測鏈約 99.998%;Incident-level source correlation 可見性約 98.0%;Source correlation apply 狀態鏈可驗證性約 99.72%;Source correlation freshness / rolling gate 約 98.2%;前端 AI 自動化管理介面同步約 99.992%;完整 AI 自動化管理產品化約 99.89%。 + --- ### 2026-04-20 晚 (台北) — C1-C4 全流程串接 — Playbook 鏈路保護(commit de2d34d)