// SPEC: PJ2026-01040111 long-running Workbench observation.
// Responsibility: Analyzer top-level findings, cross-page projection drilldown, and frontend freeze source fragment.

export function nodeWebObserveAnalyzerFindingsSource(): string {
  return String.raw`function buildFindings(samples, control, network, errors, sampleMetrics, promptNetwork, runtimeAlerts, pagePerformance, requestRate, pageProvenance, commandFailures = [], manifest = {}, apiDomLag = null, browserProcess = null, frontendPerformance = null) {
  const findings = [];
  const effectiveApiDomLag = apiDomLag || buildApiDomLagReport(samples, network);
  const compactCommandFailures = commandFailures.map(compactObserverCommandFailure);
  const firstCommandFailure = compactCommandFailures[0] || null;
  if (commandFailures.length > 0) findings.push({
    id: "observer-command-failed",
    severity: "red",
    summary: "observer control commands failed; analyze must surface the first failed command with phase/status/stdout/stderr evidence.",
    count: commandFailures.length,
    firstCommandFailure,
    evidenceSummary: firstCommandFailure ? "command=" + (firstCommandFailure.commandId || "-") + " type=" + (firstCommandFailure.type || "-") + " phase=" + (firstCommandFailure.phase || "-") + " status=" + (firstCommandFailure.status || "-") + " resultOk=" + (firstCommandFailure.resultOk ?? "-") + " failedReason=" + (firstCommandFailure.failedReason || firstCommandFailure.failureKind || firstCommandFailure.message || "-") : "commandFailures>0",
    commands: compactCommandFailures.slice(0, 20)
  });
  findings.push(...buildFrontendFreezeFindings(errors, control));
  findings.push(...buildBrowserProcessFindings(browserProcess, runtimeAlerts));
  findings.push(...buildFrontendPerformanceFindings(frontendPerformance));
  findings.push(...buildControlledNavigationRootCauseFindings(control, manifest));
  findings.push(...buildSessionInvariantFindings(control, manifest));
  const commandTimes = control
    .filter((item) => item.phase === "completed" || item.phase === "started" || item.type === "observer-periodic-refresh")
    .map((item) => Date.parse(item.ts))
    .filter(Number.isFinite);
  const controlledNavigationWindows = sessionInvariantNavigationWindows(control);
  const routeSessions = new Set(samples.map((item) => item.routeSessionId).filter(Boolean));
  const activeSessions = new Set(samples.map((item) => item.activeSessionId).filter(Boolean));
  const routeSessionUnexpected = sessionChangeSamplesOutsideControlledNavigation(samples, "routeSessionId", controlledNavigationWindows);
  const activeSessionUnexpected = sessionChangeSamplesOutsideControlledNavigation(samples, "activeSessionId", controlledNavigationWindows);
  if (routeSessions.size > 1 && routeSessionUnexpected.length > 0) findings.push({ id: "session-route-changed", severity: "amber", summary: "route session changed outside controlled session-invariance navigation windows", routeSessionCount: routeSessions.size, samples: sampleRefs(routeSessionUnexpected, (item) => item.routeSessionId) });
  if (activeSessions.size > 1 && activeSessionUnexpected.length > 0) findings.push({ id: "active-session-changed", severity: "amber", summary: "active session changed outside controlled session-invariance navigation windows", activeSessionCount: activeSessions.size, samples: sampleRefs(activeSessionUnexpected, (item) => item.activeSessionId) });
  const mismatches = samples.filter((item) => item.routeSessionId && item.activeSessionId && item.routeSessionId !== item.activeSessionId && !sampleInControlledNavigationWindow(item, controlledNavigationWindows));
  if (mismatches.length > 0) findings.push({ id: "route-active-session-mismatch", severity: "red", summary: "routeSessionId and activeSessionId diverged", count: mismatches.length, samples: mismatches.slice(0, 10).map(ref) });
  const uncommandedChanges = [];
  const commandedPromptSeqs = new Set((sampleMetrics?.timeline ?? []).filter((item) => Number(item?.promptIndex) > 0).map((item) => item.seq).filter((seq) => seq !== null && seq !== undefined));
  const previousDigestByPage = new Map();
  for (const sample of samples) {
    const pageKey = samplePageKey(sample);
    const previous = previousDigestByPage.get(pageKey);
    const next = digestSample(sample);
    if (previous && previous.digest !== next && !commandedPromptSeqs.has(sample?.seq) && !nearCommand(sample, commandTimes, alertThresholds.uncommandedStateChangeCommandWindowMs)) {
      uncommandedChanges.push({
        ...ref(sample),
        previousSeq: previous.sample?.seq ?? null,
        previousTs: previous.sample?.timestamp ?? previous.sample?.ts ?? null,
        fromDigest: previous.digest,
        toDigest: next,
        fromMessageCount: previous.sample?.messageCount ?? previous.sample?.messages?.length ?? null,
        toMessageCount: sample?.messageCount ?? sample?.messages?.length ?? null,
        fromTraceRowCount: Array.isArray(previous.sample?.traceRows) ? previous.sample.traceRows.length : previous.sample?.traceRowCount ?? null,
        toTraceRowCount: Array.isArray(sample?.traceRows) ? sample.traceRows.length : sample?.traceRowCount ?? null,
        fromPath: previous.sample?.path ?? previous.sample?.urlPath ?? null,
        toPath: sample?.path ?? sample?.urlPath ?? null,
        detail: "visible digest changed without nearby command",
      });
    }
    previousDigestByPage.set(pageKey, { digest: next, sample });
  }
  if (uncommandedChanges.length > 0) findings.push({ id: "uncommanded-visible-state-change", severity: "amber", summary: "visible message/trace digest changed without a nearby command", count: uncommandedChanges.length, samples: uncommandedChanges.slice(0, 20) });
  const finalFlicker = detectFinalFlicker(samples);
  if (finalFlicker.length > 0) findings.push({ id: "final-response-flicker", severity: "red", summary: "message text digest disappeared or switched to diagnostic-like text after non-empty final text", count: finalFlicker.length, samples: finalFlicker.slice(0, 20) });
  const terminalZeroElapsed = detectTerminalZeroElapsed(samples);
  if (terminalZeroElapsed.length > 0) findings.push({ id: "turn-terminal-zero-elapsed", severity: "amber", summary: "terminal Code Agent card displayed 耗时 0 秒; terminal duration issue is a non-blocking timing alert", count: terminalZeroElapsed.length, samples: terminalZeroElapsed.slice(0, 20) });
  const cardTiming = sampleMetrics?.codeAgentCardTiming || {};
  const cardTimingSummary = cardTiming.summary || {};
  if (Number(cardTimingSummary.missingElapsedCount ?? 0) > 0) findings.push({ id: "code-agent-card-elapsed-missing", severity: "amber", summary: "visible Code Agent card did not display total elapsed time; elapsed visibility is a non-blocking timing alert", count: cardTimingSummary.missingElapsedCount, samples: (cardTiming.missingElapsed || []).slice(0, 20) });
  if (Number(cardTimingSummary.missingRecentUpdateCount ?? 0) > 0) findings.push({ id: "code-agent-card-running-recent-update-missing", severity: "amber", summary: "non-terminal Code Agent card did not display 最近更新; recent-update visibility is a non-blocking timing alert", count: cardTimingSummary.missingRecentUpdateCount, samples: (cardTiming.missingRecentUpdate || []).slice(0, 20) });
  const roundCompletion = cardTiming.roundCompletion || {};
  if (Number(cardTimingSummary.durationUnderreportedCount ?? 0) > 0) {
    findings.push({
      id: "code-agent-card-duration-underreported",
      severity: "amber",
      summary: "completed Code Agent card total elapsed is shorter than trace/final-response duration evidence; timing mismatch is a non-blocking alert",
      timingSourceOfTruth: "trace-completion-total-or-final-response-duration",
      timingStatus: timingStatusFromRows(cardTiming.durationUnderreported, "business-turn-completed"),
      timingAlert: true,
      count: cardTimingSummary.durationUnderreportedCount,
      samples: (cardTiming.durationUnderreported || []).slice(0, 20),
    });
  }
  if (Number(cardTimingSummary.durationMismatchCount ?? 0) > 0) {
    findings.push({
      id: "code-agent-card-duration-mismatch",
      severity: "amber",
      summary: "completed Code Agent card total elapsed does not match sealed completion/final-response timing evidence; timing mismatch is a non-blocking alert",
      timingSourceOfTruth: "trace-completion-total-or-final-response-duration",
      timingStatus: timingStatusFromRows(cardTiming.durationMismatches, "business-turn-completed"),
      timingAlert: true,
      count: cardTimingSummary.durationMismatchCount,
      samples: (cardTiming.durationMismatches || []).slice(0, 20),
    });
  }
  const traceOrder = sampleMetrics?.traceOrder || {};
  const traceOrderSummary = traceOrder.summary || {};
  if (Number(traceOrderSummary.orderAnomalyCount ?? 0) > 0) {
    findings.push({
      id: "trace-row-order-nonmonotonic",
      severity: "red",
      summary: "visible trace rows are not monotonic by total time, clock time, or projected sequence in DOM order",
      count: traceOrderSummary.orderAnomalyCount,
      samples: (traceOrder.orderAnomalies || []).slice(0, 20),
    });
  }
  if (Number(traceOrderSummary.completionNotLastCount ?? 0) > 0) {
    findings.push({
      id: "trace-completion-row-not-last",
      severity: "red",
      summary: "visible trace shows a completion row before later trace rows for the same trace",
      count: traceOrderSummary.completionNotLastCount,
      samples: (traceOrder.completionNotLast || []).slice(0, 20),
    });
  }
  if (Number(cardTimingSummary.roundCompletionElapsedMismatchCount ?? 0) > 0) findings.push({ id: "round-completion-elapsed-mismatch", severity: "amber", summary: "Trace row 轮次完成（总耗时 ...） does not match the visible Code Agent card total elapsed time within YAML timing slack; timing mismatch is a non-blocking alert", timingSourceOfTruth: "trace-round-completion-total", timingStatus: timingStatusFromRows(roundCompletion.elapsedMismatches, "business-turn-completed"), timingAlert: true, count: cardTimingSummary.roundCompletionElapsedMismatchCount, toleranceSeconds: cardTimingSummary.elapsedMismatchToleranceSeconds, samples: (roundCompletion.elapsedMismatches || []).slice(0, 20) });
  if (Number(cardTimingSummary.roundCompletionFinalResponseMissingCount ?? 0) > 0) findings.push({ id: "round-completion-final-response-missing", severity: "red", summary: "Trace row showed 轮次完成, but no final response was visible in the Code Agent card afterward", count: cardTimingSummary.roundCompletionFinalResponseMissingCount, samples: (roundCompletion.finalResponseMissing || []).slice(0, 20) });
  if (Number(cardTimingSummary.roundCompletionPostTimingChangeCount ?? 0) > 0) findings.push({ id: "round-completion-post-timing-change", severity: "amber", summary: "After 轮次完成, card total elapsed or 最近更新 continued changing; terminal timing alert is non-blocking", count: cardTimingSummary.roundCompletionPostTimingChangeCount, samples: (roundCompletion.postCompletionTimingChanges || []).slice(0, 20) });
  if (Number(cardTimingSummary.roundCompletionPostRecentUpdateVisibleCount ?? 0) > 0) findings.push({ id: "round-completion-recent-update-still-visible", severity: "info", summary: "最近更新 was still visible after 轮次完成; inspect whether terminal cards should hide activity age or keep it sealed", count: cardTimingSummary.roundCompletionPostRecentUpdateVisibleCount, samples: (roundCompletion.postCompletionRecentUpdateVisible || []).slice(0, 20) });
  const scrollJumps = [];
  for (let i = 1; i < samples.length; i += 1) {
    const prevY = Number(samples[i - 1]?.scroll?.y ?? 0);
    const nextY = Number(samples[i]?.scroll?.y ?? 0);
    if (prevY > alertThresholds.scrollJumpFromY && nextY < alertThresholds.scrollJumpToY && !nearCommand(samples[i], commandTimes, alertThresholds.scrollJumpCommandWindowMs)) scrollJumps.push({ from: ref(samples[i - 1]), to: ref(samples[i]) });
  }
  if (scrollJumps.length > 0) findings.push({ id: "scroll-jump-top", severity: "amber", summary: "scroll position jumped near top without nearby command", count: scrollJumps.length, samples: scrollJumps.slice(0, 10) });
  const traceTerminal = samples.some((item) => Array.isArray(item.traceRows) && item.traceRows.some((row) => isTerminalTraceText((row.status || "") + " " + (row.textPreview || ""))));
  const traceSeen = samples.some((item) => Array.isArray(item.traceRows) && item.traceRows.length > 0);
  if (traceSeen && !traceTerminal) findings.push({ id: "trace-without-terminal", severity: "amber", summary: "trace rows were visible but no terminal status was sampled", firstTraceSample: ref(samples.find((item) => Array.isArray(item.traceRows) && item.traceRows.length > 0)) });
  const workbenchInPlaceProjectionLag = detectWorkbenchInPlaceProjectionLag(samples, network, control);
  if (workbenchInPlaceProjectionLag.terminalTraceMissing.length > 0) findings.push({
    id: "workbench-terminal-trace-not-hydrated-in-place",
    severity: "red",
    summary: "Workbench rendered a terminal turn/message in-place while the same trace still had no visible run-record trace rows",
    count: workbenchInPlaceProjectionLag.terminalTraceMissing.length,
    samples: workbenchInPlaceProjectionLag.terminalTraceMissing.slice(0, 20),
    rootCause: "workbench_trace_projection_not_hydrated_in_place",
    rootCauseStatus: "confirmed-from-dom-samples",
    rootCauseConfidence: "high",
    valuesRedacted: true
  });
  if (workbenchInPlaceProjectionLag.terminalApiDomLag.overBudget.length > 0) findings.push({
    id: "workbench-terminal-api-dom-not-refreshed-in-place",
    severity: "red",
    summary: "Workbench REST returned terminal/final trace evidence but the same in-place page did not render terminal message plus trace rows within the configured budget",
    count: workbenchInPlaceProjectionLag.terminalApiDomLag.overBudget.length,
    budgetMs: workbenchInPlaceProjectionLag.terminalApiDomLag.summary.budgetMs,
    windowMs: workbenchInPlaceProjectionLag.terminalApiDomLag.summary.windowMs,
    samples: workbenchInPlaceProjectionLag.terminalApiDomLag.overBudget.slice(0, 20),
    rootCause: "workbench_rest_terminal_projection_dom_lag",
    rootCauseStatus: "confirmed-from-network-body-summary-and-dom-samples",
    rootCauseConfidence: "high",
    valuesRedacted: true
  });
  const recoveryAuthority = workbenchInPlaceProjectionLag.recoveryAuthority || {};
  const recoveryAuthoritySummary = recoveryAuthority.summary || {};
  const forbiddenRecoveryCount = Number(recoveryAuthoritySummary.forbiddenAutomaticRecoveryCount ?? 0);
  const legacyFanoutWindowCount = Number(recoveryAuthoritySummary.legacyFanoutWindowCount ?? 0);
  if (forbiddenRecoveryCount > 0 || legacyFanoutWindowCount > 0) findings.push({
    id: "workbench-automatic-recovery-fanout-authority",
    severity: "red",
    summary: "Workbench automatic recovery used direct trace/session/turn fan-out instead of sync replay authority",
    count: forbiddenRecoveryCount + legacyFanoutWindowCount,
    forbiddenAutomaticRecoveryCount: forbiddenRecoveryCount,
    legacyFanoutWindowCount,
    syncReplayEvidenceCount: Number(recoveryAuthoritySummary.syncReplayEvidenceCount ?? 0),
    syncReplayAppliedCount: Number(recoveryAuthoritySummary.syncReplayAppliedCount ?? 0),
    recoveryAuthority: {
      summary: recoveryAuthoritySummary,
      forbiddenAutomaticRecovery: Array.isArray(recoveryAuthority.forbiddenAutomaticRecovery) ? recoveryAuthority.forbiddenAutomaticRecovery.slice(0, 12) : [],
      legacyFanoutWindows: Array.isArray(recoveryAuthority.legacyFanoutWindows) ? recoveryAuthority.legacyFanoutWindows.slice(0, 12) : [],
      syncEvidence: Array.isArray(recoveryAuthority.syncEvidence) ? recoveryAuthority.syncEvidence.slice(-12) : [],
      observabilityGaps: Array.isArray(recoveryAuthority.observabilityGaps) ? recoveryAuthority.observabilityGaps.slice(0, 8) : [],
      valuesRedacted: true
    },
    sourceOfTruth: "Workbench sync replay / entity version / terminal seal authority; explicit detail/history reads are allowed but automatic recovery must not hydrate direct REST fan-out",
    rootCause: "workbench_automatic_recovery_legacy_fanout",
    rootCauseStatus: "confirmed-from-web-performance-runtime-diagnostics-and-network-artifacts",
    rootCauseConfidence: "high",
    valuesRedacted: true
  });
  const turnStateTriad = sampleMetrics?.workbenchTurnStateTriad || {};
  const turnStateTriadSummary = turnStateTriad.summary || {};
  const turnStateTriadRows = [
    ...(Array.isArray(turnStateTriad.invalidFullTriads) ? turnStateTriad.invalidFullTriads : []),
    ...(Array.isArray(turnStateTriad.cardFinalResponseMismatches) ? turnStateTriad.cardFinalResponseMismatches : [])
  ];
  if (Number(turnStateTriadSummary.invalidRowCount ?? 0) > 0) {
    const drilldown = turnStateTriad.drilldown ?? buildWorkbenchTurnStateTriadDrilldown(turnStateTriadRows);
    const rootCause = workbenchTriadRootCauseFromDrilldown(drilldown, turnStateTriadSummary);
    findings.push({
      id: "workbench-turn-state-triad-inconsistent",
      severity: "red",
      summary: rootCause.summary,
      count: turnStateTriadSummary.invalidRowCount,
      fullTriadCount: turnStateTriadSummary.fullTriadRowCount,
      invalidFullTriadCount: turnStateTriadSummary.invalidFullTriadCount,
      cardFinalResponseMismatchCount: turnStateTriadSummary.cardFinalResponseMismatchCount,
      legacyCollectorMissingCount: turnStateTriadSummary.collectorMissingRowCount,
      collectorMissingFields: Array.isArray(turnStateTriadSummary.collectorMissingFields) ? turnStateTriadSummary.collectorMissingFields : [],
      dominantMismatchKind: rootCause.dominantMismatchKind,
      allowedTuples: [
        { railStatus: "completed", cardStatus: "completed", finalResponsePresent: true },
        { railStatus: "running", cardStatus: "running", finalResponsePresent: false }
      ],
      samples: turnStateTriadRows.slice(0, 20),
      drilldown,
      collectorMissingSamples: Array.isArray(turnStateTriad.collectorMissingRows) ? turnStateTriad.collectorMissingRows.slice(0, 10) : [],
      sourceOfTruth: rootCause.sourceOfTruth + "; do not repair via DOM fallback or GET-side state mutation",
      nextAction: rootCause.nextAction,
      rootCause: rootCause.rootCause,
      rootCauseStatus: rootCause.rootCauseStatus,
      rootCauseConfidence: rootCause.rootCauseConfidence,
      valuesRedacted: true
    });
  }
  const promptFailures = Array.isArray(promptNetwork?.rounds) ? promptNetwork.rounds.filter((item) => item.chatPostOk === false && !promptCommandHasAuthoritativeSubmitSideEffect(control, item)) : [];
  if (promptFailures.length > 0) findings.push({ id: "prompt-chat-submit-failed", severity: "red", summary: "sendPrompt command had no successful /v1/agent/chat or /v1/agent/chat/steer POST response in the sampling window", count: promptFailures.length, rounds: promptFailures.slice(0, 10) });
  const promptSteerRounds = Array.isArray(promptNetwork?.rounds) ? promptNetwork.rounds.filter((item) => item.steerUsed === true) : [];
  if (promptSteerRounds.length > 0) findings.push({ id: "prompt-routed-to-steer", severity: "amber", summary: "sendPrompt was submitted through /v1/agent/chat/steer; verify the previous turn was truly in-flight and not an unsealed terminal failure", count: promptSteerRounds.length, rounds: promptSteerRounds.slice(0, 10) });
  const elapsedZeroResets = Array.isArray(sampleMetrics?.turnTimingElapsedZeroResets) ? sampleMetrics.turnTimingElapsedZeroResets : [];
  if (elapsedZeroResets.length > 0) findings.push({ id: "turn-timing-total-elapsed-zero-reset", severity: "amber", summary: "Code Agent total elapsed jumped from a non-zero value back to 0 seconds; timing reset is a non-blocking alert", timingSourceOfTruth: "dom-card-total-elapsed-sequence", timingStatus: timingStatusFromRows(elapsedZeroResets), timingAlert: true, count: elapsedZeroResets.length, samples: elapsedZeroResets.slice(0, 20) });
  const elapsedDecreases = Array.isArray(sampleMetrics?.turnTimingNonMonotonic)
    ? sampleMetrics.turnTimingNonMonotonic.filter((item) => item.metric === "totalElapsedSeconds" && item.anomaly !== "zero-reset")
    : [];
  if (elapsedDecreases.length > 0) findings.push({ id: "turn-timing-total-elapsed-decrease", severity: "amber", summary: "Code Agent total elapsed decreased between adjacent samples; timing decrease is a non-blocking alert", timingSourceOfTruth: "dom-card-total-elapsed-sequence", timingStatus: timingStatusFromRows(elapsedDecreases), timingAlert: true, count: elapsedDecreases.length, samples: elapsedDecreases.slice(0, 20) });
  const elapsedForwardJumps = Array.isArray(sampleMetrics?.turnTimingTotalElapsedForwardJumps) ? sampleMetrics.turnTimingTotalElapsedForwardJumps : [];
  if (elapsedForwardJumps.length > 0) findings.push({ id: "turn-timing-total-elapsed-forward-jump", severity: "amber", summary: "Code Agent total elapsed jumped forward faster than browser sample interval; timing jump is a non-blocking alert", timingSourceOfTruth: "dom-card-total-elapsed-sequence", timingStatus: timingStatusFromRows(elapsedForwardJumps), timingAlert: true, count: elapsedForwardJumps.length, samples: elapsedForwardJumps.slice(0, 20) });
  const terminalElapsedGrowth = Array.isArray(sampleMetrics?.turnTimingTerminalElapsedGrowth) ? sampleMetrics.turnTimingTerminalElapsedGrowth : [];
  if (terminalElapsedGrowth.length > 0) findings.push({ id: "turn-timing-terminal-elapsed-growth", severity: "amber", summary: "terminal Code Agent card total elapsed changed after terminal status; terminal timing alert is non-blocking", timingSourceOfTruth: "terminal-card-total-elapsed-seal", timingStatus: timingStatusFromRows(terminalElapsedGrowth, "business-turn-completed"), timingAlert: true, count: terminalElapsedGrowth.length, samples: terminalElapsedGrowth.slice(0, 20) });
  const recentUpdateSawtoothJumps = Array.isArray(sampleMetrics?.turnTimingRecentUpdateSawtoothJumps)
    ? sampleMetrics.turnTimingRecentUpdateSawtoothJumps
    : Array.isArray(sampleMetrics?.turnTimingNonMonotonic)
      ? sampleMetrics.turnTimingNonMonotonic.filter((item) => item.metric === "recentUpdateSeconds" && item.anomaly === "jump")
      : [];
  if (recentUpdateSawtoothJumps.length > 0) findings.push({ id: "turn-timing-recent-update-sawtooth-jump", severity: "amber", summary: "最近更新 value jumped faster than sample interval; expected sawtooth increase-or-reset", count: recentUpdateSawtoothJumps.length, samples: recentUpdateSawtoothJumps.slice(0, 20) });
  const severeTimeoutRounds = Array.isArray(sampleMetrics?.rounds) ? sampleMetrics.rounds.filter((item) => Number(item.maxTotalElapsedSeconds) > alertThresholds.turnElapsedSevereTimeoutSeconds) : [];
  const severeTimeoutSamples = Array.isArray(sampleMetrics?.timeline) ? sampleMetrics.timeline.filter((item) => Number(item.totalElapsedSeconds) > alertThresholds.turnElapsedSevereTimeoutSeconds) : [];
  if (severeTimeoutRounds.length > 0 || severeTimeoutSamples.length > 0) findings.push({ id: "turn-elapsed-severe-timeout", severity: "amber", summary: "turn total elapsed exceeded the YAML-configured elapsed alert threshold; timing is a non-blocking alert unless the turn fails to complete or breaks multi-round continuity", timingSourceOfTruth: "dom-card-total-elapsed-yaml-threshold", timingStatus: timingStatusFromRows([...severeTimeoutRounds, ...severeTimeoutSamples], "observer-timeout"), timingAlert: true, thresholdSeconds: alertThresholds.turnElapsedSevereTimeoutSeconds, count: Math.max(severeTimeoutRounds.length, severeTimeoutSamples.length), rounds: severeTimeoutRounds.slice(0, 20), samples: severeTimeoutSamples.slice(0, 20) });
  const loadingSummary = sampleMetrics?.loading?.summary || {};
  const visibleLoadingSlowSeconds = alertThresholds.visibleLoadingSlowMs / 1000;
  if (Number(loadingSummary.longestContinuousSeconds ?? 0) > visibleLoadingSlowSeconds) findings.push({ id: "page-loading-visible-over-budget", severity: "red", summary: "visible 加载中 stayed on screen longer than configured YAML budget; fix real loading latency instead of revealing incomplete content early", count: loadingSummary.overBudgetSegmentCount ?? loadingSummary.overFiveSecondSegmentCount ?? 1, longestContinuousSeconds: loadingSummary.longestContinuousSeconds, budgetSeconds: visibleLoadingSlowSeconds, segments: sampleMetrics.loading.segments.slice(0, 20), owners: sampleMetrics.loading.owners.slice(0, 20) });
  if (Number(loadingSummary.maxSimultaneousCount ?? 0) > 1) findings.push({ id: "page-loading-concurrent", severity: "info", summary: "multiple 加载中 indicators were visible in the same sampled DOM point", count: loadingSummary.concurrentLoadingSampleCount ?? 0, maxSimultaneousCount: loadingSummary.maxSimultaneousCount, owners: sampleMetrics.loading.owners.slice(0, 20) });
  const sessionRailTitleSummary = sampleMetrics?.sessionRailTitles?.summary || {};
  if (Number(sessionRailTitleSummary.overThresholdSampleCount ?? sessionRailTitleSummary.majorityFallbackSampleCount ?? 0) > 0) findings.push({
    id: "session-rail-title-fallback-root-cause",
    severity: "red",
    summary: "INV-02 root cause visible: session rail is rendering fallback Session ses_* titles, so list projection/read model or rail binding is missing stable title/preview data before DOM render",
    rootCause: "session_title_fallback_from_facts",
    rootCauseStatus: "confirmed-from-dom-session-rail",
    rootCauseConfidence: "high",
    nextAction: "Check OTel session_list_read fallbackTitleCount/fallbackTitleRatio and emptyPreviewCount for the same run; fix session list projection/read model title/preview before changing DOM fallback text.",
    count: sessionRailTitleSummary.overThresholdSampleCount ?? sessionRailTitleSummary.majorityFallbackSampleCount,
    thresholdRatio: alertThresholds.sessionRailFallbackRatio,
    maxFallbackRatio: sessionRailTitleSummary.maxFallbackRatio,
    maxFallbackTitleCount: sessionRailTitleSummary.maxFallbackTitleCount,
    evidence: {
      thresholdRatio: alertThresholds.sessionRailFallbackRatio,
      maxFallbackRatio: sessionRailTitleSummary.maxFallbackRatio,
      maxFallbackTitleCount: sessionRailTitleSummary.maxFallbackTitleCount,
      overThresholdSampleCount: sessionRailTitleSummary.overThresholdSampleCount ?? null,
      majorityFallbackSampleCount: sessionRailTitleSummary.majorityFallbackSampleCount ?? null,
      valuesRedacted: true
    },
    samples: sampleMetrics.sessionRailTitles.samples.slice(0, 20),
    examples: sampleMetrics.sessionRailTitles.examples.slice(0, 20),
    valuesRedacted: true
  });
  const traceEventsPageReadIssues = detectTraceEventsPageReadIssues(network);
  if (traceEventsPageReadIssues.http404.length > 0) findings.push({
    id: "trace-events-page-read-404-root-cause",
    severity: "red",
    summary: "INV-07 root cause visible: /v1/workbench/traces/:traceId/events returned HTTP 404 for a trace event page read, so the failure is in the trace-events API paging/read-model contract before DOM rendering",
    rootCause: "trace_events_paging_contract_mismatch",
    rootCauseStatus: "confirmed-from-browser-network",
    rootCauseConfidence: "high",
    nextAction: "Use OTel trace_events_read for the same trace to compare sinceSeq/afterProjectedSeq, returnedEvents, range, totalEvents, hasMore and fullTraceLoaded; fix backend paging contract or add missing instrumentation before changing renderer behavior.",
    count: traceEventsPageReadIssues.http404.length,
    evidence: traceEventsPageReadIssues.summary,
    samples: traceEventsPageReadIssues.http404.slice(0, 20),
    valuesRedacted: true
  });
  if (traceEventsPageReadIssues.httpErrors.length > 0) findings.push({
    id: "trace-events-page-read-http-error-root-cause",
    severity: "red",
    summary: "trace events page read returned HTTP error status; monitor can localize this to the trace-events API instead of a generic Workbench render failure",
    rootCause: "trace-events-api-page-read-http-error",
    rootCauseStatus: "confirmed-from-browser-network",
    rootCauseConfidence: "high",
    nextAction: "Drill down by traceId and afterProjectedSeq, then compare with OTel trace_events_read paging fields.",
    count: traceEventsPageReadIssues.httpErrors.length,
    evidence: traceEventsPageReadIssues.summary,
    samples: traceEventsPageReadIssues.httpErrors.slice(0, 20),
    valuesRedacted: true
  });
  if (traceEventsPageReadIssues.requestFailed.length > 0) findings.push({
    id: "trace-events-page-read-requestfailed-root-cause",
    severity: "amber",
    summary: "trace events page read failed at browser/network level; monitor localized the failure path, but HTTP status is unavailable so OTel/API instrumentation is needed to confirm the backend root cause",
    rootCause: "trace-events-api-page-read-network-failed",
    rootCauseStatus: "network-signal-needs-otel-confirmation",
    rootCauseConfidence: "medium",
    nextAction: "Check whether this happened during observer refresh/navigation; if not, query OTel by /v1/workbench/traces/:traceId/events and add route span fields when status/afterProjectedSeq are missing.",
    count: traceEventsPageReadIssues.requestFailed.length,
    evidence: traceEventsPageReadIssues.summary,
    samples: traceEventsPageReadIssues.requestFailed.slice(0, 20),
    valuesRedacted: true
  });
  const pageResponseErrorGroups = Array.isArray(runtimeAlerts?.networkPageResponseErrorsByPath)
    ? runtimeAlerts.networkPageResponseErrorsByPath
    : (Array.isArray(runtimeAlerts?.networkHttpErrorsByPath) ? runtimeAlerts.networkHttpErrorsByPath.filter((item) => Number(item?.status) >= 500) : []);
  const nonBlockingHttpErrorGroups = Array.isArray(runtimeAlerts?.networkNonBlockingHttpErrorsByPath)
    ? runtimeAlerts.networkNonBlockingHttpErrorsByPath
    : (Array.isArray(runtimeAlerts?.networkHttpErrorsByPath) ? runtimeAlerts.networkHttpErrorsByPath.filter((item) => Number(item?.status) < 500) : []);
  if ((runtimeAlerts?.summary?.pageResponseErrorCount ?? pageResponseErrorGroups.reduce((sum, item) => sum + Number(item?.count ?? 0), 0)) > 0) findings.push({
    id: "page-response-error",
    severity: "red",
    summary: "页面响应错误：浏览器在运行页面捕获到 HTTP 5xx 响应，属于阻塞错误。",
    displayTitleZh: "页面响应错误",
    errorTitleZh: "页面响应错误",
    rootCause: "page-response-http-5xx",
    rootCauseStatus: "confirmed-from-browser-network-response",
    rootCauseConfidence: "high",
    nextAction: "按状态码和路径追溯后端日志/OTel；先修复 5xx 响应，不要把它归类为前端渲染或采样抖动。",
    blocking: true,
    count: runtimeAlerts?.summary?.pageResponseErrorCount ?? pageResponseErrorGroups.reduce((sum, item) => sum + Number(item?.count ?? 0), 0),
    evidenceSummary: pageResponseErrorGroups.slice(0, 4).map((item) => "HTTP " + (item.status ?? "-") + " " + (item.method || "-") + " " + (item.urlPath || "-") + " count=" + (item.count ?? "-")).join("; "),
    groups: pageResponseErrorGroups.slice(0, 12),
    valuesRedacted: true
  });
  if ((runtimeAlerts?.summary?.nonBlockingHttpErrorCount ?? nonBlockingHttpErrorGroups.reduce((sum, item) => sum + Number(item?.count ?? 0), 0)) > 0) findings.push({ id: "runtime-http-errors", severity: "amber", summary: "natural page requests returned non-5xx HTTP error status during observation", count: runtimeAlerts?.summary?.nonBlockingHttpErrorCount ?? nonBlockingHttpErrorGroups.reduce((sum, item) => sum + Number(item?.count ?? 0), 0), groups: nonBlockingHttpErrorGroups.slice(0, 12) });
  if ((runtimeAlerts?.summary?.significantRequestFailedCount ?? runtimeAlerts?.summary?.requestFailedCount ?? 0) > 0) findings.push({ id: "runtime-requestfailed", severity: "amber", summary: "browser requestfailed events were captured during observation", count: runtimeAlerts.summary.significantRequestFailedCount ?? runtimeAlerts.summary.requestFailedCount, groups: (runtimeAlerts.networkSignificantRequestFailedByPath ?? runtimeAlerts.networkRequestFailedByPath).slice(0, 12) });
  if ((runtimeAlerts?.summary?.domDiagnosticSampleCount ?? 0) > 0) findings.push({ id: "runtime-dom-diagnostics", severity: "amber", summary: "diagnostic/error/warning-like text was visible in sampled DOM", count: runtimeAlerts.summary.domDiagnosticSampleCount, groupCount: runtimeAlerts.summary.domDiagnosticGroupCount ?? 0, groups: runtimeAlerts.domDiagnosticsByText.slice(0, 12), samples: runtimeAlerts.domDiagnostics.slice(0, 12) });
  if ((runtimeAlerts?.summary?.executionErrorCount ?? 0) > 0) findings.push({ id: "runtime-execution-errors", severity: "red", summary: "Workbench rendered execution failure/error rows during observation", count: runtimeAlerts.summary.executionErrorCount, groups: runtimeAlerts.runtimeExecutionErrorsByCode.slice(0, 12) });
  if ((runtimeAlerts?.summary?.significantConsoleAlertCount ?? runtimeAlerts?.summary?.consoleAlertCount ?? 0) > 0) findings.push({ id: "runtime-console-alerts", severity: "amber", summary: "browser console warning/error entries were captured during observation", count: runtimeAlerts.summary.significantConsoleAlertCount ?? runtimeAlerts.summary.consoleAlertCount, groups: (runtimeAlerts.significantConsoleAlertsByPath ?? runtimeAlerts.consoleAlertsByPath).slice(0, 12) });
  const crossPageDiffs = mergeCrossPageDiffRows(
    detectCrossPageProjectionDiffs(samples),
    detectAdjacentCrossPageProjectionDiffs(samples)
  );
  const crossPageProjectionDiffs = crossPageDiffs.filter((item) => item.diffKind !== "trace-visibility");
  const crossPageTraceVisibilityDiffs = crossPageDiffs.filter((item) => item.diffKind === "trace-visibility");
  const crossPageProjectionBudgetMs = alertThresholds.crossPageProjectionDivergenceRedMs;
  const sampleBySeq = new Map(samples.map((item) => [Number(item?.seq), item]).filter(([seq]) => Number.isFinite(seq)));
  const appShellNotReadyRows = detectWorkbenchAppShellNotReady(samples);
  const persistentAppShellNotReadyRows = appShellNotReadyRows.filter((item) => Number(item.observedSpanMs ?? 0) > crossPageProjectionBudgetMs);
  const transientAppShellNotReadyRows = appShellNotReadyRows.filter((item) => Number(item.observedSpanMs ?? 0) <= crossPageProjectionBudgetMs);
  if (persistentAppShellNotReadyRows.length > 0) findings.push({
    id: "workbench-app-shell-not-ready",
    severity: "red",
    summary: "Workbench route document loaded but the app shell never mounted or hydrated within the configured budget; treat this as page/runtime startup evidence, not a Workbench projection divergence",
    count: persistentAppShellNotReadyRows.length,
    budgetMs: crossPageProjectionBudgetMs,
    samples: persistentAppShellNotReadyRows.slice(0, 20),
    rootCause: "workbench_page_app_shell_not_ready",
    rootCauseStatus: "confirmed-from-dom-and-asset-provenance",
    rootCauseConfidence: "high",
    valuesRedacted: true
  });
  if (transientAppShellNotReadyRows.length > 0) findings.push({ id: "workbench-app-shell-transient-not-ready", severity: "info", summary: "Workbench route briefly had a document and assets but no mounted app shell; retained as startup context", count: transientAppShellNotReadyRows.length, budgetMs: crossPageProjectionBudgetMs, samples: transientAppShellNotReadyRows.slice(0, 20) });
  const timedCrossPageProjectionDiffs = annotateCrossPageDiffTiming(crossPageProjectionDiffs);
  const controlledNavigationHydrationProjectionDiffs = timedCrossPageProjectionDiffs.filter((item) => controlledNavigationHydrationCrossPageDiff(item, controlledNavigationWindows, sampleBySeq));
  const appShellNotReadyProjectionDiffs = timedCrossPageProjectionDiffs.filter((item) => !controlledNavigationHydrationCrossPageDiff(item, controlledNavigationWindows, sampleBySeq) && crossPageDiffHasWorkbenchAppShellNotReady(item, sampleBySeq));
  const evaluatedCrossPageProjectionDiffs = timedCrossPageProjectionDiffs.filter((item) => !controlledNavigationHydrationCrossPageDiff(item, controlledNavigationWindows, sampleBySeq) && !crossPageDiffHasWorkbenchAppShellNotReady(item, sampleBySeq));
  const persistentCrossPageProjectionDiffs = evaluatedCrossPageProjectionDiffs.filter((item) => Number(item.observedSpanMs ?? 0) > crossPageProjectionBudgetMs);
  const transientCrossPageProjectionDiffs = evaluatedCrossPageProjectionDiffs.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),
    drilldown: buildCrossPageProjectionDrilldown(persistentCrossPageProjectionDiffs),
    sourceOfTruth: "session list/detail/messages/turn APIs must read from the same durable projection snapshot across pages",
    rootCause: "workbench_cross_page_projection_not_single_source",
    rootCauseStatus: "confirmed-from-control-observer-dom-samples",
    rootCauseConfidence: "high",
    nextAction: "Use drilldown.traceIds with diagnose-code-agent and compare session_list_read/session_messages_read/turn_status_read rows before changing renderer fallback behavior.",
    valuesRedacted: true
  });
  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 (controlledNavigationHydrationProjectionDiffs.length > 0) findings.push({ id: "cross-page-projection-controlled-navigation-hydration", severity: "info", summary: "control and observer pages differed while a non-blocking session-invariance navigation command still had an unhydrated blank page; retained as context but not treated as a red projection blocker", count: controlledNavigationHydrationProjectionDiffs.length, budgetMs: crossPageProjectionBudgetMs, samples: controlledNavigationHydrationProjectionDiffs.slice(0, 20) });
  if (appShellNotReadyProjectionDiffs.length > 0) findings.push({ id: "cross-page-projection-app-shell-not-ready", severity: "info", summary: "cross-page projection differences were explained by a page whose Workbench app shell was not mounted; see workbench-app-shell-not-ready for the blocking root cause", count: appShellNotReadyProjectionDiffs.length, budgetMs: crossPageProjectionBudgetMs, samples: appShellNotReadyProjectionDiffs.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-frame rendered duplicate visible assistant final rows; the fixed Final Response renderer summary block is excluded", count: traceMessageDuplicates.length, finalResponseSummaryBlockCounted: false, traceFrameSource: "traceRows-only", samples: traceMessageDuplicates.slice(0, 20) });
  const turnTraceMissing = detectTurnTraceIdMissing(samples);
  if (turnTraceMissing.length > 0) findings.push({ id: "turn-trace-id-missing", severity: "red", summary: "Code Agent turn/card was visible without a trace id, so historical trace hydration cannot be reliable", count: turnTraceMissing.length, samples: turnTraceMissing.slice(0, 20) });
  const pagePerformanceItems = Array.isArray(pagePerformance?.sameOriginApiByPath) ? pagePerformance.sameOriginApiByPath : [];
  const slowApi = pagePerformanceItems.filter((item) => item.isLongLivedStream !== true && Number(item.overBudgetCount ?? item.overFiveSecondCount ?? 0) > 0);
  if (slowApi.length > 0) findings.push({ id: "page-performance-slow-same-origin-api", severity: "red", summary: "same-origin API resource timing exceeded configured YAML usability budget", count: slowApi.length, budgetMs: alertThresholds.sameOriginApiSlowMs, groups: slowApi.slice(0, 20) });
  const longLivedStreams = pagePerformanceItems.filter((item) => item.isLongLivedStream);
  const slowStreamOpen = longLivedStreams.filter((item) => Number(item.streamOpenOverBudgetCount ?? item.streamOpenOverFiveSecondCount ?? 0) > 0);
  if (slowStreamOpen.length > 0) findings.push({ id: "page-performance-slow-long-lived-stream-open", severity: "red", summary: "long-lived stream open latency exceeded configured YAML usability budget; stream lifetime is still reported separately", count: slowStreamOpen.length, budgetMs: alertThresholds.longLivedStreamOpenSlowMs, groups: slowStreamOpen.slice(0, 20) });
  if (longLivedStreams.length > 0) findings.push({ id: "page-performance-long-lived-streams", severity: "info", summary: "same-origin long-lived streams are reported separately; lifetime is not treated as API load latency", count: longLivedStreams.length, groups: longLivedStreams.slice(0, 20) });
  const requestRatePeaks = Array.isArray(requestRate?.peaks) ? requestRate.peaks : [];
  const totalRequestRatePeaks = requestRatePeaks.filter((item) => item.scope === "total" && item.overThreshold === true);
  const pageRequestRatePeaks = requestRatePeaks.filter((item) => item.scope === "page" && item.overThreshold === true);
  const apiPathRequestRatePeaks = requestRatePeaks.filter((item) => item.scope === "apiPath" && item.overThreshold === true);
  if (totalRequestRatePeaks.length > 0) findings.push({
    id: "request-rate-total-peak",
    severity: "red",
    summary: "same-origin API request rate exceeded the YAML total peak threshold; this is request storm evidence from browser network events",
    count: totalRequestRatePeaks.length,
    thresholdPerMinute: alertThresholds.requestRateTotalRedPerMinute,
    bucketMs: requestRate?.summary?.bucketMs ?? alertThresholds.requestRateBucketMs,
    peaks: totalRequestRatePeaks.slice(0, 20),
    valuesRedacted: true
  });
  if (pageRequestRatePeaks.length > 0) findings.push({
    id: "request-rate-page-peak",
    severity: "red",
    summary: "a page-level same-origin API request curve exceeded the YAML peak threshold; inspect the page and top API paths before changing probe sampling",
    count: pageRequestRatePeaks.length,
    thresholdPerMinute: alertThresholds.requestRatePageRedPerMinute,
    bucketMs: requestRate?.summary?.bucketMs ?? alertThresholds.requestRateBucketMs,
    peaks: pageRequestRatePeaks.slice(0, 20),
    valuesRedacted: true
  });
  if (apiPathRequestRatePeaks.length > 0) findings.push({
    id: "request-rate-api-path-peak",
    severity: "red",
    summary: "an API-path request curve exceeded the YAML peak threshold; this pinpoints the route most likely involved in a request storm",
    count: apiPathRequestRatePeaks.length,
    thresholdPerMinute: alertThresholds.requestRateApiPathRedPerMinute,
    bucketMs: requestRate?.summary?.bucketMs ?? alertThresholds.requestRateBucketMs,
    peaks: apiPathRequestRatePeaks.slice(0, 20),
    valuesRedacted: true
  });
  if ((pageProvenance?.summary?.segmentCount ?? 0) > 1) findings.push({ id: "page-provenance-segments", severity: "info", summary: "observer crossed page asset provenance segments; interpret runtime findings by segment", segmentCount: pageProvenance.summary.segmentCount, segments: pageProvenance.segments.slice(0, 20) });
  const naturalApi = network.filter((item) => item.observerInitiated === false && item.type === "response" && /\/v1\/|\/auth\//u.test(String(item.url || "")));
  const apiDomLagSummary = effectiveApiDomLag?.summary || {};
  findings.push({ id: "natural-api-dom-lag-baseline", severity: "info", summary: "natural API responses and DOM samples are available for API-to-DOM lag correlation", naturalApiResponses: naturalApi.length, sampleCount: samples.length, apiDomLag: apiDomLagSummary });
  findings.push({
    id: "natural-api-dom-lag-candidates",
    severity: Number(apiDomLagSummary.overBudgetCount ?? 0) > 0 ? "amber" : "info",
    summary: "state-relevant natural API responses were correlated to the first subsequent DOM digest change; over-budget lag is a non-blocking investigation alert",
    count: apiDomLagSummary.candidateCount ?? 0,
    domChangedCount: apiDomLagSummary.domChangedCount ?? 0,
    noDomChangeWithinWindowCount: apiDomLagSummary.noDomChangeWithinWindowCount ?? 0,
    overBudgetCount: apiDomLagSummary.overBudgetCount ?? 0,
    budgetMs: apiDomLagSummary.budgetMs ?? null,
    p95DomChangeDeltaMs: apiDomLagSummary.p95DomChangeDeltaMs ?? null,
    maxDomChangeDeltaMs: apiDomLagSummary.maxDomChangeDeltaMs ?? null,
    groups: Array.isArray(effectiveApiDomLag?.groups) ? effectiveApiDomLag.groups.slice(0, 12) : [],
  });
  if (errors.length > 0) findings.push({ id: "browser-console-or-page-errors", severity: "amber", summary: "pageerror/runner errors were captured", count: errors.length, first: errors.slice(0, 5) });
  if (samples.length === 0) {
    if (commandFailures.length > 0) {
      findings.push({
        id: "no-samples-after-observer-command-failed",
        severity: "red",
        summary: "observer produced zero samples after a blocking control command failed; the command failure is the deterministic precondition.",
        count: 1,
        firstCommandFailure,
        rootCause: "observer-command-failed-before-sampling",
        rootCauseStatus: "confirmed",
        rootCauseConfidence: "high",
        evidenceSummary: firstCommandFailure ? "command=" + (firstCommandFailure.commandId || "-") + " type=" + (firstCommandFailure.type || "-") + " phase=" + (firstCommandFailure.phase || "-") + " status=" + (firstCommandFailure.status || "-") + " exit=" + (firstCommandFailure.exitCode ?? "-") : "commandFailures>0",
        valuesRedacted: true
      });
    } else {
      findings.push({
        id: "no-samples-artifact-evidence-missing",
        severity: "red",
        summary: "observer produced zero samples and analyzer has no failed command precondition; sampling/source evidence is missing.",
        count: 1,
        rootCause: "sample-artifact-evidence-missing",
        rootCauseStatus: "evidence-gap",
        rootCauseConfidence: "medium",
        evidenceSummary: "samples=0 control=" + (Array.isArray(control) ? control.length : 0) + " errors=" + (Array.isArray(errors) ? errors.length : 0),
        valuesRedacted: true
      });
    }
  }
  return findings;
}

function compactObserverCommandFailure(item) {
  const result = item && typeof item.result === "object" ? item.result : {};
  const output = item && typeof item.output === "object" ? item.output : {};
  const error = item && typeof item.error === "object" ? item.error : result && typeof result.error === "object" ? result.error : {};
  const stdout = item?.stdoutPreview ?? item?.stdoutTail ?? result.stdoutPreview ?? result.stdoutTail ?? output.stdoutPreview ?? output.stdoutTail ?? null;
  const stderr = item?.stderrPreview ?? item?.stderrTail ?? result.stderrPreview ?? result.stderrTail ?? output.stderrPreview ?? output.stderrTail ?? null;
  const commandId = item?.commandId ?? item?.id ?? item?.command_id ?? null;
  const phase = item?.phase ?? item?.statusPhase ?? (item?.failedAt ? "failed" : item?.abandonedAt ? "abandoned" : item?.completedAt ? "completed" : null);
  const resultOk = item?.resultOk ?? item?.ok ?? result.ok ?? null;
  const status = item?.status ?? item?.resultStatus ?? result.status ?? (phase === "failed" || resultOk === false ? "failed" : phase === "abandoned" ? "abandoned" : phase === "completed" ? "completed" : null);
  const failureKind = item?.failureKind ?? result.failureKind ?? error.failureKind ?? null;
  const message = item?.message ?? result.message ?? error.message ?? item?.reason ?? result.reason ?? null;
  const failedReason = item?.failedReason ?? item?.reason ?? result.failedReason ?? result.reason ?? failureKind ?? message ?? null;
  const artifactBucket = item?.artifactBucket ?? (phase === "failed" ? "failed" : phase === "abandoned" ? "abandoned" : phase === "completed" ? "done" : null);
  const artifactRef = item?.artifactRef ?? item?.artifactPath ?? item?.path ?? (commandId && artifactBucket ? "commands/" + artifactBucket + "/" + commandId + ".json" : null);
  return {
    commandId,
    type: item?.type ?? item?.commandType ?? item?.command_type ?? null,
    phase,
    status,
    resultOk: resultOk === true ? true : resultOk === false ? false : null,
    failureKind: failureKind == null ? null : String(failureKind).slice(0, 160),
    failedReason: failedReason == null ? null : String(failedReason).slice(0, 240),
    message: message == null ? null : String(message).slice(0, 240),
    exitCode: item?.exitCode ?? result.exitCode ?? null,
    timedOut: item?.timedOut === true || result.timedOut === true,
    stdoutPreview: stdout == null ? null : String(stdout).slice(0, 240),
    stderrPreview: stderr == null ? null : String(stderr).slice(0, 240),
    artifactBucket,
    artifactRef,
    failedAt: item?.failedAt ?? null,
    completedAt: item?.completedAt ?? null,
    abandonedAt: item?.abandonedAt ?? null,
    valuesRedacted: true
  };
}

function buildCrossPageProjectionDrilldown(rows) {
  const sourceRows = Array.isArray(rows) ? rows.filter(Boolean) : [];
  const traceIds = uniqueSorted(sourceRows.flatMap((row) => collectIdsFromUnknown(row, "trace")).filter(Boolean)).slice(0, 12);
  const sessionIds = uniqueSorted(sourceRows.flatMap((row) => collectIdsFromUnknown(row, "session")).filter(Boolean)).slice(0, 12);
  const diffKinds = uniqueSorted(sourceRows.map((row) => row?.diffKind).filter(Boolean));
  const groupsByKey = new Map();
  for (const row of sourceRows) {
    const rowTraceIds = collectIdsFromUnknown(row, "trace").slice(0, 8);
    const rowSessionIds = collectIdsFromUnknown(row, "session").slice(0, 8);
    const key = [
      row?.diffKind || "projection",
      rowSessionIds[0] || row?.sessionIdPrefix || "-",
      rowTraceIds[0] || "-",
    ].join("|");
    let group = groupsByKey.get(key);
    if (!group) {
      group = {
        keyHash: sha256(key),
        diffKind: row?.diffKind ?? null,
        traceIds: new Set(),
        sessionIds: new Set(),
        count: 0,
        firstSeq: row?.firstSeq ?? row?.controlSeq ?? row?.observerSeq ?? row?.seq ?? null,
        lastSeq: row?.lastSeq ?? row?.controlSeq ?? row?.observerSeq ?? row?.seq ?? null,
        firstAt: row?.firstAt ?? row?.controlTs ?? row?.observerTs ?? row?.ts ?? null,
        lastAt: row?.lastAt ?? row?.controlTs ?? row?.observerTs ?? row?.ts ?? null,
        maxObservedSpanMs: 0,
        examples: [],
      };
      groupsByKey.set(key, group);
    }
    group.count += 1;
    for (const traceId of rowTraceIds) group.traceIds.add(traceId);
    for (const sessionId of rowSessionIds) group.sessionIds.add(sessionId);
    group.firstSeq = minNumberOrValue(group.firstSeq, row?.firstSeq ?? row?.controlSeq ?? row?.observerSeq ?? row?.seq);
    group.lastSeq = maxNumberOrValue(group.lastSeq, row?.lastSeq ?? row?.controlSeq ?? row?.observerSeq ?? row?.seq);
    group.firstAt = minIso(group.firstAt, row?.firstAt ?? row?.controlTs ?? row?.observerTs ?? row?.ts ?? null);
    group.lastAt = maxIso(group.lastAt, row?.lastAt ?? row?.controlTs ?? row?.observerTs ?? row?.ts ?? null);
    group.maxObservedSpanMs = Math.max(group.maxObservedSpanMs, Number(row?.observedSpanMs ?? 0) || 0);
    if (group.examples.length < 3) {
      group.examples.push({
        diffKind: row?.diffKind ?? null,
        firstSeq: row?.firstSeq ?? null,
        lastSeq: row?.lastSeq ?? null,
        observedSpanMs: row?.observedSpanMs ?? null,
        controlMessageCount: row?.controlMessageCount ?? null,
        observerMessageCount: row?.observerMessageCount ?? null,
        traceIds: rowTraceIds.slice(0, 6),
        sessionIds: rowSessionIds.slice(0, 4),
        valuesRedacted: true,
      });
    }
  }
  const groups = Array.from(groupsByKey.values()).map((group) => ({
    keyHash: group.keyHash,
    diffKind: group.diffKind,
    traceIds: Array.from(group.traceIds).slice(0, 8),
    sessionIds: Array.from(group.sessionIds).slice(0, 6),
    count: group.count,
    firstSeq: group.firstSeq,
    lastSeq: group.lastSeq,
    firstAt: group.firstAt,
    lastAt: group.lastAt,
    observedSpanMs: Math.max(group.maxObservedSpanMs, isoSpanMs(group.firstAt, group.lastAt)),
    examples: group.examples,
    valuesRedacted: true,
  })).sort((left, right) => Number(right.observedSpanMs ?? 0) - Number(left.observedSpanMs ?? 0) || Number(right.count ?? 0) - Number(left.count ?? 0));
  return {
    summary: {
      rowCount: sourceRows.length,
      groupCount: groups.length,
      diffKinds,
      traceIds,
      sessionIds,
      maxObservedSpanMs: groups.reduce((value, item) => Math.max(value, Number(item.observedSpanMs ?? 0)), 0),
      valuesRedacted: true,
    },
    traceIds,
    sessionIds,
    groups: groups.slice(0, 12),
    otelDrilldown: buildWorkbenchTriadOtelDrilldown(traceIds.slice(0, 4)),
    staticSourceHints: workbenchTriadStaticSourceHints(),
    unitTestReproHints: [
      "two independent Workbench pages must converge to identical session list/detail/messages/turn projection after the same durable events",
      "late session-list or message refresh must not drop a trace that another page already read from durable projection",
      "read-side APIs must expose enough OTel fields to compare projection version/cursor and trace ids across pages",
    ],
    valuesRedacted: true,
  };
}

function collectIdsFromUnknown(value, kind, output = new Set(), depth = 0) {
  if (depth > 4 || value === null || value === undefined) return Array.from(output);
  if (typeof value === "string") {
    const pattern = kind === "session" ? /\bses_[A-Za-z0-9_-]+\b/gu : /\btrc_[A-Za-z0-9_-]+\b/gu;
    for (const match of value.match(pattern) || []) output.add(match);
    return Array.from(output);
  }
  if (Array.isArray(value)) {
    for (const item of value.slice(0, 40)) collectIdsFromUnknown(item, kind, output, depth + 1);
    return Array.from(output);
  }
  if (typeof value === "object") {
    for (const item of Object.values(value).slice(0, 80)) collectIdsFromUnknown(item, kind, output, depth + 1);
  }
  return Array.from(output);
}

function buildFrontendFreezeFindings(errors, control) {
  const findings = [];
  const promptTimes = (control || [])
    .filter((item) => item.type === "sendPrompt" && item.phase === "completed")
    .map((item) => Date.parse(item.ts))
    .filter(Number.isFinite)
    .sort((a, b) => a - b);
  const stopWindows = stopCommandWindows(control);
  const events = (errors || [])
    .map((item) => frontendFreezeErrorEvent(item, promptTimes))
    .filter((item) => item && !errorInsideStopWindow(item, stopWindows));
  const domEvents = events.filter((item) => item.kind === "dom-evaluate-timeout");
  const controlDomBurst = firstBurst(
    domEvents.filter((item) => item.pageRole === "control" || item.pageRole === null),
    alertThresholds.domEvaluateTimeoutRedCount,
    alertThresholds.domEvaluateTimeoutRedWindowMs,
  );
  if (controlDomBurst) findings.push(frontendFreezeBurstFinding({
    id: "frontend-control-dom-evaluate-timeout-red",
    summary: "control page DOM evaluation timed out repeatedly; treat the browser page as frozen and keep the sentinel red instead of refreshing or falling back",
    burst: controlDomBurst,
    thresholdCount: alertThresholds.domEvaluateTimeoutRedCount,
    windowMs: alertThresholds.domEvaluateTimeoutRedWindowMs,
    pageRole: "control",
  }));
  const observerDomBurst = firstBurst(
    domEvents.filter((item) => item.pageRole === "observer"),
    alertThresholds.domEvaluateTimeoutRedCount,
    alertThresholds.domEvaluateTimeoutRedWindowMs,
  );
  if (observerDomBurst) findings.push(frontendFreezeBurstFinding({
    id: "frontend-observer-dom-evaluate-timeout-red",
    summary: "observer page DOM evaluation timed out repeatedly; the observer page is frozen and later periodic refresh evidence must not clear this run",
    burst: observerDomBurst,
    thresholdCount: alertThresholds.domEvaluateTimeoutRedCount,
    windowMs: alertThresholds.domEvaluateTimeoutRedWindowMs,
    pageRole: "observer",
  }));
  const screenshotBurst = firstBurst(
    events.filter((item) => item.kind === "screenshot-timeout"),
    alertThresholds.screenshotTimeoutRedCount,
    alertThresholds.domEvaluateTimeoutRedWindowMs,
  );
  if (screenshotBurst) findings.push(frontendFreezeBurstFinding({
    id: "frontend-screenshot-timeout-red",
    summary: "browser screenshot capture timed out repeatedly; this is freeze evidence and the sentinel must stay red until investigated",
    burst: screenshotBurst,
    thresholdCount: alertThresholds.screenshotTimeoutRedCount,
    windowMs: alertThresholds.domEvaluateTimeoutRedWindowMs,
    pageRole: null,
  }));
  const pageErrors = events.filter((item) => item.kind === "page-error");
  const pageErrorBurst = firstBurst(pageErrors, alertThresholds.pageErrorRedCount, alertThresholds.domEvaluateTimeoutRedWindowMs);
  if (pageErrorBurst) findings.push(frontendFreezeBurstFinding({
    id: "frontend-page-error-red",
    summary: "browser pageerror entries exceeded the YAML threshold; page runtime exceptions are blocking when repeated in the observation window",
    burst: pageErrorBurst,
    thresholdCount: alertThresholds.pageErrorRedCount,
    windowMs: alertThresholds.domEvaluateTimeoutRedWindowMs,
    pageRole: null,
  }));
  return findings;
}
`;
}
