diff --git a/config/hwlab-web-probe-sentinel/check-catalog.yaml b/config/hwlab-web-probe-sentinel/check-catalog.yaml index 866d91ae..74614bc6 100644 --- a/config/hwlab-web-probe-sentinel/check-catalog.yaml +++ b/config/hwlab-web-probe-sentinel/check-catalog.yaml @@ -22,6 +22,7 @@ sentinel: level: error titleZh: 刷新后终端内容没更新 summaryZh: 后台已有新内容,但页面终端区域仍显示旧内容。 + actionZh: 查看详情后处理。 blocking: true order: 10 - code: WBC-002 @@ -29,6 +30,7 @@ sentinel: level: error titleZh: 终端记录缺失 summaryZh: 会话已有过程记录,但终端区域没有显示出来。 + actionZh: 查看详情后处理。 blocking: true order: 20 - code: WBC-003 @@ -36,6 +38,7 @@ sentinel: level: error titleZh: 快速验证没有有效对话 summaryZh: 快速验证没有看到稳定会话、过程记录或最终回复。 + actionZh: 查看详情后处理。 blocking: true order: 30 - code: WBC-004 @@ -43,6 +46,7 @@ sentinel: level: error titleZh: 快速验证步骤失败 summaryZh: 快速验证的操作步骤没有完整执行。 + actionZh: 查看详情后处理。 blocking: true order: 40 - code: WBC-005 @@ -50,6 +54,7 @@ sentinel: level: error titleZh: 页面观察未启动 summaryZh: 快速验证前未能打开页面观察环境。 + actionZh: 查看详情后处理。 blocking: true order: 50 - code: WBC-006 @@ -57,6 +62,7 @@ sentinel: level: error titleZh: 验证账号未配置 summaryZh: 快速验证所需账号或密钥缺失。 + actionZh: 查看详情后处理。 blocking: true order: 60 - code: WBC-007 @@ -64,6 +70,7 @@ sentinel: level: error titleZh: 消息发送失败 summaryZh: 用户消息提交后没有观察到成功发送结果。 + actionZh: 查看详情后处理。 blocking: true order: 70 - code: WBC-008 @@ -71,6 +78,7 @@ sentinel: level: error titleZh: 页面操作失败 summaryZh: 自动页面操作没有成功执行。 + actionZh: 查看详情后处理。 blocking: true order: 80 - code: WBC-009 @@ -78,6 +86,7 @@ sentinel: level: error titleZh: 当前会话不一致 summaryZh: 地址栏中的会话与页面当前会话不一致。 + actionZh: 查看详情后处理。 blocking: true order: 90 - code: WBC-010 @@ -85,6 +94,7 @@ sentinel: level: warning titleZh: 返回页面后消息顺序异常 summaryZh: 导航或刷新后,消息顺序看起来不符合对话顺序。 + actionZh: 查看详情后处理。 blocking: false order: 100 - code: WBC-011 @@ -92,6 +102,7 @@ sentinel: level: error titleZh: 两个页面内容不一致 summaryZh: 同一会话在两个页面中显示了不同内容。 + actionZh: 查看详情后处理。 blocking: true order: 110 - code: WBC-012 @@ -99,6 +110,7 @@ sentinel: level: info titleZh: 页面切换时短暂不一致 summaryZh: 页面切换附近短时间显示了不同内容。 + actionZh: 查看详情后处理。 blocking: false order: 120 - code: WBC-013 @@ -106,6 +118,7 @@ sentinel: level: info titleZh: 返回页面后内容短暂不同步 summaryZh: 导航返回后,页面内容短时间没有完全同步。 + actionZh: 查看详情后处理。 blocking: false order: 130 - code: WBC-014 @@ -113,6 +126,7 @@ sentinel: level: info titleZh: 页面未完全打开导致差异 summaryZh: 内容差异发生在页面主体尚未完全打开时。 + actionZh: 查看详情后处理。 blocking: false order: 140 - code: WBC-015 @@ -120,6 +134,7 @@ sentinel: level: info titleZh: 两个页面记录数量不同 summaryZh: 两个页面显示的过程记录数量不同。 + actionZh: 查看详情后处理。 blocking: false order: 150 - code: WBC-016 @@ -127,6 +142,7 @@ sentinel: level: error titleZh: Workbench 页面未打开完整 summaryZh: Workbench 地址已打开,但主要工作区没有正常显示。 + actionZh: 查看详情后处理。 blocking: true order: 160 - code: WBC-017 @@ -134,6 +150,7 @@ sentinel: level: info titleZh: Workbench 短暂未显示 summaryZh: Workbench 打开过程中短时间没有显示主要工作区。 + actionZh: 查看详情后处理。 blocking: false order: 170 - code: WBC-018 @@ -141,6 +158,7 @@ sentinel: level: warning titleZh: 过程记录缺少结束状态 summaryZh: 页面显示了过程记录,但没有看到对应的结束状态。 + actionZh: 查看详情后处理。 blocking: false order: 180 - code: WBC-019 @@ -148,6 +166,7 @@ sentinel: level: error titleZh: 对话回合缺少追踪编号 summaryZh: 页面显示了对话回合,但缺少可用于排查的编号。 + actionZh: 查看详情后处理。 blocking: true order: 190 - code: WBC-020 @@ -155,6 +174,7 @@ sentinel: level: warning titleZh: 最终回复重复显示 summaryZh: 页面上重复显示了助手最终回复。 + actionZh: 查看详情后处理。 blocking: false order: 200 - code: WBC-021 @@ -162,6 +182,7 @@ sentinel: level: error titleZh: 最终回复显示不稳定 summaryZh: 最终回复在观察期间出现闪烁或变化。 + actionZh: 查看详情后处理。 blocking: true order: 210 - code: WBC-022 @@ -169,6 +190,7 @@ sentinel: level: error titleZh: 完成后无最终回复 summaryZh: 回合完成后缺少最终回复内容。 + actionZh: 查看详情后处理。 blocking: true order: 220 - code: WBC-023 @@ -176,6 +198,7 @@ sentinel: level: error titleZh: 过程记录页面打不开 summaryZh: 打开更早的过程记录时返回未找到。 + actionZh: 查看详情后处理。 blocking: true order: 230 - code: WBC-024 @@ -183,6 +206,7 @@ sentinel: level: error titleZh: 过程记录加载失败 summaryZh: 打开更早的过程记录时页面返回错误。 + actionZh: 查看详情后处理。 blocking: true order: 240 - code: WBC-025 @@ -190,6 +214,7 @@ sentinel: level: warning titleZh: 过程记录加载中断 summaryZh: 打开更早的过程记录时网络请求中断。 + actionZh: 查看详情后处理。 blocking: false order: 250 - code: WBC-026 @@ -197,6 +222,7 @@ sentinel: level: warning titleZh: 页面请求返回错误 summaryZh: 页面加载过程中有请求返回错误状态。 + actionZh: 查看详情后处理。 blocking: false order: 260 - code: WBC-027 @@ -204,6 +230,7 @@ sentinel: level: warning titleZh: 页面请求中断 summaryZh: 页面加载过程中有网络请求未完成。 + actionZh: 查看详情后处理。 blocking: false order: 270 - code: WBC-028 @@ -211,6 +238,7 @@ sentinel: level: warning titleZh: 页面出现错误提示 summaryZh: 页面内容中出现错误或警告提示文本。 + actionZh: 查看详情后处理。 blocking: false order: 280 - code: WBC-029 @@ -218,6 +246,7 @@ sentinel: level: error titleZh: 任务执行失败 summaryZh: Workbench 页面显示任务执行失败。 + actionZh: 查看详情后处理。 blocking: true order: 290 - code: WBC-030 @@ -225,6 +254,7 @@ sentinel: level: warning titleZh: 浏览器记录到告警 summaryZh: 浏览器运行日志记录到警告或错误。 + actionZh: 查看详情后处理。 blocking: false order: 300 - code: WBC-031 @@ -232,6 +262,7 @@ sentinel: level: warning titleZh: 页面运行异常 summaryZh: 页面运行过程中捕获到异常。 + actionZh: 查看详情后处理。 blocking: false order: 310 - code: WBC-032 @@ -239,6 +270,7 @@ sentinel: level: error titleZh: 页面响应过慢 summaryZh: 页面加载数据的耗时超过配置预算。 + actionZh: 查看详情后处理。 blocking: true order: 320 - code: WBC-033 @@ -246,6 +278,7 @@ sentinel: level: error titleZh: 实时连接建立过慢 summaryZh: 页面建立实时连接的耗时超过配置预算。 + actionZh: 查看详情后处理。 blocking: true order: 330 - code: WBC-034 @@ -253,6 +286,7 @@ sentinel: level: info titleZh: 页面存在实时连接 summaryZh: 页面打开了用于持续更新内容的连接,作为上下文保留。 + actionZh: 查看详情后处理。 blocking: false order: 340 - code: WBC-035 @@ -260,6 +294,7 @@ sentinel: level: info titleZh: 页面版本发生切换 summaryZh: 观察期间页面资源版本发生变化,排查时需要注意前后差异。 + actionZh: 查看详情后处理。 blocking: false order: 350 - code: WBC-036 @@ -267,6 +302,7 @@ sentinel: level: info titleZh: 已收集页面更新基线 summaryZh: 已收集后台数据变化到页面显示变化的基础样本。 + actionZh: 查看详情后处理。 blocking: false order: 360 - code: WBC-037 @@ -274,6 +310,7 @@ sentinel: level: info titleZh: 页面更新可能滞后 summaryZh: 后台数据变化后,页面显示可能存在滞后样本。 + actionZh: 查看详情后处理。 blocking: false order: 370 - code: WBC-038 @@ -281,6 +318,7 @@ sentinel: level: warning titleZh: 总耗时突然归零 summaryZh: 已显示的总耗时突然回到 0。 + actionZh: 查看详情后处理。 blocking: false order: 380 - code: WBC-039 @@ -288,6 +326,7 @@ sentinel: level: warning titleZh: 总耗时倒退 summaryZh: 相邻观察点中,总耗时变小。 + actionZh: 查看详情后处理。 blocking: false order: 390 - code: WBC-040 @@ -295,6 +334,7 @@ sentinel: level: warning titleZh: 总耗时突然跳大 summaryZh: 总耗时增长速度明显快于实际观察间隔。 + actionZh: 查看详情后处理。 blocking: false order: 400 - code: WBC-041 @@ -302,6 +342,7 @@ sentinel: level: warning titleZh: 完成后耗时仍增长 summaryZh: 回合完成后总耗时仍继续变化。 + actionZh: 查看详情后处理。 blocking: false order: 410 - code: WBC-042 @@ -309,6 +350,7 @@ sentinel: level: warning titleZh: 最近更新跳变 summaryZh: 最近更新时间显示出现异常跳变。 + actionZh: 查看详情后处理。 blocking: false order: 420 - code: WBC-043 @@ -316,6 +358,7 @@ sentinel: level: warning titleZh: 回合耗时过长 summaryZh: 回合总耗时超过配置的告警阈值。 + actionZh: 查看详情后处理。 blocking: false order: 430 - code: WBC-044 @@ -323,6 +366,7 @@ sentinel: level: error titleZh: 页面一直显示加载中 summaryZh: 页面可见加载状态持续时间超过配置预算。 + actionZh: 查看详情后处理。 blocking: true order: 440 - code: WBC-045 @@ -330,6 +374,7 @@ sentinel: level: info titleZh: 页面同时显示多个加载中 summaryZh: 同一时刻页面出现多个加载中提示。 + actionZh: 查看详情后处理。 blocking: false order: 450 - code: WBC-046 @@ -337,6 +382,7 @@ sentinel: level: error titleZh: 会话标题显示为兜底内容 summaryZh: 会话栏没有显示正常标题,而是显示了兜底内容。 + actionZh: 查看详情后处理。 blocking: true order: 460 - code: WBC-047 @@ -344,6 +390,7 @@ sentinel: level: warning titleZh: 页面滚动位置异常跳动 summaryZh: 没有明显用户操作时,页面滚动位置跳到顶部附近。 + actionZh: 查看详情后处理。 blocking: false order: 470 - code: WBC-048 @@ -351,6 +398,7 @@ sentinel: level: warning titleZh: 卡片耗时不一致 summaryZh: 页面卡片上的耗时与实际观察到的耗时不一致。 + actionZh: 查看详情后处理。 blocking: false order: 480 - code: WBC-049 @@ -358,6 +406,7 @@ sentinel: level: warning titleZh: 完成耗时不一致 summaryZh: 回合完成状态前后的耗时显示不一致。 + actionZh: 查看详情后处理。 blocking: false order: 490 - code: WBC-050 @@ -365,6 +414,7 @@ sentinel: level: warning titleZh: 完成后耗时变化 summaryZh: 回合完成后仍出现耗时变化。 + actionZh: 查看详情后处理。 blocking: false order: 500 - code: WBC-051 @@ -372,6 +422,7 @@ sentinel: level: info titleZh: 完成后仍显示最近更新 summaryZh: 回合完成后仍保留最近更新时间显示。 + actionZh: 查看详情后处理。 blocking: false order: 510 - code: WBC-052 @@ -379,6 +430,7 @@ sentinel: level: error titleZh: 没有采样数据 summaryZh: 本次观察没有产生可分析的页面样本。 + actionZh: 查看详情后处理。 blocking: true order: 520 - code: WBC-053 @@ -386,6 +438,7 @@ sentinel: level: error titleZh: 样本文件读取失败 summaryZh: 观察样本文件无法读取或解析。 + actionZh: 查看详情后处理。 blocking: true order: 530 - code: WBC-054 @@ -393,6 +446,7 @@ sentinel: level: warning titleZh: 消息发送路径异常 summaryZh: 用户消息走了非预期发送路径,需要确认上一回合状态。 + actionZh: 查看详情后处理。 blocking: false order: 540 - code: WBC-055 @@ -400,6 +454,7 @@ sentinel: level: error titleZh: 观察程序心跳过期 summaryZh: 页面观察程序长时间没有更新心跳。 + actionZh: 查看详情后处理。 blocking: true order: 550 - code: WBC-056 @@ -407,6 +462,7 @@ sentinel: level: error titleZh: 页面操作未被执行 summaryZh: 存在等待执行但页面尚未处理的操作。 + actionZh: 查看详情后处理。 blocking: true order: 560 - code: WBC-057 @@ -414,6 +470,7 @@ sentinel: level: info titleZh: 历史页面操作遗留 summaryZh: 观察过程中发现遗留的历史页面操作。 + actionZh: 查看详情后处理。 blocking: false order: 570 - code: WBC-058 @@ -421,6 +478,7 @@ sentinel: level: info titleZh: 观察程序被强制停止 summaryZh: 页面观察程序被控制面强制停止,作为上下文保留。 + actionZh: 查看详情后处理。 blocking: false order: 580 - code: WBC-059 @@ -428,5 +486,294 @@ sentinel: level: warning titleZh: 项目入口请求失败 summaryZh: 打开项目或进入 Workbench 的页面请求没有成功完成。 + actionZh: 查看详情后处理。 blocking: false order: 590 + - code: WBC-060 + id: active-session-changed + level: warning + titleZh: 当前会话意外切换 + summaryZh: 页面当前会话在非预期窗口内发生切换。 + actionZh: 查看详情后处理。 + blocking: false + order: 600 + - code: WBC-061 + id: code-agent-card-duration-underreported + level: warning + titleZh: 卡片耗时偏小 + summaryZh: 页面卡片显示的耗时小于观察到的实际耗时。 + actionZh: 查看详情后处理。 + blocking: false + order: 610 + - code: WBC-062 + id: code-agent-card-elapsed-missing + level: warning + titleZh: 卡片未显示总耗时 + summaryZh: 页面运行卡片没有显示总耗时,影响判断等待时间。 + actionZh: 查看详情后处理。 + blocking: false + order: 620 + - code: WBC-063 + id: code-agent-card-running-recent-update-missing + level: warning + titleZh: 卡片未显示最近更新 + summaryZh: 运行中的页面卡片没有显示最近更新时间。 + actionZh: 查看详情后处理。 + blocking: false + order: 630 + - code: WBC-064 + id: frontend-browser-freeze-runner-blocker + level: error + titleZh: 浏览器冻结已阻塞 + summaryZh: 浏览器冻结策略已触发,巡检中止页面并报红。 + actionZh: 查看详情后处理。 + blocking: true + order: 640 + - code: WBC-065 + id: frontend-browser-memory-growth-red + level: error + titleZh: 页面内存持续增长 + summaryZh: 页面有效内存在观察窗口内持续增长并超过配置预算。 + actionZh: 查看详情后处理。 + blocking: true + order: 650 + - code: WBC-066 + id: frontend-browser-memory-rss-red + level: error + titleZh: 页面内存超出预算 + summaryZh: 页面有效内存超过配置红线,已按阻塞错误展示。 + actionZh: 查看详情后处理。 + blocking: true + order: 660 + - code: WBC-067 + id: frontend-cdp-metrics-timeout-red + level: error + titleZh: 浏览器指标采集超时 + summaryZh: 浏览器侧指标连续采集超时,说明页面运行时可能已经无响应。 + actionZh: 查看详情后处理。 + blocking: false + order: 670 + - code: WBC-068 + id: frontend-control-dom-evaluate-timeout-red + level: error + titleZh: 控制页面响应超时 + summaryZh: 控制页面的页面脚本执行连续超时,符合前端无响应特征。 + actionZh: 查看详情后处理。 + blocking: true + order: 680 + - code: WBC-069 + id: frontend-observer-dom-evaluate-timeout-red + level: error + titleZh: 观察页面响应超时 + summaryZh: 观察页面的页面脚本执行连续超时,符合前端无响应特征。 + actionZh: 查看详情后处理。 + blocking: true + order: 690 + - code: WBC-070 + id: frontend-page-error-red + level: error + titleZh: 页面错误连续出现 + summaryZh: 页面运行错误在观察窗口内连续出现,已按红色监测项展示。 + actionZh: 查看详情后处理。 + blocking: true + order: 700 + - code: WBC-071 + id: frontend-playwright-responsiveness-red + level: error + titleZh: 页面响应探测超时 + summaryZh: 页面响应探测超过配置预算,已按前端卡死处理并报红。 + actionZh: 查看详情后处理。 + blocking: true + order: 710 + - code: WBC-072 + id: frontend-screenshot-timeout-red + level: error + titleZh: 页面截图连续超时 + summaryZh: 页面截图在观察窗口内连续超时,说明页面可能已经无响应。 + actionZh: 查看详情后处理。 + blocking: true + order: 720 + - code: WBC-073 + id: mdtodo-file-label-not-filename + level: error + titleZh: MDTODO 文件名显示异常 + summaryZh: MDTODO 文件下拉框当前选择项不是直接的 Markdown 文件名。 + actionZh: 查看详情后处理。 + blocking: true + order: 730 + - code: WBC-074 + id: mdtodo-hwpod-node-disconnected + level: error + titleZh: HWPOD 节点未连接 + summaryZh: MDTODO 页面显示 HWPOD 节点连接不可用。 + actionZh: 查看详情后处理。 + blocking: true + order: 740 + - code: WBC-075 + id: mdtodo-nondirect-files-visible + level: error + titleZh: MDTODO 文件列表混入非直接文件 + summaryZh: MDTODO 文件下拉框出现非直接文件或报告类条目。 + actionZh: 查看详情后处理。 + blocking: true + order: 750 + - code: WBC-076 + id: mdtodo-pane-bottom-gap + level: error + titleZh: MDTODO 面板底部空白过大 + summaryZh: MDTODO 任务树、详情或报告区域存在影响操作的大块底部空白。 + actionZh: 查看详情后处理。 + blocking: true + order: 760 + - code: WBC-077 + id: mdtodo-report-fullscreen-missing + level: error + titleZh: 报告全屏未打开 + summaryZh: 执行报告全屏操作后没有观察到全屏报告对话框。 + actionZh: 查看详情后处理。 + blocking: true + order: 770 + - code: WBC-078 + id: mdtodo-report-preview-missing + level: error + titleZh: 报告预览未显示 + summaryZh: 页面有报告入口,但没有观察到 Markdown 报告预览。 + actionZh: 查看详情后处理。 + blocking: true + order: 780 + - code: WBC-079 + id: mdtodo-report-projection-only + level: error + titleZh: 报告只显示投影内容 + summaryZh: MDTODO 报告预览只显示投影内容,没有打开源报告正文。 + actionZh: 查看详情后处理。 + blocking: true + order: 790 + - code: WBC-080 + id: mdtodo-task-body-not-visible + level: error + titleZh: MDTODO 任务正文不可见 + summaryZh: 已选择 MDTODO 任务,但页面没有显示任务正文。 + actionZh: 查看详情后处理。 + blocking: true + order: 800 + - code: WBC-081 + id: mdtodo-task-count-diverged + level: warning + titleZh: MDTODO 任务数量波动 + summaryZh: 观察期间 MDTODO 任务数量出现明显波动。 + actionZh: 查看详情后处理。 + blocking: false + order: 810 + - code: WBC-082 + id: mdtodo-taskref-missing + level: error + titleZh: MDTODO 任务缺少稳定编号 + summaryZh: MDTODO 任务行可见,但缺少稳定任务引用编号。 + actionZh: 查看详情后处理。 + blocking: true + order: 820 + - code: WBC-083 + id: mdtodo-workbench-launch-empty + level: error + titleZh: Workbench 启动后内容为空 + summaryZh: 从 MDTODO 启动 Workbench 后没有观察到对话或过程记录内容。 + actionZh: 查看详情后处理。 + blocking: true + order: 830 + - code: WBC-084 + id: mdtodo-workbench-launch-failed + level: error + titleZh: Workbench 启动失败 + summaryZh: 从 MDTODO 启动 Workbench 的操作失败或返回错误。 + actionZh: 查看详情后处理。 + blocking: true + order: 840 + - code: WBC-085 + id: mdtodo-workbench-launch-otel-trace-missing + level: warning + titleZh: Workbench 启动缺少追踪编号 + summaryZh: Workbench 启动成功,但没有采集到可用于链路排查的追踪编号。 + actionZh: 查看详情后处理。 + blocking: false + order: 850 + - code: WBC-086 + id: project-management-api-slow + level: error + titleZh: 项目管理接口过慢 + summaryZh: 项目管理页面接口耗时超过配置预算。 + actionZh: 查看详情后处理。 + blocking: true + order: 860 + - code: WBC-087 + id: project-management-hwpod-api-failed + level: error + titleZh: HWPOD 项目接口失败 + summaryZh: HWPOD 支撑的任务详情或报告接口返回服务错误。 + actionZh: 查看详情后处理。 + blocking: true + order: 870 + - code: WBC-088 + id: project-management-route-not-ready + level: error + titleZh: 项目管理页面未就绪 + summaryZh: 已打开项目管理目标路径,但页面摘要没有正常出现。 + actionZh: 查看详情后处理。 + blocking: true + order: 880 + - code: WBC-089 + id: session-route-changed + level: warning + titleZh: 地址栏会话意外切换 + summaryZh: 地址栏会话在非预期窗口内发生切换。 + actionZh: 查看详情后处理。 + blocking: false + order: 890 + - code: WBC-090 + id: trace-completion-row-not-last + level: error + titleZh: 完成记录不是最后一行 + summaryZh: 过程记录中完成状态后仍出现后续记录,影响判断终态。 + actionZh: 查看详情后处理。 + blocking: true + order: 900 + - code: WBC-091 + id: trace-row-order-nonmonotonic + level: error + titleZh: 过程记录顺序异常 + summaryZh: 过程记录的行顺序不是单调递增,影响排查和终态判断。 + actionZh: 查看详情后处理。 + blocking: true + order: 910 + - code: WBC-092 + id: turn-terminal-zero-elapsed + level: warning + titleZh: 终态耗时显示为零 + summaryZh: 已完成回合的页面卡片仍显示总耗时为 0 秒。 + actionZh: 查看详情后处理。 + blocking: false + order: 920 + - code: WBC-093 + id: uncommanded-visible-state-change + level: warning + titleZh: 页面状态无操作变化 + summaryZh: 没有对应用户操作时,页面可见消息或过程记录发生变化。 + actionZh: 查看详情后处理。 + blocking: false + order: 930 + - code: WBC-094 + id: workbench-controlled-navigation-degraded-root-cause + level: error + titleZh: 受控导航后页面退化 + summaryZh: Workbench 受控导航后页面状态退化,影响后续观察。 + actionZh: 查看详情后处理。 + blocking: true + order: 940 + - code: WBC-095 + id: workbench-launch-button-unavailable + level: error + titleZh: Workbench 启动按钮不可用 + summaryZh: MDTODO 任务可见,但 Workbench 启动按钮一直不可用。 + actionZh: 查看详情后处理。 + blocking: true + order: 950 diff --git a/scripts/assets/web-probe-sentinel-monitor-web/monitor-web.css b/scripts/assets/web-probe-sentinel-monitor-web/monitor-web.css index 1b667f49..b35b5c9d 100644 --- a/scripts/assets/web-probe-sentinel-monitor-web/monitor-web.css +++ b/scripts/assets/web-probe-sentinel-monitor-web/monitor-web.css @@ -343,30 +343,12 @@ select { font-size: 13px; } -.trend-red { - fill: none; - stroke: var(--red); - stroke-width: 3; - stroke-linecap: round; - stroke-linejoin: round; -} - -.trend-warning { - fill: none; - stroke: var(--amber); - stroke-width: 3; - stroke-linecap: round; - stroke-linejoin: round; -} - -.trend-total { +.trend-duration { fill: none; stroke: var(--blue); - stroke-width: 2; - stroke-dasharray: 5 6; + stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; - opacity: 0.75; } .trend-grid-line { @@ -374,12 +356,10 @@ select { stroke-width: 1; } -.trend-dot-red { - fill: var(--red); -} - -.trend-dot-warning { - fill: var(--amber); +.trend-dot-duration { + fill: var(--blue); + stroke: #ffffff; + stroke-width: 1.5; } .trend-dot-hit { @@ -450,6 +430,10 @@ select { background: var(--red); } +.legend-swatch.duration { + background: var(--blue); +} + .legend-swatch.warning { background: var(--amber); } 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 092cfe06..2db380d6 100644 --- a/scripts/assets/web-probe-sentinel-monitor-web/monitor-web.js +++ b/scripts/assets/web-probe-sentinel-monitor-web/monitor-web.js @@ -4,123 +4,6 @@ import { createApp, computed, onMounted, ref, watch } from "./vendor/vue.esm-bro 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: "巡检未确认到稳定的业务交互结果,不能作为恢复证据。", - }, - "frontend-browser-memory-rss-red": { - code: "CHECK-801", - title: "页面内存超出预算", - summary: "页面有效内存超过配置红线,已按阻塞错误展示。", - }, - "frontend-browser-memory-growth-red": { - code: "CHECK-802", - title: "页面内存持续增长", - summary: "页面有效内存在观察窗口内持续增长并超过配置预算,符合卡死风险特征。", - }, - "frontend-browser-freeze-runner-blocker": { - code: "CHECK-803", - title: "浏览器冻结已阻塞", - summary: "浏览器冻结策略已触发,巡检中止页面并报红,不能用刷新或兜底掩盖。", - }, - "frontend-playwright-responsiveness-red": { - code: "CHECK-804", - title: "页面响应探测超时", - summary: "页面响应探测超过配置预算,已按前端卡死处理并报红。", - }, - "frontend-cdp-metrics-timeout-red": { - code: "CHECK-805", - title: "浏览器指标采集超时", - summary: "浏览器侧指标连续采集超时,说明页面运行时可能已经无响应。", - }, -}; createApp({ setup() { @@ -165,19 +48,18 @@ createApp({ const selectedRun = computed(() => runs.value.find((run) => run.id === selectedRunId.value) || latestRun.value); const trendRows = computed(() => runs.value.slice().sort((a, b) => Date.parse(a.updatedAt || a.createdAt || "") - Date.parse(b.updatedAt || b.createdAt || "")).slice(-48)); const latestTrendRun = computed(() => trendRows.value.length > 0 ? trendRows.value[trendRows.value.length - 1] : latestRun.value); - const trendMax = computed(() => Math.max(1, ...trendRows.value.flatMap((run) => [trendErrorCount(run), trendWarningCount(run), trendTotalCount(run)]))); + const trendDurationMax = computed(() => Math.max(0, ...trendRows.value.map((run) => trendDurationMinutes(run)))); + const trendMax = computed(() => Math.max(1, trendDurationMax.value)); const trendPolylines = computed(() => ({ - red: trendPolyline((run) => trendErrorCount(run)), - warning: trendPolyline((run) => trendWarningCount(run)), - total: trendPolyline((run) => trendTotalCount(run)), + duration: trendPolyline((run) => trendDurationMinutes(run)), })); const trendDots = computed(() => trendRows.value.map((run, index) => { const red = trendErrorCount(run); const warning = trendWarningCount(run); const total = trendTotalCount(run); + const duration = trendDurationMinutes(run); const x = trendX(index, trendRows.value.length); - const redY = trendY(red); - const warningY = trendY(warning); + const durationY = trendY(duration); const rawTime = run.updatedAt || run.createdAt || ""; const durationText = runDurationText(run); const configTimingText = runTimingConfigText(run); @@ -185,10 +67,10 @@ createApp({ id: run.id || String(index), runId: run.id || "", x, - redY, - warningY, + durationY, + duration, tooltipLeft: `${clamp((x / 720) * 100, 16, 84)}%`, - tooltipTop: `${clamp(((Math.min(redY, warningY) + 18) / 142) * 100, 24, 76)}%`, + tooltipTop: `${clamp(((durationY + 18) / 142) * 100, 24, 76)}%`, red, warning, total, @@ -363,6 +245,10 @@ createApp({ return runCheckAlertCount(run); } + function trendDurationMinutes(run) { + return number(run?.runDurationMinutes ?? run?.durationMinutes ?? run?.timing?.durationMinutes); + } + function openCheckDetail(item) { activeCheckItem.value = item || null; } @@ -459,6 +345,7 @@ createApp({ selectedRun, trendRows, latestTrendRun, + trendDurationMax, trendPolylines, trendDots, timelineRuns, @@ -492,12 +379,14 @@ createApp({ trendTotalCount, trendErrorCount, trendWarningCount, + trendDurationMinutes, runDurationText, runTimingConfigText, severityClass, formatDate, formatAbsoluteDate, formatDuration, + formatMinutes, shortId, rootCauseText, findingTitle, @@ -566,19 +455,17 @@ createApp({
-

错误 / 告警监测项曲线

-

按运行更新时间展示最近 {{ trendRows.length }} 次变化,点位为单次运行监测项行数

+

运行耗时曲线

+

按运行更新时间展示最近 {{ trendRows.length }} 次巡检耗时,单位为分钟

{{ cadence.stale ? "非阻塞报警" : "新鲜" }}
- + - - - + - - - {{ dot.title }} - - + + {{ dot.title }} @@ -617,9 +501,9 @@ createApp({
暂无运行数据
- 最新点错误 {{ trendErrorCount(latestTrendRun) }} - 最新点告警 {{ trendWarningCount(latestTrendRun) }} - 最新点错误+告警合计 {{ trendTotalCount(latestTrendRun) }} + 最新运行耗时 {{ runDurationText(latestTrendRun) }} + 最近最高耗时 {{ formatMinutes(trendDurationMax) }} + 最新错误 {{ trendErrorCount(latestTrendRun) }} / 告警 {{ trendWarningCount(latestTrendRun) }} 历史样本累计 错误 {{ redCount({ severityCounts: severityTotals }) }} / 告警 {{ warningCount({ severityCounts: severityTotals }) }} {{ cadence.alert }}
@@ -1127,7 +1011,7 @@ function clamp(value, min, max) { function rootCauseText(item) { const display = checkDisplay(item); if (display.summary) return display.summary; - const safeSummary = safeUserText(item?.checkSummaryZh || item?.summary || item?.evidenceSummary); + const safeSummary = safeUserText(item?.checkSummaryZh || item?.check?.summaryZh); if (safeSummary) return safeSummary; if (item?.rootCause) return "已记录内部根因,见报告详情。"; return "尚未记录用户可见问题摘要。"; @@ -1201,7 +1085,8 @@ function checkTimeText(item) { } function checkActionText(item) { - return safeUserText(item?.nextAction || item?.action || item?.recommendation) || "查看详情后处理"; + const display = checkDisplay(item); + return display.action || safeUserText(item?.checkActionZh || item?.check?.actionZh) || "查看详情后处理"; } function checkDetailRows(item) { @@ -1223,7 +1108,7 @@ function checkEvidenceRows(item) { if (!item) return [{ key: "empty", label: "状态", value: "未选择监测项" }]; const evidence = item?.evidence && typeof item.evidence === "object" && !Array.isArray(item.evidence) ? item.evidence : {}; const rows = [ - { key: "summary", label: "证据摘要", value: safeUserText(item?.evidenceSummary || evidence.summary || item?.summary) || rootCauseText(item) }, + { key: "summary", label: "证据摘要", value: rootCauseText(item) || safeUserText(item?.evidenceSummary || evidence.summary) }, { key: "sample", label: "样本序号", value: safeDetailValue(item?.sampleSeq ?? evidence.sampleSeq) }, { key: "page", label: "页面", value: safeDetailValue(item?.pageRole || evidence.pageRole) }, { key: "command", label: "命令编号", value: safeDetailValue(item?.commandId || evidence.commandId) }, @@ -1254,20 +1139,12 @@ function safeDetailValue(value) { function checkDisplay(item) { const rawCode = rawCheckCode(item); const rawId = rawFindingId(item); - const registered = checkDisplayCatalog[rawId] || checkDisplayCatalog[rawCode]; const serviceCode = publicCheckCode(item?.checkCode || item?.check?.code); - if (registered) { - return { - ...registered, - code: serviceCode || registered.code, - title: safeUserText(item?.checkTitleZh || item?.check?.titleZh) || registered.title, - summary: safeUserText(item?.checkSummaryZh || item?.summary || item?.evidenceSummary || item?.check?.summaryZh) || registered.summary, - }; - } return { code: serviceCode || publicCheckCode(rawId || rawCode) || stableCheckCode(rawCode || rawId), title: safeUserText(item?.checkTitleZh || item?.check?.titleZh) || "未登记监测项", - summary: safeUserText(item?.checkSummaryZh || item?.summary || item?.evidenceSummary) || "已记录监测项详情,见报告原文。", + summary: safeUserText(item?.checkSummaryZh || item?.check?.summaryZh) || "已记录监测项详情,见报告原文。", + action: safeUserText(item?.checkActionZh || item?.check?.actionZh) || "查看详情后处理", }; } diff --git a/scripts/src/hwlab-node-web-sentinel-config.ts b/scripts/src/hwlab-node-web-sentinel-config.ts index 3a74d8ed..a10bd640 100644 --- a/scripts/src/hwlab-node-web-sentinel-config.ts +++ b/scripts/src/hwlab-node-web-sentinel-config.ts @@ -1,6 +1,8 @@ // SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-25-p0-web-probe-sentinel. // SPEC: PJ2026-01060508 Web哨兵 draft-2026-06-26-p9-multi-web-probe-sentinel. // Responsibility: Redacted YAML configRef graph for web-probe sentinel plan/status. +import { readFileSync } from "node:fs"; +import { rootPath } from "./config"; import { readWebProbeSentinelConfigRef } from "./hwlab-node-web-sentinel-config-ref"; import { HWLAB_WEB_PROBE_SENTINEL_CONFIG_REF_KEYS, type HwlabRuntimeLaneSpec, type HwlabRuntimeWebProbeSentinelConfigRefKey } from "./hwlab-node-lanes"; import { effectiveWebProbeSentinelPublicExposure, resolveWebProbeSentinel, webProbeSentinelRegistryRows, type WebProbeSentinelRegistryRow } from "./hwlab-node-web-sentinel-resolver"; @@ -100,7 +102,7 @@ const REQUIRED_TARGET_SHAPES: Record | null): void { + if (reportViews === null) return; + const catalogRef = stringAt(reportViews, "checkCatalogRef"); + if (catalogRef === null) { + conflicts.push(`${ref?.file ?? "-"}#${ref?.path ?? "-"}.checkCatalogRef is required`); + return; + } + let catalog: Record; + try { + const target = readWebProbeSentinelConfigRef(spec, catalogRef).target; + catalog = isRecord(target) ? target : {}; + } catch (error) { + conflicts.push(`${ref?.file ?? "-"}#${ref?.path ?? "-"}.checkCatalogRef=${catalogRef} is not readable: ${error instanceof Error ? error.message : String(error)}`); + return; + } + const items = arrayAt(catalog, "items"); + if (items.length === 0) { + conflicts.push(`${catalogRef}.items is empty`); + return; + } + const byId = new Map>(); + const codes = new Set(); + for (const [index, item] of items.entries()) { + const itemId = stringAt(item, "id"); + const code = stringAt(item, "code"); + if (itemId === null) conflicts.push(`${catalogRef}.items[${index}].id is required`); + else if (byId.has(itemId)) conflicts.push(`${catalogRef}.items id duplicated: ${itemId}`); + else byId.set(itemId, item); + if (code === null) conflicts.push(`${catalogRef}.items[${index}].code is required`); + else if (codes.has(code)) conflicts.push(`${catalogRef}.items code duplicated: ${code}`); + else codes.add(code); + for (const field of ["titleZh", "summaryZh", "actionZh"]) { + const text = stringAt(item, field); + if (text === null) { + conflicts.push(`${catalogRef}.items[${index}].${field} is required`); + } else if (!containsChinese(text)) { + conflicts.push(`${catalogRef}.items[${index}].${field} must contain Chinese text`); + } + } + } + const requiredIds = knownWebProbeFindingIds(); + const missing = requiredIds.filter((id) => !byId.has(id)); + if (missing.length > 0) { + conflicts.push(`${catalogRef}.items missing analyzer finding ids: ${missing.slice(0, 24).join(",")}${missing.length > 24 ? `,+${missing.length - 24}` : ""}`); + } +} + +function knownWebProbeFindingIds(): string[] { + const ids = new Set(); + for (const file of [ + "scripts/src/hwlab-node-web-observe-analyzer-source.ts", + "scripts/src/hwlab-node-web-sentinel-p5-observe.ts", + ]) { + let source = ""; + try { + source = readFileSync(rootPath(file), "utf8"); + } catch { + continue; + } + for (const match of source.matchAll(/\bid:\s*["`]([A-Za-z0-9_.:-]+)["`]/gu)) ids.add(match[1]); + } + return Array.from(ids).sort(); +} + +function containsChinese(value: string): boolean { + return /[\u3400-\u9fff]/u.test(value); +} + function requireReadableConfigRef(spec: HwlabRuntimeLaneSpec, conflicts: string[], ref: InternalConfigRefStatus | undefined, path: string, value: unknown): void { if (typeof value !== "string" || value.length === 0) return; try { diff --git a/scripts/src/hwlab-node-web-sentinel-p5.ts b/scripts/src/hwlab-node-web-sentinel-p5.ts index b2e35a26..372b9935 100644 --- a/scripts/src/hwlab-node-web-sentinel-p5.ts +++ b/scripts/src/hwlab-node-web-sentinel-p5.ts @@ -552,7 +552,7 @@ await page.evaluate(() => { await page.waitForTimeout(150); const trendHoverPoint = await page.evaluate(() => { - const target = document.querySelector(".trend-dot-hit .trend-dot-red") || document.querySelector(".trend-dot-hit .trend-dot-warning"); + const target = document.querySelector(".trend-dot-hit .trend-dot-duration"); if (!(target instanceof SVGElement)) return null; const rect = target.getBoundingClientRect(); if (rect.width <= 0 || rect.height <= 0) return null; @@ -600,17 +600,15 @@ const dom = await page.evaluate(async ({ expectedRoutePrefix, expectedSentinelId const legendTexts = Array.from(document.querySelectorAll(".trend-legend .legend-item")).map((item) => String(item.textContent || "").replace(/\s+/g, " ").trim()); const legendNumber = (label) => { const row = legendTexts.find((item) => item.includes(label)) || ""; - const match = /(\d+)/u.exec(row); + const match = /(\d+(?:\.\d+)?)/u.exec(row); return match ? Number(match[1]) : null; }; - const chartCounts = { - error: legendNumber("最新点错误"), - warning: legendNumber("最新点告警"), - total: legendNumber("错误+告警合计"), + const chartTiming = { + latestMinutes: legendNumber("最新运行耗时"), + maxMinutes: legendNumber("最近最高耗时"), + title: text("#trend-heading"), + legendHasDuration: legendTexts.some((item) => item.includes("最新运行耗时")), }; - chartCounts.ok = typeof chartCounts.error === "number" && typeof chartCounts.warning === "number" && typeof chartCounts.total === "number" - ? chartCounts.total === chartCounts.error + chartCounts.warning - : false; const apiUrl = (path) => { const basePath = root?.getAttribute("data-base-path") || expectedRoutePrefix || ""; const prefix = basePath.replace(/\/+$/u, ""); @@ -769,10 +767,9 @@ const dom = await page.evaluate(async ({ expectedRoutePrefix, expectedSentinelId total: errorSampleCount(overviewCounts) + warningSampleCount(overviewCounts), allSamples: allSampleCount(overviewCounts), }; - chartCounts.matchesLatestRun = chartCounts.ok === true - && chartCounts.error === latestRunCounts.error - && chartCounts.warning === latestRunCounts.warning - && chartCounts.total === latestRunCounts.total; + chartTiming.ok = chartTiming.title.includes("运行耗时") && chartTiming.legendHasDuration === true && Number.isFinite(chartTiming.latestMinutes); + chartTiming.matchesLatestRun = chartTiming.ok === true + && Math.abs(Number(chartTiming.latestMinutes) - Number(latestRunCounts.durationMinutes)) < 0.02; const trendPanel = document.querySelector(".trend-panel"); const trendLegend = document.querySelector(".trend-panel .trend-legend"); const trendPanelRect = trendPanel?.getBoundingClientRect(); @@ -870,7 +867,7 @@ const dom = await page.evaluate(async ({ expectedRoutePrefix, expectedSentinelId trendDotCount: document.querySelectorAll(".trend-dot-hit").length, trendTooltip: trendTooltipSummary, trendPanelText: text("#trend-heading"), - chartCounts, + chartTiming, latestRunCounts, latestDetailSummary, timingVisibility, @@ -881,7 +878,7 @@ const dom = await page.evaluate(async ({ expectedRoutePrefix, expectedSentinelId overviewSamples, panelHeights, scopeLabels: { - latestPointLegend: legendTexts.some((item) => item.includes("最新点")), + latestPointLegend: legendTexts.some((item) => item.includes("最新运行耗时")), historicalSamples: legendTexts.some((item) => item.includes("历史样本累计")) || statusText.includes("历史错误样本"), }, timelineItems: document.querySelectorAll(".timeline-list .timeline-item").length, @@ -1067,8 +1064,8 @@ const ok = !navigationError && dom.sentinelBoundary?.routePrefixMatches === true && dom.errorVisible !== true && dom.trendCurve === true - && dom.chartCounts?.ok === true - && dom.chartCounts?.matchesLatestRun === true + && dom.chartTiming?.ok === true + && dom.chartTiming?.matchesLatestRun === true && dom.checkScope?.matchesLatestRun === true && dom.checkScope?.matchesRunDetail === true && dom.selectedRunTags?.matchesRunDetail === true @@ -1533,7 +1530,7 @@ function renderDashboardResult(result: Record): string { const dom = record(page.dom); const dataset = record(dom.dataset); const layout = record(dom.layout); - const chartCounts = record(dom.chartCounts); + const chartTiming = record(dom.chartTiming); const latestRunCounts = record(dom.latestRunCounts); const latestDetailSummary = record(dom.latestDetailSummary); const timingVisibility = record(dom.timingVisibility); @@ -1570,12 +1567,11 @@ function renderDashboardResult(result: Record): string { "", table(["TITLE", "STATUS_TEXT", "CONTRACT", "BASE_PATH"], [[dom.title, dom.statusText, dataset.contractVersion, dataset.basePath ?? "-"]]), "", - table(["TREND_ERR_TYPES", "TREND_ALERT_TYPES", "TREND_TOTAL_TYPES", "TREND_EXACT", "MATCH_LATEST", "BAD_TITLE", "BAD_BODY"], [[ - chartCounts.error ?? "-", - chartCounts.warning ?? "-", - chartCounts.total ?? "-", - chartCounts.ok ?? "-", - chartCounts.matchesLatestRun ?? "-", + table(["TREND_LATEST_MIN", "TREND_MAX_MIN", "TREND_DURATION", "MATCH_LATEST", "BAD_TITLE", "BAD_BODY"], [[ + chartTiming.latestMinutes ?? "-", + chartTiming.maxMinutes ?? "-", + chartTiming.ok ?? "-", + chartTiming.matchesLatestRun ?? "-", dom.badCardTitleCount ?? "-", dom.badCardBodyCount ?? "-", ]]), diff --git a/scripts/src/hwlab-node-web-sentinel-service.ts b/scripts/src/hwlab-node-web-sentinel-service.ts index 6ca9ee15..6e496581 100644 --- a/scripts/src/hwlab-node-web-sentinel-service.ts +++ b/scripts/src/hwlab-node-web-sentinel-service.ts @@ -1316,6 +1316,7 @@ function enrichFindingWithCheck(config: WebProbeSentinelServiceConfig, value: Re checkLevel, checkTitleZh: stringOrNull(check.titleZh), checkSummaryZh: stringOrNull(check.summaryZh), + checkActionZh: stringOrNull(check.actionZh), checkRegistered: check.registered === true, blocking: value.blocking === true || check.blocking === true, valuesRedacted: true, @@ -1327,13 +1328,13 @@ function checkForFinding(config: WebProbeSentinelServiceConfig, value: Record