From 2a180039d9c88a501096dbe19c9dc5201113dffe Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 28 Jun 2026 09:37:32 +0000 Subject: [PATCH] fix: render sentinel checks with user-facing labels --- .../monitor-web.js | 134 +++++++++++++++++- 1 file changed, 129 insertions(+), 5 deletions(-) diff --git a/scripts/assets/web-probe-sentinel-monitor-web/monitor-web.js b/scripts/assets/web-probe-sentinel-monitor-web/monitor-web.js index aac6e98b..a1d05fc1 100644 --- a/scripts/assets/web-probe-sentinel-monitor-web/monitor-web.js +++ b/scripts/assets/web-probe-sentinel-monitor-web/monitor-web.js @@ -3,6 +3,99 @@ import { createApp, computed, onMounted, ref, watch } from "./vendor/vue.esm-browser.prod.js"; const bootstrap = readBootstrap(); +const internalTextPattern = /水合|投影|Trace|trace|Shell|API|DOM|Console|console|Runner|runner|JSONL|steer|facts|分页|HTTP|http|requestfailed|pageerror|Final Response|Code Agent|web-probe|observe|analyzer|终态/u; +const checkDisplayCatalog = { + "code-agent-card-elapsed-missing": { + code: "CHECK-101", + title: "耗时未显示", + summary: "运行卡片没有显示总耗时,影响判断等待时间。", + }, + "code-agent-card-running-recent-update-missing": { + code: "CHECK-102", + title: "最近更新时间未显示", + summary: "运行中的卡片没有显示最近更新时间,影响判断是否仍在推进。", + }, + "turn-timing-total-elapsed-decrease": { + code: "CHECK-103", + title: "耗时显示回退", + summary: "相邻采样中的总耗时出现回退,作为非阻塞计时报警展示。", + }, + "page-loading-concurrent": { + code: "CHECK-201", + title: "多个加载状态同时出现", + summary: "同一采样点看到多个加载提示,用户可能难以判断当前页面是否已就绪。", + }, + "trace-events-page-read-requestfailed-root-cause": { + code: "CHECK-301", + title: "运行事件读取失败", + summary: "运行事件页面读取失败,需要结合服务端链路确认具体失败位置。", + }, + "runtime-requestfailed": { + code: "CHECK-302", + title: "页面资源加载失败", + summary: "巡检期间捕获到页面资源加载失败,可能影响用户看到的运行状态。", + }, + "runtime-console-alerts": { + code: "CHECK-303", + title: "页面脚本报警", + summary: "巡检期间捕获到页面脚本报警,需要评估是否影响用户操作。", + }, + "workbench-app-shell-transient-not-ready": { + code: "CHECK-304", + title: "工作台短暂未就绪", + summary: "工作台短时间内未完成主界面就绪,作为启动过程上下文保留。", + }, + "cross-page-projection-divergence": { + code: "CHECK-401", + title: "多页面状态不一致", + summary: "同一会话在两个页面中显示的状态持续不一致,可能影响用户判断。", + }, + "cross-page-projection-transient-divergence": { + code: "CHECK-402", + title: "多页面短暂不一致", + summary: "页面切换附近短暂出现显示差异,作为上下文保留。", + }, + "cross-page-projection-controlled-navigation-hydration": { + code: "CHECK-403", + title: "跳转后页面短暂空白", + summary: "页面跳转后短暂空白,当前按非阻塞上下文展示。", + }, + "cross-page-trace-visibility-divergence": { + code: "CHECK-404", + title: "运行记录显示数量不一致", + summary: "两个页面看到的运行记录数量不同,但未直接证明消息状态不一致。", + }, + "page-performance-slow-same-origin-api": { + code: "CHECK-501", + title: "页面数据加载慢", + summary: "页面数据加载超过配置预算,用户可能感觉等待时间过长。", + }, + "page-performance-long-lived-streams": { + code: "CHECK-502", + title: "长连接持续保持", + summary: "长时间连接单独统计,不直接作为页面加载慢处理。", + }, + "natural-api-dom-lag-baseline": { + code: "CHECK-503", + title: "数据变化可关联", + summary: "已采集到数据响应和页面变化样本,可用于分析显示延迟。", + }, + "natural-api-dom-lag-candidates": { + code: "CHECK-504", + title: "数据更新显示偏慢", + summary: "部分数据变化到页面显示的时间超过预算,作为非阻塞调查报警。", + }, + "browser-console-or-page-errors": { + code: "CHECK-601", + title: "页面脚本错误", + summary: "巡检期间捕获到页面脚本错误,需要确认是否影响用户流程。", + }, + "quick-verify-no-business-turn": { + code: "CHECK-701", + title: "业务轮次未完成", + summary: "巡检未确认到稳定的业务交互结果,不能作为恢复证据。", + }, +}; createApp({ setup() { @@ -816,19 +909,22 @@ function clamp(value, min, max) { } function rootCauseText(item) { - if (item?.checkSummaryZh) return item.checkSummaryZh; - if (item?.summary) return item.summary; - if (item?.evidenceSummary) return item.evidenceSummary; + const display = checkDisplay(item); + if (display.summary) return display.summary; + const safeSummary = safeUserText(item?.checkSummaryZh || item?.summary || item?.evidenceSummary); + if (safeSummary) return safeSummary; if (item?.rootCause) return "已记录内部根因,见报告详情。"; return "尚未记录用户可见问题摘要。"; } function findingTitle(item) { - return item?.checkTitleZh || item?.check?.titleZh || item?.findingId || item?.code || item?.scenarioId || item?.latestRunId || "未登记监测项"; + const display = checkDisplay(item); + if (display.title) return display.title; + return safeUserText(item?.checkTitleZh || item?.check?.titleZh) || "未登记监测项"; } function findingCode(item) { - return item?.checkCode || item?.check?.code || "未登记"; + return checkDisplay(item).code; } function levelLabel(item) { @@ -869,6 +965,34 @@ function findingSearchText(item) { ].filter((value) => value !== null && value !== undefined).join(" ").toLowerCase(); } +function checkDisplay(item) { + const rawCode = rawCheckCode(item); + const registered = checkDisplayCatalog[rawCode]; + if (registered) return registered; + return { + code: stableCheckCode(rawCode), + title: safeUserText(item?.checkTitleZh || item?.check?.titleZh) || "未登记监测项", + summary: safeUserText(item?.checkSummaryZh || item?.summary || item?.evidenceSummary) || "已记录监测项详情,见报告原文。", + }; +} + +function rawCheckCode(item) { + return String(item?.checkCode || item?.check?.code || item?.code || item?.findingId || item?.kind || "unknown"); +} + +function stableCheckCode(value) { + const text = String(value || "unknown"); + let hash = 0; + for (let index = 0; index < text.length; index += 1) hash = (hash * 31 + text.charCodeAt(index)) >>> 0; + return `CHECK-${String(hash % 10000).padStart(4, "0")}`; +} + +function safeUserText(value) { + const text = String(value || "").replace(/\s+/g, " ").trim(); + if (text.length === 0 || internalTextPattern.test(text)) return ""; + return text; +} + function detailSummaryText(detail) { return detailSummaryRows(detail).map((row) => `${row.label}: ${row.value}`).join("\n"); }