fix(web-probe): classify transient cross-page divergence (#755)

Co-authored-by: Codex <codex@noreply.local>
This commit is contained in:
Lyon
2026-06-23 21:22:27 +08:00
committed by GitHub
parent ea73dcfbdb
commit 0a1d43183c
@@ -1989,6 +1989,7 @@ function parseAlertThresholds(value) {
scrollJumpFromY: requiredPositiveThreshold(raw, "scrollJumpFromY"),
scrollJumpToY: requiredPositiveThreshold(raw, "scrollJumpToY"),
sessionRailFallbackRatio,
crossPageProjectionDivergenceRedMs: positiveNumber(raw.crossPageProjectionDivergenceRedMs, requiredPositiveThreshold(raw, "visibleLoadingSlowMs")),
source: "yaml-env",
};
}
@@ -2408,6 +2409,7 @@ function parseAlertThresholds(value) {
scrollJumpFromY: requiredPositiveThreshold(raw, "scrollJumpFromY"),
scrollJumpToY: requiredPositiveThreshold(raw, "scrollJumpToY"),
sessionRailFallbackRatio,
crossPageProjectionDivergenceRedMs: positiveNumber(raw.crossPageProjectionDivergenceRedMs, requiredPositiveThreshold(raw, "visibleLoadingSlowMs")),
source: "yaml-env",
};
}
@@ -2795,7 +2797,12 @@ function buildFindings(samples, control, network, errors, sampleMetrics, promptN
);
const crossPageProjectionDiffs = crossPageDiffs.filter((item) => item.diffKind !== "trace-visibility");
const crossPageTraceVisibilityDiffs = crossPageDiffs.filter((item) => item.diffKind === "trace-visibility");
if (crossPageProjectionDiffs.length > 0) findings.push({ id: "cross-page-projection-divergence", severity: "red", summary: "control and observer pages saw different projection state for the same sampled session", count: crossPageProjectionDiffs.length, samples: crossPageProjectionDiffs.slice(0, 20) });
const crossPageProjectionBudgetMs = alertThresholds.crossPageProjectionDivergenceRedMs;
const timedCrossPageProjectionDiffs = annotateCrossPageDiffTiming(crossPageProjectionDiffs);
const persistentCrossPageProjectionDiffs = timedCrossPageProjectionDiffs.filter((item) => Number(item.observedSpanMs ?? 0) > crossPageProjectionBudgetMs);
const transientCrossPageProjectionDiffs = timedCrossPageProjectionDiffs.filter((item) => Number(item.observedSpanMs ?? 0) <= crossPageProjectionBudgetMs);
if (persistentCrossPageProjectionDiffs.length > 0) findings.push({ id: "cross-page-projection-divergence", severity: "red", summary: "control and observer pages saw different projection state for the same sampled session beyond the configured budget", count: persistentCrossPageProjectionDiffs.length, budgetMs: crossPageProjectionBudgetMs, samples: persistentCrossPageProjectionDiffs.slice(0, 20) });
if (transientCrossPageProjectionDiffs.length > 0) findings.push({ id: "cross-page-projection-transient-divergence", severity: "info", summary: "control and observer pages briefly differed near a sampled transition; retained as transient evidence but not treated as persistent projection failure", count: transientCrossPageProjectionDiffs.length, budgetMs: crossPageProjectionBudgetMs, samples: transientCrossPageProjectionDiffs.slice(0, 20) });
if (crossPageTraceVisibilityDiffs.length > 0) findings.push({ id: "cross-page-trace-visibility-divergence", severity: "info", summary: "control and observer pages differed only in visible trace row count; this is local disclosure/hydration visibility, not session/message projection divergence", count: crossPageTraceVisibilityDiffs.length, samples: crossPageTraceVisibilityDiffs.slice(0, 20) });
const traceMessageDuplicates = detectTraceMessageDuplication(samples);
if (traceMessageDuplicates.length > 0) findings.push({ id: "trace-assistant-message-duplicates-final-response", severity: "amber", summary: "trace rendered assistant message rows that duplicate the sealed final response", count: traceMessageDuplicates.length, samples: traceMessageDuplicates.slice(0, 20) });
@@ -5943,6 +5950,43 @@ function mergeCrossPageDiffRows(...groups) {
return rows;
}
function annotateCrossPageDiffTiming(rows) {
const groups = new Map();
for (const row of Array.isArray(rows) ? rows : []) {
const controlAt = Date.parse(String(row?.control?.ts || ""));
const observerAt = Date.parse(String(row?.observer?.ts || ""));
const timestamps = [controlAt, observerAt].filter(Number.isFinite);
const startMs = timestamps.length > 0 ? Math.min(...timestamps) : null;
const endMs = timestamps.length > 0 ? Math.max(...timestamps) : null;
const sessionId = row?.control?.routeSessionId || row?.control?.activeSessionId || row?.observer?.routeSessionId || row?.observer?.activeSessionId || "unknown-session";
const key = [row?.diffKind || "projection", sessionId].join(":");
const group = groups.get(key) || { rows: [], firstMs: null, lastMs: null };
const annotated = {
...row,
sampleStartAt: startMs === null ? null : new Date(startMs).toISOString(),
sampleEndAt: endMs === null ? null : new Date(endMs).toISOString(),
pairSkewMs: startMs === null || endMs === null ? null : endMs - startMs,
};
group.rows.push(annotated);
if (startMs !== null && (group.firstMs === null || startMs < group.firstMs)) group.firstMs = startMs;
if (endMs !== null && (group.lastMs === null || endMs > group.lastMs)) group.lastMs = endMs;
groups.set(key, group);
}
const result = [];
for (const group of groups.values()) {
const observedSpanMs = group.firstMs === null || group.lastMs === null ? null : group.lastMs - group.firstMs;
for (const row of group.rows) {
result.push({
...row,
observedFirstAt: group.firstMs === null ? null : new Date(group.firstMs).toISOString(),
observedLastAt: group.lastMs === null ? null : new Date(group.lastMs).toISOString(),
observedSpanMs,
});
}
}
return result;
}
function detectAdjacentCrossPageProjectionDiffs(samples) {
const rows = [];
const ordered = (Array.isArray(samples) ? samples : []).slice().sort((a, b) => Number(a?.seq ?? 0) - Number(b?.seq ?? 0));