From 618f52fe46ea2cd4c6fe57515d5c97adf80f442f Mon Sep 17 00:00:00 2001 From: root Date: Mon, 20 Jul 2026 20:56:28 +0200 Subject: [PATCH] fix: distinguish source preparation from retry failures --- tools/src/hwlab-cli/trace-renderer.ts | 7 ++- .../components/agent/TraceTimeline.test.ts | 52 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/tools/src/hwlab-cli/trace-renderer.ts b/tools/src/hwlab-cli/trace-renderer.ts index d2c65564..71e05d41 100644 --- a/tools/src/hwlab-cli/trace-renderer.ts +++ b/tools/src/hwlab-cli/trace-renderer.ts @@ -117,7 +117,12 @@ export function traceDisplayRows(trace: Record = {}, events: Tr } function isSemanticFailureRetryEvent(event: TraceEvent): boolean { - return Boolean(nonEmptyString(event.failureDomain) && nonEmptyString(event.retryPhase)); + if (!nonEmptyString(event.failureDomain)) return false; + const phase = normalizedRetryPhase(event.retryPhase); + return phase.includes("scheduled") + || phase.includes("exhausted") + || phase.includes("recovered") + || (phase.includes("retry") && phase.includes("started")); } function traceSemanticFailureRetryRow(event: TraceEvent, options: ResolvedTraceDisplayRowsOptions): TraceEventRow { diff --git a/web/hwlab-cloud-web/src/components/agent/TraceTimeline.test.ts b/web/hwlab-cloud-web/src/components/agent/TraceTimeline.test.ts index ad3c6a08..271341b0 100644 --- a/web/hwlab-cloud-web/src/components/agent/TraceTimeline.test.ts +++ b/web/hwlab-cloud-web/src/components/agent/TraceTimeline.test.ts @@ -179,6 +179,58 @@ describe("TraceTimeline sequence authority", () => { wrapper.unmount(); }); + it("does not classify normal Git source preparation as an infrastructure failure", async () => { + const wrapper = mount(TraceTimeline, { + props: { + autoExpanded: true, + trace: { + traceId: "trc_git_fetch_timeline", + eventSource: "hwlab-kafka-sse", + status: "completed", + eventCount: 2, + events: [{ + sourceEventId: "evt_git_fetch_started", + runId: "run_git_fetch", + sourceSeq: 5, + source: "agentrun.kafka", + type: "backend", + status: "running", + label: "agentrun:backend:runner-source-fetch-started", + failureDomain: "infrastructure", + failureComponent: "git-mirror", + failureCode: "git-mirror-fetch-in-progress", + summary: "正在从 Git mirror 获取 Runner 源码", + retryPhase: "initialAttempt", + retryAttempt: 1, + retryMaxAttempts: 3, + createdAt: "2026-07-20T10:00:01.000Z" + }, { + sourceEventId: "evt_git_fetch_completed", + runId: "run_git_fetch", + sourceSeq: 6, + source: "agentrun.kafka", + type: "backend", + status: "running", + label: "agentrun:backend:runner-source-fetch-completed", + failureDomain: "infrastructure", + failureComponent: "git-mirror", + failureCode: "git-mirror-fetch-completed", + summary: "Git mirror 源码获取完成", + retryPhase: "initialAttempt", + retryAttempt: 1, + retryMaxAttempts: 3, + createdAt: "2026-07-20T10:00:03.000Z" + }] + } + } + }); + await nextTick(); + + expect(wrapper.text()).not.toContain("基础设施故障"); + expect(wrapper.findAll('[data-row-id^="event:semantic-retry:"]')).toHaveLength(0); + wrapper.unmount(); + }); + it("keeps a tool row stable while projecting visual and accessibility state", async () => { const wrapper = mount(TraceTimeline, { props: {