From ffe479dbccc36f9934525a7872827c976128a881 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 25 May 2026 15:30:00 +0800 Subject: [PATCH] fix(web): align homepage automation truth metrics --- apps/web/messages/en.json | 9 +++ apps/web/messages/zh-TW.json | 9 +++ apps/web/src/app/[locale]/page.tsx | 113 +++++++++++++++++++++++++---- docs/LOGBOOK.md | 47 ++++++++++++ 4 files changed, 164 insertions(+), 14 deletions(-) diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 3b99a756..045d0816 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -142,12 +142,21 @@ "execution": "Execution", "resolved": "Resolved" }, + "unresolvedIncidents": "Unresolved Incidents", "activeIncidents": "Active Incidents", "serviceHealth": "Service Health", "todayIncidents": "Today Incidents", "operations24h": "24h Operations", "operationsTotal": "{total} total", "autoRemediationRate": "Auto Remediation", + "autoRepairVerified24h": "24h Verified Repair", + "autoRepairVerifiedCount": "verified {verified}/{evaluated}", + "autoRepairAllTime": "history {pct}% / {total}", + "latestIncidentWindow": "latest {shown} shown", + "truthChainCoverage": "truth-chain {loaded}/{shown}", + "truthChainLoading": "truth-chain loading", + "severityBreakdown": "P1:{p1} P2:{p2}", + "stableUnresolved": "{stable} · 0 {label}", "mttrAvg": "MTTR Avg", "stable": "Stable", "normal": "Normal", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 76abd1f5..ca18c2c4 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -143,12 +143,21 @@ "execution": "執行", "resolved": "完成" }, + "unresolvedIncidents": "未解事件", "activeIncidents": "活躍事件", "serviceHealth": "服務健康", "todayIncidents": "今日事件", "operations24h": "近 24h 操作", "operationsTotal": "總計 {total}", "autoRemediationRate": "自動處置率", + "autoRepairVerified24h": "24h 驗證修復率", + "autoRepairVerifiedCount": "已驗證 {verified}/{evaluated}", + "autoRepairAllTime": "歷史 {pct}% / {total} 筆", + "latestIncidentWindow": "首屏最新 {shown} 筆", + "truthChainCoverage": "truth-chain {loaded}/{shown}", + "truthChainLoading": "truth-chain 讀取中", + "severityBreakdown": "P1:{p1} P2:{p2}", + "stableUnresolved": "{stable} · 0 {label}", "mttrAvg": "MTTR 均值", "stable": "穩定", "normal": "正常", diff --git a/apps/web/src/app/[locale]/page.tsx b/apps/web/src/app/[locale]/page.tsx index 2131e218..8fe77a1d 100644 --- a/apps/web/src/app/[locale]/page.tsx +++ b/apps/web/src/app/[locale]/page.tsx @@ -36,6 +36,14 @@ const API_BASE = process.env.NEXT_PUBLIC_API_URL ?? '' const STATUS_CHAIN_PREFETCH_LIMIT = 25 const HOMEPAGE_INCIDENT_LIMIT = STATUS_CHAIN_PREFETCH_LIMIT +interface HomepageAutomationQualitySummary { + evaluated_total?: number + verified_auto_repair_total?: number + production_claim?: { + can_claim_full_auto_repair?: boolean + } +} + // ============================================================================= // Tab 2: 告警 & 授權 (串接真實 API) // ============================================================================= @@ -512,7 +520,11 @@ export default function Home({ params }: { params: { locale: string } }) { pollInterval: 15000, enablePolling: true, }) - const { statusChains } = useIncidentStatusChains({ + const { + statusChains, + requestedIncidentIds, + isLoading: isStatusChainsLoading, + } = useIncidentStatusChains({ incidentIds: incidents?.map(incident => incident.incident_id) ?? [], limit: STATUS_CHAIN_PREFETCH_LIMIT, refreshKey: incidentsLastUpdated?.toISOString() ?? null, @@ -534,6 +546,7 @@ export default function Home({ params }: { params: { locale: string } }) { // 2026-04-07 Claude Code: Sprint 4 E2 — 從 disposition API 取得真實自動化率 const [dispositionRate, setDispositionRate] = useState<{ auto_rate: number; total: number } | null>(null) + const [automationQuality, setAutomationQuality] = useState(null) useEffect(() => { fetch(`${API_BASE}/api/v1/stats/disposition`) .then(r => r.json()) @@ -542,22 +555,57 @@ export default function Home({ params }: { params: { locale: string } }) { }) .catch(() => {}) }, []) + useEffect(() => { + const controller = new AbortController() + fetch(`${API_BASE}/api/v1/platform/truth-chain/quality/summary?project_id=awoooi&hours=24&limit=30`, { + signal: controller.signal, + }) + .then(r => r.ok ? r.json() : null) + .then(d => { + if (!d) return + setAutomationQuality({ + evaluated_total: typeof d.evaluated_total === 'number' ? d.evaluated_total : undefined, + verified_auto_repair_total: typeof d.verified_auto_repair_total === 'number' ? d.verified_auto_repair_total : undefined, + production_claim: d.production_claim, + }) + }) + .catch(() => {}) + return () => controller.abort() + }, []) - // 自動處置率 — 優先使用 disposition API,fallback 到 incidents 推算 + // 自動處置率 — 首頁 KPI 使用 24h truth-chain 驗證率,避免把歷史 disposition 總表誤讀成今日閉環。 + const evaluatedAutomationTotal = automationQuality?.evaluated_total ?? 0 + const verifiedAutomationTotal = automationQuality?.verified_auto_repair_total ?? 0 const autoRemediationRate = (() => { - if (dispositionRate && dispositionRate.total > 0) { - return `${Math.round(dispositionRate.auto_rate * 100)}%` + if (evaluatedAutomationTotal > 0) { + return `${Math.round((verifiedAutomationTotal / evaluatedAutomationTotal) * 100)}%` } return '--' })() // 自動處置率數值 (for progress bar) const autoRemediationPct = (() => { - if (dispositionRate && dispositionRate.total > 0) { - return Math.round(dispositionRate.auto_rate * 100) + if (evaluatedAutomationTotal > 0) { + return Math.round((verifiedAutomationTotal / evaluatedAutomationTotal) * 100) } return 0 })() + const autoRemediationTone = automationQuality?.production_claim?.can_claim_full_auto_repair + ? '#22C55E' + : evaluatedAutomationTotal > 0 + ? '#F59E0B' + : '#141413' + const autoRemediationDetail = evaluatedAutomationTotal > 0 + ? tDashboard('autoRepairVerifiedCount', { + verified: verifiedAutomationTotal, + evaluated: evaluatedAutomationTotal, + }) + : dispositionRate && dispositionRate.total > 0 + ? tDashboard('autoRepairAllTime', { + pct: Math.round(dispositionRate.auto_rate * 100), + total: dispositionRate.total.toLocaleString(), + }) + : null // ── 5 KPI Cards (Sprint 5R 設計稿批准版) ──────────────────────────────────── @@ -567,6 +615,16 @@ export default function Home({ params }: { params: { locale: string } }) { const p2Count = incidents?.filter(i => i.severity === 'P2').length ?? 0 const visibleIncidents = incidents?.slice(0, HOMEPAGE_INCIDENT_LIMIT) ?? [] const hiddenIncidentCount = Math.max(incidentCount - visibleIncidents.length, 0) + const truthChainCoveredCount = requestedIncidentIds.filter((incidentId) => { + const chain = statusChains[incidentId] + return Boolean(chain && !chain.fetch_error && chain.source_id) + }).length + const truthChainCoverageLabel = isStatusChainsLoading + ? tDashboard('truthChainLoading') + : tDashboard('truthChainCoverage', { + loaded: truthChainCoveredCount, + shown: requestedIncidentIds.length, + }) const liveTopologyGroups = Object.values( hosts.reduce {/* 活動事件 */}
-
{tDashboard('activeIncidents')}
+
{tDashboard('unresolvedIncidents')}
0 ? '#d97757' : '#141413' }}>{incidentCount || '--'} - {incidentCount > 0 && P1:{p1Count} P2:{p2Count}} + {incidentCount > 0 && ( + + {tDashboard('severityBreakdown', { p1: p1Count, p2: p2Count })} + + )}
+ {visibleIncidents.length > 0 && ( +
+ {tDashboard('latestIncidentWindow', { shown: visibleIncidents.length })} +
+ )}
{/* 自動修復率 */}
-
{tDashboard('autoRemediationRate')}
+
{tDashboard('autoRepairVerified24h')}
- {autoRemediationRate} - {autoRemediationPct > 0 && {tDashboard('trendUp', { pct: autoRemediationPct })}} + {autoRemediationRate} + {autoRemediationDetail && {autoRemediationDetail}}
-
+
{/* 待審批 */} @@ -738,7 +805,7 @@ export default function Home({ params }: { params: { locale: string } }) { }}>
- {tDashboard('activeIncidents')} + {tDashboard('unresolvedIncidents')} {(incidents?.length ?? 0) > 0 && ( )} + {requestedIncidentIds.length > 0 && ( + + {truthChainCoverageLabel} + + )}
- {tDashboard('stable')} · 0 {tDashboard('activeIncidents')} + + {tDashboard('stableUnresolved', { + stable: tDashboard('stable'), + label: tDashboard('unresolvedIncidents'), + })} +
) : (
diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md index 62d74c38..ac96d5a9 100644 --- a/docs/LOGBOOK.md +++ b/docs/LOGBOOK.md @@ -19956,3 +19956,50 @@ format_governance_alert_card("knowledge_degradation", legacy payload) - CI/CD runner hygiene:約 96%。 - 治理告警可讀性 / 可處置性:約 90%。 - 完整 AI 自動化管理產品化:約 89.6%。 + +--- + +## 2026-05-25 T180 — 首頁 KPI / 小龍蝦流程條對齊 truth-chain + +**背景**: + +- 首頁上方 KPI 顯示「自動處置率 35%」,來源是 `/api/v1/stats/disposition` 的歷史累計總表;但 AwoooP Automation Evidence / truth-chain quality 近 24h 顯示 `verified_auto_repair_total=0 / evaluated_total=25`,容易讓 operator 誤解成目前 35% 事件已完成 AI 自動修復。 +- 「活躍事件」實際取自 `/api/v1/incidents` 未解事件列表,語意應改成「未解事件」,避免和真正 running / active stage 混淆。 +- 首頁事件流程條本身已能吃 status-chain truth source;缺口是畫面沒有明確顯示這批首屏事件的 truth-chain coverage,使用者無法看出流程條是 DB/truth-chain 還是 heuristic fallback。 + +**本輪修正**: + +- 首頁自動修復 KPI 改用 `/api/v1/platform/truth-chain/quality/summary?project_id=awoooi&hours=24&limit=30` 作為主要資料源。 +- KPI 顯示「24h 驗證修復率」與 `已驗證 {verified}/{evaluated}`,當 `production_claim.can_claim_full_auto_repair=false` 時用 amber 呈現,不再用綠色成功口吻包裝未驗證自動修復。 +- `/api/v1/stats/disposition` 只保留為 truth-chain quality 尚未載入時的歷史 fallback 文案,不再作為首頁主判斷。 +- 首頁事件區塊改為「未解事件」,並新增 `truth-chain {loaded}/{shown}` 覆蓋率 chip,讓 operator 直接看到小龍蝦流程條是否已對到 status-chain evidence。 +- 新增 zh-TW / en i18n key,未新增 mock data、未新增內網 IP、未新增新 API contract。 + +**local validation(完成)**: + +```text +jq empty apps/web/messages/zh-TW.json apps/web/messages/en.json +git diff --check +pnpm --dir apps/web exec tsc --noEmit --tsBuildInfoFile /tmp/awoooi-t180-tsconfig.tsbuildinfo +pnpm --dir apps/web lint -- --file 'src/app/[locale]/page.tsx' +NEXT_PUBLIC_API_URL=https://awoooi.wooo.work pnpm --dir apps/web run build +``` + +**local browser note**: + +- 本機 `localhost:30180` 預覽會被 production API CORS 擋住,所以 local Playwright 只能驗證靜態殼;首頁真實資料仍需以 Gitea CD 後的 production Playwright 為準。 + +**目前整體進度**: + +- AwoooP 告警可觀測鏈:約 99.34%。 +- 低風險自動修復閉環:約 95.8%。 +- 前端 AI 自動化管理介面同步:約 98.1%。 +- 首頁 KPI / 小龍蝦流程 truth alignment:約 96.5%。 +- Telegram 詳情 / 歷史可追溯:約 95.5%。 +- callback / DB replayability:約 96.0%。 +- MCP / 自建 MCP 可視化:約 88%。 +- Sentry / SigNoz source correlation:約 88%。 +- Ansible / PlayBook 可視化:約 85.2%。 +- KM governance:約 84%。 +- AI Provider lane visibility:約 92%。 +- 完整 AI 自動化管理產品化:約 95.6%。