fix: expose workbench timing source status
This commit is contained in:
@@ -143,6 +143,9 @@ function detectTurnTimingNonMonotonic(columns, rows) {
|
||||
const event = {
|
||||
columnId: column.id,
|
||||
columnLabel: column.label,
|
||||
...timingFindingMeta("dom-card-total-elapsed-sequence", timingStatusFromTurnStatus(cell.status ?? previous.status), {
|
||||
cardElapsedSource: cell.source ?? column.source ?? "dom-card",
|
||||
}),
|
||||
metric,
|
||||
anomaly,
|
||||
expectedPattern: anomaly === "zero-reset" ? "total-elapsed-should-not-return-to-zero" : "total-elapsed-monotonic",
|
||||
@@ -186,6 +189,9 @@ function detectTurnTimingNonMonotonic(columns, rows) {
|
||||
totalElapsedForwardJumps.push({
|
||||
columnId: column.id,
|
||||
columnLabel: column.label,
|
||||
...timingFindingMeta("dom-card-total-elapsed-sequence", timingStatusFromTurnStatus(cell.status ?? previous.status), {
|
||||
cardElapsedSource: cell.source ?? column.source ?? "dom-card",
|
||||
}),
|
||||
metric,
|
||||
anomaly: "forward-jump",
|
||||
expectedPattern: "total-elapsed-increase-should-match-browser-sample-interval",
|
||||
@@ -218,6 +224,9 @@ function detectTurnTimingNonMonotonic(columns, rows) {
|
||||
terminalElapsedGrowth.push({
|
||||
columnId: column.id,
|
||||
columnLabel: column.label,
|
||||
...timingFindingMeta("terminal-card-total-elapsed-seal", timingStatusFromTurnStatus(cell.status, "business-turn-completed"), {
|
||||
cardElapsedSource: cell.source ?? column.source ?? "dom-card",
|
||||
}),
|
||||
metric,
|
||||
anomaly: "terminal-growth",
|
||||
expectedPattern: "terminal-total-elapsed-sealed",
|
||||
@@ -507,6 +516,10 @@ function buildCodeAgentCardDurationUnderreportedMetrics(samples, timeline) {
|
||||
if (strongest.seconds > cardSeconds + tolerance) {
|
||||
findings.push({
|
||||
sampleIndex,
|
||||
...timingFindingMeta(strongest.kind, timingStatusFromTurnStatus(card.status || card.state || card.phase, "business-turn-completed"), {
|
||||
cardElapsedSource: "dom-card-total-elapsed",
|
||||
expectedElapsedSource: strongest.kind,
|
||||
}),
|
||||
timestamp: sample.timestamp || sample.collectedAt || sample.time || null,
|
||||
pageRole: card.pageRole || sample.pageRole || sample.role || sample.contextRole || null,
|
||||
pageId: card.pageId || sample.pageId || sample.contextId || null,
|
||||
@@ -557,6 +570,10 @@ function buildCodeAgentCardDurationMismatchMetrics(samples, timeline) {
|
||||
if (!underreported && !overreported) continue;
|
||||
findings.push({
|
||||
sampleIndex,
|
||||
...timingFindingMeta(strongest.kind, timingStatusFromTurnStatus(card.status || card.state || card.phase, "business-turn-completed"), {
|
||||
cardElapsedSource: "dom-card-total-elapsed",
|
||||
expectedElapsedSource: strongest.kind,
|
||||
}),
|
||||
timestamp: sample.timestamp || sample.collectedAt || sample.time || sample.ts || null,
|
||||
pageRole: card.pageRole || sample.pageRole || sample.role || sample.contextRole || null,
|
||||
pageId: card.pageId || sample.pageId || sample.contextId || null,
|
||||
@@ -993,6 +1010,38 @@ function isCodeAgentCardTerminal(item) {
|
||||
return isTerminalTraceText(text) || /轮次完成|轮次失败|轮次取消|已记录|completed|failed|canceled|cancelled|blocked/iu.test(text);
|
||||
}
|
||||
|
||||
function timingFindingMeta(sourceOfTruth, status, extra = {}) {
|
||||
return {
|
||||
timingSourceOfTruth: sourceOfTruth,
|
||||
timingStatus: status || "non-blocking-timing-alert",
|
||||
timingAlert: true,
|
||||
blocking: false,
|
||||
...extra,
|
||||
};
|
||||
}
|
||||
|
||||
function timingStatusFromTurnStatus(status, fallback = "observer-timeout") {
|
||||
const normalized = String(status ?? "").trim().toLowerCase().replace(/_/gu, "-");
|
||||
if (isSuccessfulTurnStatus(normalized)) return "business-turn-completed";
|
||||
if (isTerminalTurnStatus(normalized)) return "scenario-incomplete";
|
||||
if (isActiveTurnStatus(normalized)) return "observer-timeout";
|
||||
return fallback;
|
||||
}
|
||||
|
||||
function timingStatusFromRows(rows, fallback = "observer-timeout") {
|
||||
const list = Array.isArray(rows) ? rows : [];
|
||||
if (list.some((item) => isSuccessfulTurnStatus(item?.status ?? item?.toStatus ?? item?.fromStatus))) return "business-turn-completed";
|
||||
if (list.some((item) => Number(item?.finalTextSamples ?? 0) > 0)) return "business-turn-completed";
|
||||
if (list.some((item) => isTerminalTurnStatus(item?.status ?? item?.toStatus ?? item?.fromStatus))) return "scenario-incomplete";
|
||||
if (list.some((item) => isActiveTurnStatus(item?.status ?? item?.toStatus ?? item?.fromStatus))) return "observer-timeout";
|
||||
return fallback;
|
||||
}
|
||||
|
||||
function isSuccessfulTurnStatus(status) {
|
||||
const normalized = String(status ?? "").trim().toLowerCase().replace(/_/gu, "-");
|
||||
return ["completed", "complete", "succeeded", "success", "done", "ok", "passed"].includes(normalized);
|
||||
}
|
||||
|
||||
function isActiveTurnStatus(value) {
|
||||
const status = String(value ?? "").trim().toLowerCase().replace(/_/gu, "-");
|
||||
return ["pending", "running", "queued", "admitted", "dispatching", "in-progress", "inprogress", "executing", "progress", "thinking", "working", "active", "streaming", "created", "started"].includes(status);
|
||||
@@ -1022,6 +1071,10 @@ function buildRoundCompletionMetrics(samples, timeline, turnTiming) {
|
||||
if (delta > elapsedMismatchToleranceSeconds) {
|
||||
elapsedMismatches.push({
|
||||
...eventRef(event),
|
||||
...timingFindingMeta("trace-round-completion-total", timingStatusFromTurnStatus(bestCard.status, "business-turn-completed"), {
|
||||
cardElapsedSource: bestCard.source ?? "dom-card",
|
||||
completionElapsedSource: "trace-round-completion",
|
||||
}),
|
||||
cardTotalElapsedSeconds: Number(bestCard.totalElapsedSeconds),
|
||||
completionElapsedSeconds: Number(event.elapsedSeconds),
|
||||
deltaSeconds: Number(delta.toFixed(3)),
|
||||
@@ -1072,6 +1125,8 @@ function roundCompletionEventsForSample(sample, timelineItem) {
|
||||
attributed: Boolean(item?.traceId || item?.messageId || attributed?.traceId || attributed?.messageId),
|
||||
traceRowIndex: item?.rowIndex ?? item?.index ?? null,
|
||||
elapsedSeconds: elapsedValues.length > 0 ? Math.max(...elapsedValues) : null,
|
||||
timingSourceOfTruth: "trace-round-completion-total",
|
||||
timingStatus: "business-turn-completed",
|
||||
textHash: item?.textHash ?? sha256(text),
|
||||
preview: limitText(text, 180),
|
||||
valuesRedacted: true
|
||||
@@ -2078,19 +2133,19 @@ function renderTurnTimingTable(sampleMetrics) {
|
||||
const columnLines = columns.map((column) => "- " + formatTurnColumnDisplayLabel(column) + ": pageRole=" + (column.pageRole || "-") + " pageId=" + (column.pageId || "-") + " source=" + (column.source || "-") + " prompt=" + (column.promptIndex ?? "-") + " lastPrompt=" + (column.lastPromptIndex ?? "-") + " firstSeq=" + (column.firstSeq ?? "-") + " lastSeq=" + (column.lastSeq ?? "-") + " traceId=" + (column.traceId || "-") + " messageId=" + (column.messageId || "-")).join("\n");
|
||||
const nonMonotonic = Array.isArray(sampleMetrics?.turnTimingNonMonotonic) ? sampleMetrics.turnTimingNonMonotonic : [];
|
||||
const nonMonotonicLines = nonMonotonic.length > 0
|
||||
? nonMonotonic.slice(0, 80).map((item) => "- " + formatTurnEventDisplayLabel(item) + " " + item.metric + (item.anomaly ? " " + item.anomaly : "") + " " + (item.fromValue ?? "-") + " -> " + (item.toValue ?? "-") + " delta=" + (item.delta ?? "-") + " sampleDelta=" + (item.sampleDeltaSeconds ?? "-") + " allowed=" + (item.allowedIncreaseSeconds ?? "-") + " seq " + (item.fromSeq ?? "-") + " -> " + (item.toSeq ?? "-") + " ts " + (item.fromTs || "-") + " -> " + (item.toTs || "-") + " traceId=" + (item.traceId || "-")).join("\n")
|
||||
? nonMonotonic.slice(0, 80).map((item) => "- " + formatTurnEventDisplayLabel(item) + " " + item.metric + (item.anomaly ? " " + item.anomaly : "") + " " + (item.fromValue ?? "-") + " -> " + (item.toValue ?? "-") + " delta=" + (item.delta ?? "-") + " sampleDelta=" + (item.sampleDeltaSeconds ?? "-") + " allowed=" + (item.allowedIncreaseSeconds ?? "-") + formatTimingMeta(item) + " seq " + (item.fromSeq ?? "-") + " -> " + (item.toSeq ?? "-") + " ts " + (item.fromTs || "-") + " -> " + (item.toTs || "-") + " traceId=" + (item.traceId || "-")).join("\n")
|
||||
: "- 未观察到总耗时下降或最近更新异常跳增。";
|
||||
const terminalGrowth = Array.isArray(sampleMetrics?.turnTimingTerminalElapsedGrowth) ? sampleMetrics.turnTimingTerminalElapsedGrowth : [];
|
||||
const terminalGrowthLines = terminalGrowth.length > 0
|
||||
? terminalGrowth.slice(0, 80).map((item) => "- " + formatTurnEventDisplayLabel(item) + " terminal totalElapsed growth " + (item.fromValue ?? "-") + " -> " + (item.toValue ?? "-") + " delta=" + (item.delta ?? "-") + " status " + (item.fromStatus || "-") + " -> " + (item.toStatus || "-") + " seq " + (item.fromSeq ?? "-") + " -> " + (item.toSeq ?? "-") + " ts " + (item.fromTs || "-") + " -> " + (item.toTs || "-") + " traceId=" + (item.traceId || "-")).join("\n")
|
||||
? terminalGrowth.slice(0, 80).map((item) => "- " + formatTurnEventDisplayLabel(item) + " terminal totalElapsed growth " + (item.fromValue ?? "-") + " -> " + (item.toValue ?? "-") + " delta=" + (item.delta ?? "-") + " status " + (item.fromStatus || "-") + " -> " + (item.toStatus || "-") + formatTimingMeta(item) + " seq " + (item.fromSeq ?? "-") + " -> " + (item.toSeq ?? "-") + " ts " + (item.fromTs || "-") + " -> " + (item.toTs || "-") + " traceId=" + (item.traceId || "-")).join("\n")
|
||||
: "- 未观察到 terminal 后总耗时增长。";
|
||||
const elapsedZeroResets = Array.isArray(sampleMetrics?.turnTimingElapsedZeroResets) ? sampleMetrics.turnTimingElapsedZeroResets : [];
|
||||
const elapsedZeroResetLines = elapsedZeroResets.length > 0
|
||||
? elapsedZeroResets.slice(0, 80).map((item) => "- " + formatTurnEventDisplayLabel(item) + " totalElapsed zero-reset " + (item.fromValue ?? "-") + " -> " + (item.toValue ?? "-") + " delta=" + (item.delta ?? "-") + " seq " + (item.fromSeq ?? "-") + " -> " + (item.toSeq ?? "-") + " ts " + (item.fromTs || "-") + " -> " + (item.toTs || "-") + " traceId=" + (item.traceId || "-")).join("\n")
|
||||
? elapsedZeroResets.slice(0, 80).map((item) => "- " + formatTurnEventDisplayLabel(item) + " totalElapsed zero-reset " + (item.fromValue ?? "-") + " -> " + (item.toValue ?? "-") + " delta=" + (item.delta ?? "-") + formatTimingMeta(item) + " seq " + (item.fromSeq ?? "-") + " -> " + (item.toSeq ?? "-") + " ts " + (item.fromTs || "-") + " -> " + (item.toTs || "-") + " traceId=" + (item.traceId || "-")).join("\n")
|
||||
: "- 未观察到总耗时从非零跳回 0 秒。";
|
||||
const totalElapsedForwardJumps = Array.isArray(sampleMetrics?.turnTimingTotalElapsedForwardJumps) ? sampleMetrics.turnTimingTotalElapsedForwardJumps : [];
|
||||
const totalElapsedForwardJumpLines = totalElapsedForwardJumps.length > 0
|
||||
? totalElapsedForwardJumps.slice(0, 80).map((item) => "- " + formatTurnEventDisplayLabel(item) + " totalElapsed forward-jump " + (item.fromValue ?? "-") + " -> " + (item.toValue ?? "-") + " delta=" + (item.delta ?? "-") + " sampleDelta=" + (item.sampleDeltaSeconds ?? "-") + " allowed=" + (item.allowedIncreaseSeconds ?? "-") + " seq " + (item.fromSeq ?? "-") + " -> " + (item.toSeq ?? "-") + " ts " + (item.fromTs || "-") + " -> " + (item.toTs || "-") + " traceId=" + (item.traceId || "-")).join("\n")
|
||||
? totalElapsedForwardJumps.slice(0, 80).map((item) => "- " + formatTurnEventDisplayLabel(item) + " totalElapsed forward-jump " + (item.fromValue ?? "-") + " -> " + (item.toValue ?? "-") + " delta=" + (item.delta ?? "-") + " sampleDelta=" + (item.sampleDeltaSeconds ?? "-") + " allowed=" + (item.allowedIncreaseSeconds ?? "-") + formatTimingMeta(item) + " seq " + (item.fromSeq ?? "-") + " -> " + (item.toSeq ?? "-") + " ts " + (item.fromTs || "-") + " -> " + (item.toTs || "-") + " traceId=" + (item.traceId || "-")).join("\n")
|
||||
: "- 未观察到总耗时超出采样间隔的异常前跳。";
|
||||
const sawtoothJumps = Array.isArray(sampleMetrics?.turnTimingRecentUpdateSawtoothJumps)
|
||||
? sampleMetrics.turnTimingRecentUpdateSawtoothJumps
|
||||
@@ -2113,7 +2168,7 @@ function renderTurnTimingTable(sampleMetrics) {
|
||||
const disclosureLine = disclosure?.truncated
|
||||
? "表格披露:已按 head/tail 有界输出,totalRows=" + disclosure.totalRows + " includedRows=" + disclosure.includedRows + " omittedRows=" + disclosure.omittedRows + ";异常计数在截断前基于全量采样计算。"
|
||||
: "表格披露:完整输出当前分析窗口的采样点。";
|
||||
return disclosureLine + "\n\n" + lines.join("\n") + "\n\n列说明:\n" + columnLines + "\n\n异常事件(仅报表暴露,不做下游 repair;最近更新按三角波模型检测异常跳增):\n" + nonMonotonicLines + "\n\nTerminal 后总耗时增长事件(终态 turn 的总耗时应 sealed,不应继续增长):\n" + terminalGrowthLines + "\n\n总耗时归零跳变事件(例如已显示真实耗时后又变成 0 秒):\n" + elapsedZeroResetLines + "\n\n总耗时异常前跳事件(预期按采样间隔近似递增;例如 14 秒 -> 1137 秒应被列入这里):\n" + totalElapsedForwardJumpLines + "\n\n最近更新 sawtooth jump 事件(预期每秒增长约 1,遇到新活动归零;例如 1 秒 -> 1 分 4 秒应被列入这里):\n" + sawtoothJumpLines + "\n\n最近更新相邻采样 step(按 delta 降序;用于人工识别一秒跳几十秒/一分钟的瞬态):\n" + stepLines + "\n\n最近更新 reset 事件(预期三角波归零,不计为异常):\n" + resetLines;
|
||||
return disclosureLine + "\n\n" + lines.join("\n") + "\n\n列说明:\n" + columnLines + "\n\n时间源说明:totalElapsed 异常以 DOM Code Agent card 采样序列为观察源;completion/final-response 可用时作为 sealed source-of-truth;status=business-turn-completed 表示 timing 仅为非阻塞告警,status=observer-timeout 表示观察等待超预算,status=scenario-incomplete 表示业务回合失败或未完成。\n\n异常事件(仅报表暴露,不做下游 repair;最近更新按三角波模型检测异常跳增):\n" + nonMonotonicLines + "\n\nTerminal 后总耗时增长事件(终态 turn 的总耗时应 sealed,不应继续增长):\n" + terminalGrowthLines + "\n\n总耗时归零跳变事件(例如已显示真实耗时后又变成 0 秒):\n" + elapsedZeroResetLines + "\n\n总耗时异常前跳事件(预期按采样间隔近似递增;例如 14 秒 -> 1137 秒应被列入这里):\n" + totalElapsedForwardJumpLines + "\n\n最近更新 sawtooth jump 事件(预期每秒增长约 1,遇到新活动归零;例如 1 秒 -> 1 分 4 秒应被列入这里):\n" + sawtoothJumpLines + "\n\n最近更新相邻采样 step(按 delta 降序;用于人工识别一秒跳几十秒/一分钟的瞬态):\n" + stepLines + "\n\n最近更新 reset 事件(预期三角波归零,不计为异常):\n" + resetLines;
|
||||
}
|
||||
|
||||
function formatTurnColumnDisplayLabel(column) {
|
||||
@@ -2146,6 +2201,12 @@ function escapeMarkdownCell(value) {
|
||||
return String(value ?? "-").replace(/\|/gu, "\\|");
|
||||
}
|
||||
|
||||
function formatTimingMeta(item) {
|
||||
const source = item?.timingSourceOfTruth || item?.expectedElapsedSource || item?.evidenceKind || "-";
|
||||
const status = item?.timingStatus || "-";
|
||||
return " source=" + source + " status=" + status;
|
||||
}
|
||||
|
||||
function renderMarkdown(report) {
|
||||
const findingLines = report.findings.length === 0 ? "- 无红灯项。" : report.findings.map((item) => "- " + item.severity + ": " + item.id + " - " + item.summary).join("\n");
|
||||
const commandLines = report.commandTimeline.length === 0 ? "- 无控制命令。" : report.commandTimeline.map((item) => "- " + item.ts + " " + item.phase + " " + item.type + " " + item.commandId + " " + (item.afterUrl || "")).join("\n");
|
||||
@@ -2208,7 +2269,7 @@ function renderMarkdown(report) {
|
||||
? roundCompletion.events.slice(0, 80).map((item) => "- #" + (item.seq ?? "-") + " " + (item.ts || "-") + " prompt=" + (item.promptIndex ?? "-") + " role=" + (item.pageRole || "-") + " traceId=" + (item.traceId || "-") + " completionElapsed=" + (item.elapsedSeconds ?? "-") + " preview=" + escapeMarkdownCell(item.preview || "")).join("\n")
|
||||
: "- 未观察到“轮次完成(总耗时 ...)”trace 行。";
|
||||
const roundCompletionMismatchLines = Array.isArray(roundCompletion.elapsedMismatches) && roundCompletion.elapsedMismatches.length > 0
|
||||
? roundCompletion.elapsedMismatches.slice(0, 80).map((item) => "- #" + (item.seq ?? "-") + " " + (item.ts || "-") + " prompt=" + (item.promptIndex ?? "-") + " traceId=" + (item.traceId || "-") + " completion=" + (item.completionElapsedSeconds ?? "-") + " card=" + (item.cardTotalElapsedSeconds ?? "-") + " delta=" + (item.deltaSeconds ?? "-") + " tolerance=" + (item.toleranceSeconds ?? "-")).join("\n")
|
||||
? roundCompletion.elapsedMismatches.slice(0, 80).map((item) => "- #" + (item.seq ?? "-") + " " + (item.ts || "-") + " prompt=" + (item.promptIndex ?? "-") + " traceId=" + (item.traceId || "-") + " completion=" + (item.completionElapsedSeconds ?? "-") + " card=" + (item.cardTotalElapsedSeconds ?? "-") + " delta=" + (item.deltaSeconds ?? "-") + " tolerance=" + (item.toleranceSeconds ?? "-") + formatTimingMeta(item)).join("\n")
|
||||
: "- 未观察到轮次完成耗时与卡片耗时不一致。";
|
||||
const roundCompletionFinalMissingLines = Array.isArray(roundCompletion.finalResponseMissing) && roundCompletion.finalResponseMissing.length > 0
|
||||
? roundCompletion.finalResponseMissing.slice(0, 80).map((item) => "- #" + (item.seq ?? "-") + " " + (item.ts || "-") + " prompt=" + (item.promptIndex ?? "-") + " role=" + (item.pageRole || "-") + " traceId=" + (item.traceId || "-") + " completionElapsed=" + (item.completionElapsedSeconds ?? "-")).join("\n")
|
||||
@@ -2217,10 +2278,10 @@ function renderMarkdown(report) {
|
||||
? roundCompletion.postCompletionTimingChanges.slice(0, 80).map((item) => "- " + (item.columnLabel || item.columnId || "-") + " " + (item.metric || "-") + " " + (item.fromValue ?? "-") + " -> " + (item.toValue ?? "-") + " delta=" + (item.delta ?? "-") + " completionSeq=" + (item.seq ?? "-") + " seq " + (item.fromSeq ?? "-") + " -> " + (item.toSeq ?? "-") + " traceId=" + (item.traceId || "-")).join("\n")
|
||||
: "- 未观察到轮次完成后耗时/最近更新继续变化。";
|
||||
const durationUnderreportedLines = Array.isArray(codeAgentCardTiming.durationUnderreported) && codeAgentCardTiming.durationUnderreported.length > 0
|
||||
? codeAgentCardTiming.durationUnderreported.slice(0, 80).map((item) => "- sample=" + (item.sampleIndex ?? "-") + " " + (item.timestamp || "-") + " role=" + (item.pageRole || "-") + " status=" + (item.status || "-") + " traceId=" + (item.traceId || "-") + " card=" + (item.cardTotalElapsedSeconds ?? "-") + "s expected=" + (item.expectedElapsedSeconds ?? "-") + "s delta=" + (item.deltaSeconds ?? "-") + "s evidence=" + (item.evidenceKind || "-") + " preview=" + escapeMarkdownCell(item.evidencePreview || item.cardPreview || "")).join("\n")
|
||||
? codeAgentCardTiming.durationUnderreported.slice(0, 80).map((item) => "- sample=" + (item.sampleIndex ?? "-") + " " + (item.timestamp || "-") + " role=" + (item.pageRole || "-") + " status=" + (item.status || "-") + " traceId=" + (item.traceId || "-") + " card=" + (item.cardTotalElapsedSeconds ?? "-") + "s expected=" + (item.expectedElapsedSeconds ?? "-") + "s delta=" + (item.deltaSeconds ?? "-") + "s evidence=" + (item.evidenceKind || "-") + formatTimingMeta(item) + " preview=" + escapeMarkdownCell(item.evidencePreview || item.cardPreview || "")).join("\n")
|
||||
: "- 未观察到 Code Agent 卡片耗时低于 trace/final-response 证据。";
|
||||
const durationMismatchLines = Array.isArray(codeAgentCardTiming.durationMismatches) && codeAgentCardTiming.durationMismatches.length > 0
|
||||
? codeAgentCardTiming.durationMismatches.slice(0, 80).map((item) => "- sample=" + (item.sampleIndex ?? "-") + " " + (item.timestamp || "-") + " role=" + (item.pageRole || "-") + " status=" + (item.status || "-") + " traceId=" + (item.traceId || "-") + " direction=" + (item.direction || "-") + " card=" + (item.cardTotalElapsedSeconds ?? "-") + "s expected=" + (item.expectedElapsedSeconds ?? "-") + "s signedDelta=" + (item.signedDeltaSeconds ?? "-") + "s delta=" + (item.deltaSeconds ?? "-") + "s tolerance=" + (item.toleranceSeconds ?? "-") + "s evidence=" + (item.evidenceKind || "-") + " exact=" + String(item.exactEvidence === true) + " preview=" + escapeMarkdownCell(item.evidencePreview || item.cardPreview || "")).join("\n")
|
||||
? codeAgentCardTiming.durationMismatches.slice(0, 80).map((item) => "- sample=" + (item.sampleIndex ?? "-") + " " + (item.timestamp || "-") + " role=" + (item.pageRole || "-") + " status=" + (item.status || "-") + " traceId=" + (item.traceId || "-") + " direction=" + (item.direction || "-") + " card=" + (item.cardTotalElapsedSeconds ?? "-") + "s expected=" + (item.expectedElapsedSeconds ?? "-") + "s signedDelta=" + (item.signedDeltaSeconds ?? "-") + "s delta=" + (item.deltaSeconds ?? "-") + "s tolerance=" + (item.toleranceSeconds ?? "-") + "s evidence=" + (item.evidenceKind || "-") + " exact=" + String(item.exactEvidence === true) + formatTimingMeta(item) + " preview=" + escapeMarkdownCell(item.evidencePreview || item.cardPreview || "")).join("\n")
|
||||
: "- 未观察到 Code Agent 卡片耗时与 completion/final-response 封口证据不一致。";
|
||||
const traceOrderAnomalyLines = Array.isArray(traceOrder.orderAnomalies) && traceOrder.orderAnomalies.length > 0
|
||||
? traceOrder.orderAnomalies.slice(0, 80).map((item) => "- sample=" + (item.sampleIndex ?? "-") + " " + (item.timestamp || "-") + " role=" + (item.pageRole || "-") + " traceId=" + (item.traceId || "-") + " rows=" + (item.previousRowIndex ?? "-") + "->" + (item.currentRowIndex ?? "-") + " reasons=" + (Array.isArray(item.reasons) ? item.reasons.join(",") : "-") + " total=" + (item.previousTotalSeconds ?? "-") + "->" + (item.currentTotalSeconds ?? "-") + " clock=" + (item.previousClockSeconds ?? "-") + "->" + (item.currentClockSeconds ?? "-") + " preview=" + escapeMarkdownCell((item.previousPreview || "") + " / " + (item.currentPreview || ""))).join("\n")
|
||||
@@ -2340,7 +2401,7 @@ function renderMarkdown(report) {
|
||||
+ "- missingRecentUpdateCount: " + (codeAgentCardTimingSummary.missingRecentUpdateCount ?? 0) + "\n"
|
||||
+ "- durationUnderreportedCount: " + (codeAgentCardTimingSummary.durationUnderreportedCount ?? 0) + "\n"
|
||||
+ "- durationMismatchCount: " + (codeAgentCardTimingSummary.durationMismatchCount ?? 0) + "\n"
|
||||
+ "- policy: Code Agent 卡片无论终态/非终态都必须显示耗时;非终态必须显示最近更新。该 analyzer 只报告采样到的页面表现,不做下游 repair。\n\n"
|
||||
+ "- policy: Code Agent 卡片无论终态/非终态都必须显示耗时;非终态必须显示最近更新。completion/final-response 可用时是 sealed source-of-truth;DOM card elapsed 是显示源。该 analyzer 只报告采样到的页面表现,不做下游 repair。\n\n"
|
||||
+ "#### Missing elapsed samples\n\n" + cardMissingElapsedLines + "\n\n"
|
||||
+ "#### Missing recent update samples\n\n" + cardMissingRecentLines + "\n\n"
|
||||
+ "#### Duration underreported samples\n\n" + durationUnderreportedLines + "\n\n"
|
||||
@@ -2359,7 +2420,7 @@ function renderMarkdown(report) {
|
||||
+ "- postTimingChangeCount: " + (codeAgentCardTimingSummary.roundCompletionPostTimingChangeCount ?? 0) + "\n"
|
||||
+ "- postRecentUpdateVisibleCount: " + (codeAgentCardTimingSummary.roundCompletionPostRecentUpdateVisibleCount ?? 0) + "\n"
|
||||
+ "- elapsedMismatchToleranceSeconds: " + (codeAgentCardTimingSummary.elapsedMismatchToleranceSeconds ?? "-") + "\n"
|
||||
+ "- policy: 轮次完成(总耗时 ...) 的耗时必须与卡片总耗时一致;完成后 final response 必须可见,耗时/最近更新不得继续跳变。\n\n"
|
||||
+ "- policy: 轮次完成(总耗时 ...) 是 trace sealed source-of-truth;卡片总耗时必须与它一致。完成后 final response 必须可见,耗时/最近更新不得继续跳变。\n\n"
|
||||
+ "#### Round completion events\n\n" + roundCompletionLines + "\n\n"
|
||||
+ "#### Completion elapsed mismatches\n\n" + roundCompletionMismatchLines + "\n\n"
|
||||
+ "#### Final response missing after completion\n\n" + roundCompletionFinalMissingLines + "\n\n"
|
||||
|
||||
Reference in New Issue
Block a user