diff --git a/config/hwlab-web-probe-sentinel/check-catalog.yaml b/config/hwlab-web-probe-sentinel/check-catalog.yaml
new file mode 100644
index 00000000..81a99b24
--- /dev/null
+++ b/config/hwlab-web-probe-sentinel/check-catalog.yaml
@@ -0,0 +1,425 @@
+version: 1
+kind: HwlabWebProbeSentinelCheckCatalog
+metadata:
+ id: web-probe-sentinel-check-catalog
+ owner: UniDesk
+ specRef: PJ2026-01060508
+ issue: 1203
+sentinel:
+ checkCatalog:
+ terminology:
+ entity: check
+ zh: 监测项
+ codePrefix: WBC
+ levels:
+ - critical
+ - error
+ - warning
+ - info
+ items:
+ - code: WBC-001
+ id: workbench-terminal-api-dom-not-refreshed-in-place
+ level: error
+ titleZh: 终端未原地刷新
+ summaryZh: API 已变化但终端 DOM 未同步。
+ blocking: true
+ order: 10
+ - code: WBC-002
+ id: workbench-terminal-trace-not-hydrated-in-place
+ level: error
+ titleZh: 终端 Trace 未水合
+ summaryZh: Trace 数据存在但终端区域未原地渲染。
+ blocking: true
+ order: 20
+ - code: WBC-003
+ id: quick-verify-no-business-turn
+ level: error
+ titleZh: 快速验证无业务回合
+ summaryZh: 快速验证未形成稳定会话、trace 或最终回复。
+ blocking: true
+ order: 30
+ - code: WBC-004
+ id: quick-verify-command-sequence-failed
+ level: error
+ titleZh: 快速验证命令失败
+ summaryZh: 快速验证命令序列未能完成。
+ blocking: true
+ order: 40
+ - code: WBC-005
+ id: quick-verify-observer-start-failed
+ level: error
+ titleZh: 观察器启动失败
+ summaryZh: 快速验证前观察器未成功启动。
+ blocking: true
+ order: 50
+ - code: WBC-006
+ id: quick-verify-account-secret-missing
+ level: error
+ titleZh: 账号密钥缺失
+ summaryZh: 快速验证所需账号或 Secret 未配置。
+ blocking: true
+ order: 60
+ - code: WBC-007
+ id: prompt-chat-submit-failed
+ level: error
+ titleZh: Prompt 提交失败
+ summaryZh: sendPrompt 未观察到成功的 chat 请求。
+ blocking: true
+ order: 70
+ - code: WBC-008
+ id: observer-command-failed
+ level: error
+ titleZh: 观察命令失败
+ summaryZh: web-probe observe 命令执行失败。
+ blocking: true
+ order: 80
+ - code: WBC-009
+ id: route-active-session-mismatch
+ level: error
+ titleZh: 路由会话不一致
+ summaryZh: URL 路由会话与活动会话不一致。
+ blocking: true
+ order: 90
+ - code: WBC-010
+ id: workbench-message-order-user-clustered-after-navigation
+ level: warning
+ titleZh: 导航后消息顺序异常
+ summaryZh: 导航或刷新后用户消息聚集,需核对会话投影。
+ blocking: false
+ order: 100
+ - code: WBC-011
+ id: cross-page-projection-divergence
+ level: error
+ titleZh: 跨页面投影分叉
+ summaryZh: control 与 observer 在同一会话看到不同投影。
+ blocking: true
+ order: 110
+ - code: WBC-012
+ id: cross-page-projection-transient-divergence
+ level: info
+ titleZh: 跨页面短暂分叉
+ summaryZh: 页面切换附近出现短暂投影差异。
+ blocking: false
+ order: 120
+ - code: WBC-013
+ id: cross-page-projection-controlled-navigation-hydration
+ level: info
+ titleZh: 导航水合期差异
+ summaryZh: 导航水合期间 control 与 observer 暂时不同步。
+ blocking: false
+ order: 130
+ - code: WBC-014
+ id: cross-page-projection-app-shell-not-ready
+ level: info
+ titleZh: Shell 未就绪差异
+ summaryZh: 投影差异由页面 Shell 未挂载解释。
+ blocking: false
+ order: 140
+ - code: WBC-015
+ id: cross-page-trace-visibility-divergence
+ level: info
+ titleZh: Trace 可见性差异
+ summaryZh: 两页只在可见 Trace 行数上不同。
+ blocking: false
+ order: 150
+ - code: WBC-016
+ id: workbench-app-shell-not-ready
+ level: error
+ titleZh: Workbench Shell 未就绪
+ summaryZh: Workbench 路由已加载但应用 Shell 未挂载。
+ blocking: true
+ order: 160
+ - code: WBC-017
+ id: workbench-app-shell-transient-not-ready
+ level: info
+ titleZh: Shell 短暂未就绪
+ summaryZh: Workbench Shell 启动期间短暂不可用。
+ blocking: false
+ order: 170
+ - code: WBC-018
+ id: trace-without-terminal
+ level: warning
+ titleZh: Trace 缺少终端态
+ summaryZh: 已看到 Trace 行但未看到终端状态。
+ blocking: false
+ order: 180
+ - code: WBC-019
+ id: turn-trace-id-missing
+ level: error
+ titleZh: 回合缺少 Trace ID
+ summaryZh: Code Agent 回合可见但缺少可追踪 Trace ID。
+ blocking: true
+ order: 190
+ - code: WBC-020
+ id: trace-assistant-message-duplicates-final-response
+ level: warning
+ titleZh: Trace 回复重复
+ summaryZh: Trace Frame 渲染了重复助手最终回复。
+ blocking: false
+ order: 200
+ - code: WBC-021
+ id: final-response-flicker
+ level: error
+ titleZh: 最终回复闪烁
+ summaryZh: Final Response 在采样期间不稳定。
+ blocking: true
+ order: 210
+ - code: WBC-022
+ id: round-completion-final-response-missing
+ level: error
+ titleZh: 完成后无最终回复
+ summaryZh: 回合完成后缺少最终回复内容。
+ blocking: true
+ order: 220
+ - code: WBC-023
+ id: trace-events-page-read-404-root-cause
+ level: error
+ titleZh: Trace 分页 404
+ summaryZh: Trace events 分页读取命中 404。
+ blocking: true
+ order: 230
+ - code: WBC-024
+ id: trace-events-page-read-http-error-root-cause
+ level: error
+ titleZh: Trace 分页 HTTP 错误
+ summaryZh: Trace events 分页读取返回 HTTP 错误。
+ blocking: true
+ order: 240
+ - code: WBC-025
+ id: trace-events-page-read-requestfailed-root-cause
+ level: warning
+ titleZh: Trace 分页网络失败
+ summaryZh: Trace events 分页读取出现 requestfailed。
+ blocking: false
+ order: 250
+ - code: WBC-026
+ id: runtime-http-errors
+ level: warning
+ titleZh: 页面 HTTP 错误
+ summaryZh: 观察期间页面请求返回 HTTP 错误状态。
+ blocking: false
+ order: 260
+ - code: WBC-027
+ id: runtime-requestfailed
+ level: warning
+ titleZh: 页面请求失败
+ summaryZh: 浏览器捕获 requestfailed 事件。
+ blocking: false
+ order: 270
+ - code: WBC-028
+ id: runtime-dom-diagnostics
+ level: warning
+ titleZh: DOM 诊断文本
+ summaryZh: 页面 DOM 中出现错误或警告类诊断文本。
+ blocking: false
+ order: 280
+ - code: WBC-029
+ id: runtime-execution-errors
+ level: error
+ titleZh: 运行面执行错误
+ summaryZh: Workbench 渲染了执行失败或错误行。
+ blocking: true
+ order: 290
+ - code: WBC-030
+ id: runtime-console-alerts
+ level: warning
+ titleZh: Console 告警
+ summaryZh: 浏览器 console 捕获警告或错误。
+ blocking: false
+ order: 300
+ - code: WBC-031
+ id: browser-console-or-page-errors
+ level: warning
+ titleZh: 页面运行错误
+ summaryZh: pageerror 或 runner error 被捕获。
+ blocking: false
+ order: 310
+ - code: WBC-032
+ id: page-performance-slow-same-origin-api
+ level: error
+ titleZh: 同源 API 过慢
+ summaryZh: 同源 API 资源耗时超过 YAML 预算。
+ blocking: true
+ order: 320
+ - code: WBC-033
+ id: page-performance-slow-long-lived-stream-open
+ level: error
+ titleZh: 长连接打开过慢
+ summaryZh: 长连接打开耗时超过 YAML 预算。
+ blocking: true
+ order: 330
+ - code: WBC-034
+ id: page-performance-long-lived-streams
+ level: info
+ titleZh: 长连接上下文
+ summaryZh: 页面存在同源长连接,作为性能上下文保留。
+ blocking: false
+ order: 340
+ - code: WBC-035
+ id: page-provenance-segments
+ level: info
+ titleZh: 页面资产分段
+ summaryZh: 观察跨越多个页面资产版本段。
+ blocking: false
+ order: 350
+ - code: WBC-036
+ id: natural-api-dom-lag-baseline
+ level: info
+ titleZh: API-DOM 基线
+ summaryZh: 已收集自然 API 与 DOM 滞后基线。
+ blocking: false
+ order: 360
+ - code: WBC-037
+ id: natural-api-dom-lag-candidates
+ level: info
+ titleZh: API-DOM 滞后候选
+ summaryZh: 自然 API 与 DOM 投影滞后候选样本。
+ blocking: false
+ order: 370
+ - code: WBC-038
+ id: turn-timing-total-elapsed-zero-reset
+ level: warning
+ titleZh: 总耗时归零
+ summaryZh: Code Agent 总耗时从非零跳回 0。
+ blocking: false
+ order: 380
+ - code: WBC-039
+ id: turn-timing-total-elapsed-decrease
+ level: warning
+ titleZh: 总耗时回退
+ summaryZh: Code Agent 总耗时在相邻样本间降低。
+ blocking: false
+ order: 390
+ - code: WBC-040
+ id: turn-timing-total-elapsed-forward-jump
+ level: warning
+ titleZh: 总耗时前跳
+ summaryZh: Code Agent 总耗时增长快于采样间隔。
+ blocking: false
+ order: 400
+ - code: WBC-041
+ id: turn-timing-terminal-elapsed-growth
+ level: warning
+ titleZh: 终态耗时增长
+ summaryZh: 回合终态后总耗时仍继续变化。
+ blocking: false
+ order: 410
+ - code: WBC-042
+ id: turn-timing-recent-update-sawtooth-jump
+ level: warning
+ titleZh: 最近更新跳变
+ summaryZh: 最近更新时间显示出现锯齿跳变。
+ blocking: false
+ order: 420
+ - code: WBC-043
+ id: turn-elapsed-severe-timeout
+ level: warning
+ titleZh: 回合耗时超阈值
+ summaryZh: 回合总耗时超过 YAML 配置告警阈值。
+ blocking: false
+ order: 430
+ - code: WBC-044
+ id: page-loading-visible-over-budget
+ level: error
+ titleZh: 加载态超时
+ summaryZh: 页面可见加载态持续时间超过 YAML 预算。
+ blocking: true
+ order: 440
+ - code: WBC-045
+ id: page-loading-concurrent
+ level: info
+ titleZh: 多加载态并发
+ summaryZh: 同一采样点出现多个加载中指示。
+ blocking: false
+ order: 450
+ - code: WBC-046
+ id: session-rail-title-fallback-root-cause
+ level: error
+ titleZh: 会话标题回退
+ summaryZh: 会话栏标题从 facts 回退,已定位为根因。
+ blocking: true
+ order: 460
+ - code: WBC-047
+ id: scroll-jump-top
+ level: warning
+ titleZh: 滚动跳顶
+ summaryZh: 页面滚动位置无命令触发地跳到顶部附近。
+ blocking: false
+ order: 470
+ - code: WBC-048
+ id: code-agent-card-duration-mismatch
+ level: warning
+ titleZh: 卡片耗时不一致
+ summaryZh: Code Agent 卡片耗时与观测回合耗时不一致。
+ blocking: false
+ order: 480
+ - code: WBC-049
+ id: round-completion-elapsed-mismatch
+ level: warning
+ titleZh: 完成耗时不一致
+ summaryZh: 回合完成状态前后的耗时显示不一致。
+ blocking: false
+ order: 490
+ - code: WBC-050
+ id: round-completion-post-timing-change
+ level: warning
+ titleZh: 完成后耗时变化
+ summaryZh: 回合完成后仍出现耗时变化。
+ blocking: false
+ order: 500
+ - code: WBC-051
+ id: round-completion-recent-update-still-visible
+ level: info
+ titleZh: 完成后仍显示最近更新
+ summaryZh: 回合完成后仍保留最近更新时间显示。
+ blocking: false
+ order: 510
+ - code: WBC-052
+ id: no-samples
+ level: error
+ titleZh: 无采样数据
+ summaryZh: 观察器未产生任何可分析样本。
+ blocking: true
+ order: 520
+ - code: WBC-053
+ id: jsonl-read-issues
+ level: error
+ titleZh: JSONL 读取异常
+ summaryZh: analyzer 读取或解析 JSONL 样本失败。
+ blocking: true
+ order: 530
+ - code: WBC-054
+ id: prompt-routed-to-steer
+ level: warning
+ titleZh: Prompt 走 steer
+ summaryZh: sendPrompt 被路由到 steer,需确认上一回合状态。
+ blocking: false
+ order: 540
+ - code: WBC-055
+ id: tool-runner-heartbeat-stale
+ level: error
+ titleZh: Runner 心跳过期
+ summaryZh: web-probe runner 心跳超过预算未更新。
+ blocking: true
+ order: 550
+ - code: WBC-056
+ id: tool-pending-commands-unconsumed
+ level: error
+ titleZh: 命令未消费
+ summaryZh: runner 存在未消费的待执行命令。
+ blocking: true
+ order: 560
+ - code: WBC-057
+ id: tool-commands-abandoned
+ level: info
+ titleZh: 命令被遗留
+ summaryZh: 历史命令被遗留,作为工具上下文保留。
+ blocking: false
+ order: 570
+ - code: WBC-058
+ id: tool-runner-force-stopped
+ level: info
+ titleZh: Runner 被强制停止
+ summaryZh: runner 由控制面强制停止,作为观察上下文保留。
+ blocking: false
+ order: 580
diff --git a/config/hwlab-web-probe-sentinel/report-views.auth-session-switch.yaml b/config/hwlab-web-probe-sentinel/report-views.auth-session-switch.yaml
index c292f1e4..6ffdb0a8 100644
--- a/config/hwlab-web-probe-sentinel/report-views.auth-session-switch.yaml
+++ b/config/hwlab-web-probe-sentinel/report-views.auth-session-switch.yaml
@@ -15,6 +15,7 @@ sentinel:
pageSize: 20
maxPageSize: 100
rawAccess: explicit-only
+ checkCatalogRef: config/hwlab-web-probe-sentinel/check-catalog.yaml#sentinel.checkCatalog
redaction:
prompt: hash-and-byte-count
assistantFinal: summary-and-hash
diff --git a/config/hwlab-web-probe-sentinel/report-views.yaml b/config/hwlab-web-probe-sentinel/report-views.yaml
index 9202f2e6..923fce86 100644
--- a/config/hwlab-web-probe-sentinel/report-views.yaml
+++ b/config/hwlab-web-probe-sentinel/report-views.yaml
@@ -15,6 +15,7 @@ sentinel:
pageSize: 20
maxPageSize: 100
rawAccess: explicit-only
+ checkCatalogRef: config/hwlab-web-probe-sentinel/check-catalog.yaml#sentinel.checkCatalog
redaction:
prompt: hash-and-byte-count
assistantFinal: summary-and-hash
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 56f509f3..9fdcedf6 100644
--- a/scripts/assets/web-probe-sentinel-monitor-web/monitor-web.css
+++ b/scripts/assets/web-probe-sentinel-monitor-web/monitor-web.css
@@ -27,14 +27,14 @@
html,
body,
#monitor-web-root {
- height: 100%;
+ min-height: 100%;
margin: 0;
}
body {
background: var(--bg);
color: var(--text);
- overflow: hidden;
+ overflow: auto;
}
button,
@@ -45,11 +45,10 @@ input {
.monitor-shell {
display: flex;
- height: 100dvh;
- min-height: 0;
+ min-height: 100dvh;
flex-direction: column;
gap: 10px;
- overflow: hidden;
+ overflow: visible;
padding: 12px;
}
@@ -462,7 +461,7 @@ select {
.timeline-list {
display: grid;
- max-height: 150px;
+ max-height: 300px;
gap: 7px;
overflow: auto;
padding-right: 2px;
@@ -549,9 +548,9 @@ select {
display: grid;
grid-template-columns: minmax(260px, 0.82fr) minmax(420px, 1.34fr) minmax(300px, 1fr);
gap: 10px;
- flex: 1 1 auto;
- min-height: 0;
- overflow: hidden;
+ flex: 0 0 auto;
+ min-height: clamp(680px, calc(100dvh - 220px), 980px);
+ overflow: visible;
}
.pane {
@@ -615,6 +614,7 @@ select {
.finding-list,
.detail-stack {
display: grid;
+ align-content: start;
gap: 8px;
}
@@ -658,6 +658,18 @@ select {
background: var(--green);
}
+.check-code {
+ flex: 0 0 auto;
+ border: 1px solid var(--line-strong);
+ border-radius: 6px;
+ background: #ffffff;
+ color: var(--ink);
+ padding: 2px 6px;
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
+ font-size: 11px;
+ line-height: 1.2;
+}
+
.tag {
display: inline-flex;
align-items: center;
@@ -702,6 +714,40 @@ select {
background: #ffffff;
}
+.summary-list {
+ display: grid;
+ overflow: hidden;
+ border: 1px solid var(--line);
+ border-radius: 8px;
+ background: #ffffff;
+}
+
+.summary-row {
+ display: grid;
+ grid-template-columns: minmax(86px, 0.35fr) minmax(0, 1fr);
+ gap: 10px;
+ align-items: center;
+ min-height: 34px;
+ padding: 7px 10px;
+ border-bottom: 1px solid var(--line);
+ font-size: 12px;
+}
+
+.summary-row:last-child {
+ border-bottom: 0;
+}
+
+.summary-row span {
+ color: var(--muted);
+}
+
+.summary-row strong {
+ min-width: 0;
+ overflow-wrap: anywhere;
+ font-size: 12px;
+ font-weight: 600;
+}
+
pre {
max-height: 240px;
margin: 0;
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 c0136040..c8c9ec6f 100644
--- a/scripts/assets/web-probe-sentinel-monitor-web/monitor-web.js
+++ b/scripts/assets/web-probe-sentinel-monitor-web/monitor-web.js
@@ -71,13 +71,18 @@ createApp({
timeLabel: formatDate(rawTime),
absoluteTime: formatAbsoluteDate(rawTime),
reportSha: shortHash(run.reportJsonSha256 || run.report_json_sha256 || run.reportSha256 || ""),
- title: `${shortId(run.id)} ${formatAbsoluteDate(rawTime)} 红色 ${red} 警告 ${warning} 总量 ${total}`,
+ title: `${shortId(run.id)} ${formatAbsoluteDate(rawTime)} 错误 ${red} 警告 ${warning} 总量 ${total}`,
};
}));
const timelineRuns = computed(() => runs.value.slice(0, 16));
const rootCauseFindings = computed(() => {
- const rows = findings.value.filter((item) => item.rootCause || item.nextAction || ["red", "warning"].includes(severityClass(item)));
- return rows.slice(0, 14);
+ const rows = findings.value.filter((item) => item.checkRegistered !== false || item.rootCause || item.nextAction || ["red", "warning", "info"].includes(severityClass(item)));
+ return rows.slice(0, 32);
+ });
+ const visibleCheckFindings = computed(() => {
+ const needle = findingFilter.value.trim().toLowerCase();
+ const rows = needle.length === 0 ? rootCauseFindings.value : rootCauseFindings.value.filter((item) => findingSearchText(item).includes(needle));
+ return rows.slice(0, 24);
});
const cadence = computed(() => {
const intervalMs = Number(overview.value?.scheduler?.intervalMs || 0);
@@ -220,6 +225,7 @@ createApp({
trendDots,
timelineRuns,
rootCauseFindings,
+ visibleCheckFindings,
cadence,
healthChecks,
loadAll,
@@ -238,7 +244,10 @@ createApp({
shortId,
rootCauseText,
findingTitle,
+ findingCode,
+ levelLabel,
detailSummaryText,
+ detailSummaryRows,
commandSummary,
statusLabel,
};
@@ -292,13 +301,13 @@ createApp({
-
暂无运行数据
- 红色 {{ redCount({ severityCounts: severityTotals }) }}
+ 错误 {{ redCount({ severityCounts: severityTotals }) }}
警告 {{ warningCount({ severityCounts: severityTotals }) }}
- 发现总量 {{ findingCount({ findingCount: overview?.latestRun?.findingCount, severityCounts: severityTotals }) }}
+ 监测项总量 {{ findingCount({ findingCount: overview?.latestRun?.findingCount, severityCounts: severityTotals }) }}
{{ cadence.alert }}
@@ -384,7 +393,7 @@ createApp({
{{ cadence.latestAge >= 0 ? formatDuration(cadence.latestAge) : "-" }}
- 红色
+ 错误
{{ redCount({ severityCounts: severityTotals }) }}
@@ -412,7 +421,7 @@ createApp({