From bd51eefeebc1274d9d899cf00db6f00e52c72d45 Mon Sep 17 00:00:00 2001 From: Lyon <88232613+pikasTech@users.noreply.github.com> Date: Tue, 23 Jun 2026 16:50:27 +0800 Subject: [PATCH] fix(web-probe): scope trace timing evidence (#741) Co-authored-by: Codex --- .../hwlab-node-web-observe-runner-source.ts | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/scripts/src/hwlab-node-web-observe-runner-source.ts b/scripts/src/hwlab-node-web-observe-runner-source.ts index 73b4ba6b..8c45a43e 100644 --- a/scripts/src/hwlab-node-web-observe-runner-source.ts +++ b/scripts/src/hwlab-node-web-observe-runner-source.ts @@ -1579,16 +1579,17 @@ async function sampleOnePage(targetPage, { reason, groupSeq, pageRole, targetPag }; const summarize = (selector, limit) => Array.from(document.querySelectorAll(selector)).filter(visible).slice(-limit).map((element, index) => { const rect = element.getBoundingClientRect(); + const owner = element.closest('article.message-card, .message-card[data-message-id], article[data-message-id], [data-trace-id]'); return { index, tag: element.tagName.toLowerCase(), testId: element.getAttribute("data-testid"), role: element.getAttribute("role"), status: element.getAttribute("data-status") || element.getAttribute("aria-busy") || null, - sessionId: element.getAttribute("data-session-id") || null, - messageId: element.getAttribute("data-message-id") || element.getAttribute("id") || null, - traceId: element.getAttribute("data-trace-id") || null, - turnId: element.getAttribute("data-turn-id") || null, + sessionId: element.getAttribute("data-session-id") || owner?.getAttribute("data-session-id") || null, + messageId: element.getAttribute("data-message-id") || owner?.getAttribute("data-message-id") || element.getAttribute("id") || null, + traceId: element.getAttribute("data-trace-id") || owner?.getAttribute("data-trace-id") || null, + turnId: element.getAttribute("data-turn-id") || owner?.getAttribute("data-turn-id") || null, text: textHashInput(element), rect: { x: Math.round(rect.x), y: Math.round(rect.y), width: Math.round(rect.width), height: Math.round(rect.height) }, }; @@ -3737,7 +3738,7 @@ function isTerminalTraceText(text) { } function isFinalResultText(text) { - return /已完成第\d+轮|final response|sealed final response|最终结果|已完成[::]/iu.test(String(text || "")); + return /已完成第\d+轮|已按第\d+轮完成|final response|sealed final response|最终结果|已完成[::]|smoke\s*测试结果|benchmark|PVC\/workspace|修改文件|Results:/iu.test(String(text || "")); } function buildSampleMetrics(samples, control) { @@ -4611,7 +4612,7 @@ function buildCodeAgentCardDurationUnderreportedMetrics(samples, timeline) { const cardSeconds = Number.isFinite(Number(card.totalElapsedSeconds)) ? Number(card.totalElapsedSeconds) : parsedCardSeconds.length > 0 ? Math.max(...parsedCardSeconds) : NaN; if (!Number.isFinite(cardSeconds)) continue; const traceMatched = traceRows.filter((row) => traceRowMatchesCard(row, card, terminalCards.length)); - const traceEvidence = maxTraceDurationEvidence(traceMatched.length ? traceMatched : traceRows); + const traceEvidence = maxTraceDurationEvidence(traceMatched); const textEvidence = maxSelfReportedDurationEvidence([card.text, card.preview, card.finalResponseText, card.runningRecordText, terminalCards.length === 1 ? sampleText : ''].filter(Boolean).join('\n')); const evidences = [traceEvidence, textEvidence].filter((item) => item && Number.isFinite(item.seconds)); if (!evidences.length) continue; @@ -4812,13 +4813,14 @@ function parseTraceRowTraceId(text) { function traceRowGroupKey(row) { const identity = row.traceId ? 'trace:' + row.traceId : 'sample:' + (row.sampleIndex ?? '-') + ':' + (row.source || 'unknown'); - return [row.pageRole || '', row.pageId || '', row.sessionId || '', identity].join('|'); + return [row.pageRole || '', row.pageId || '', row.sessionId || '', row.source || '', row.sampleIndex ?? '', identity].join('|'); } function traceRowMatchesCard(row, card, terminalCardCount) { if (!row) return false; - if (row.traceId && card.traceId) return row.traceId === card.traceId; - if (row.sessionId && card.sessionId) return row.sessionId === card.sessionId; + if (card.traceId) return row.traceId === card.traceId; + if (row.traceId) return false; + if (row.sessionId && card.sessionId) return terminalCardCount === 1 && row.sessionId === card.sessionId; if (terminalCardCount === 1) return true; return false; } @@ -5004,6 +5006,7 @@ function isCodeAgentCardTerminal(item) { function buildRoundCompletionMetrics(samples, timeline, turnTiming) { const events = []; + const elapsedMismatchToleranceSeconds = Math.max(5, Number(alertThresholds.turnTimingSampleSlackSeconds || 0)); for (let index = 0; index < (Array.isArray(samples) ? samples : []).length; index += 1) { const sample = samples[index]; const timelineItem = timeline[index] || {}; @@ -5021,13 +5024,13 @@ function buildRoundCompletionMetrics(samples, timeline, turnTiming) { const bestCard = cards.filter((card) => Number.isFinite(Number(card.totalElapsedSeconds)))[0] || null; if (Number.isFinite(Number(event.elapsedSeconds)) && bestCard) { const delta = Math.abs(Number(bestCard.totalElapsedSeconds) - Number(event.elapsedSeconds)); - if (delta > alertThresholds.turnTimingSampleSlackSeconds) { + if (delta > elapsedMismatchToleranceSeconds) { elapsedMismatches.push({ ...eventRef(event), cardTotalElapsedSeconds: Number(bestCard.totalElapsedSeconds), completionElapsedSeconds: Number(event.elapsedSeconds), deltaSeconds: Number(delta.toFixed(3)), - toleranceSeconds: alertThresholds.turnTimingSampleSlackSeconds, + toleranceSeconds: elapsedMismatchToleranceSeconds, cardTraceId: bestCard.traceId ?? null, cardMessageId: bestCard.messageId ?? null, valuesRedacted: true @@ -5127,7 +5130,7 @@ function hasFinalResponseAfterCompletion(samples, timeline, event) { } function sampleHasVisibleFinalResponse(sample, event = {}) { - for (const group of [sample?.messages, sample?.turns]) { + for (const [groupName, group] of [["messages", sample?.messages], ["turns", sample?.turns]]) { if (!Array.isArray(group)) continue; for (const item of group) { if (event.traceId && item?.traceId && item.traceId !== event.traceId) continue; @@ -5135,6 +5138,7 @@ function sampleHasVisibleFinalResponse(sample, event = {}) { const text = normalizedText([item?.text, item?.textPreview].filter(Boolean).join(" ")); if (text.length < 24) continue; if (isDiagnosticText(text)) continue; + if (groupName === "messages" && isTerminalTurnStatus(item?.status)) return true; if (isFinalResultText(text)) return true; if (/运行记录/iu.test(text) && /(?:已完成|完成|新增|实现|验证|测试|结果|README|文件|summary)/iu.test(text)) return true; }