From 5262583e8bbe43a5fb2d58de1c09e2c891e308ae Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Mon, 1 Jun 2026 02:06:33 -0700 Subject: [PATCH] feat(tracker-web): collapse heartbeat noise + surface PR on job detail The job detail timeline was buried under hundreds of lease_renewed rows on long-running jobs. Collapse consecutive high-frequency events (lease_renewed) into one "type xN - over Nm" summary row; everything else renders verbatim. Add a prominent Pull Request banner (link + state) sourced from whichever run opened the PR, instead of only the per-attempt Runs column. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../app/dashboard/fleet/jobs/[id]/page.tsx | 122 ++++++++++++++++-- 1 file changed, 110 insertions(+), 12 deletions(-) diff --git a/dashboards/tracker-web/src/app/dashboard/fleet/jobs/[id]/page.tsx b/dashboards/tracker-web/src/app/dashboard/fleet/jobs/[id]/page.tsx index 48c2d6e5..5ca3a04c 100644 --- a/dashboards/tracker-web/src/app/dashboard/fleet/jobs/[id]/page.tsx +++ b/dashboards/tracker-web/src/app/dashboard/fleet/jobs/[id]/page.tsx @@ -260,6 +260,39 @@ export default function FleetJobDetailPage() { {/* Prompt (the job body) + PR/target config */} + {/* Pull request (surfaced from whichever run opened it) */} + {(() => { + const prRun = runs.find(r => r.prUrl); + if (!prRun?.prUrl) return null; + return ( +
+ Pull Request + + {prRun.prUrl} ↗ + + {prRun.prState && ( + + {prRun.prState} + + )} +
+ ); + })()} + {/* Review gate (multi-reviewer human gate) */} {job.stage === 'review' && ( No events recorded.

) : (
    - {events.map(e => ( -
  • - - {new Date(e.at).toLocaleTimeString()} - - {e.type} - {e.actor && by {e.actor}} -
  • - ))} + {groupTimelineEvents(events).map(g => + g.kind === 'single' ? ( +
  • + + {new Date(g.event.at).toLocaleTimeString()} + + {g.event.type} + {g.event.actor && ( + by {g.event.actor} + )} +
  • + ) : ( +
  • + + {new Date(g.first).toLocaleTimeString()} + + + {g.type} ×{g.count} + · over {fmtDuration(g.last - g.first)} + +
  • + ) + )}
)} @@ -665,6 +716,53 @@ function Stat({ label, value }: { label: string; value: string }) { ); } +type TimelineGroup = + | { kind: 'single'; event: FleetEvent } + | { kind: 'collapsed'; key: string; type: string; count: number; first: number; last: number }; + +/** High-frequency event types collapsed into one summary row so a long-running + * job's timeline isn't buried under hundreds of heartbeats. */ +const COLLAPSIBLE_EVENT_TYPES = new Set(['lease_renewed']); + +/** Fold consecutive runs of a collapsible event type (e.g. lease_renewed) into a + * single "type ×N · over Xm" row; everything else renders verbatim, in order. */ +function groupTimelineEvents(events: FleetEvent[]): TimelineGroup[] { + const out: TimelineGroup[] = []; + let run: FleetEvent[] = []; + const flush = () => { + if (run.length === 0) return; + if (run.length === 1) { + out.push({ kind: 'single', event: run[0]! }); + } else { + const first = run[0]!; + const last = run[run.length - 1]!; + out.push({ + kind: 'collapsed', + key: `grp-${first.id}-${last.id}`, + type: first.type, + count: run.length, + first: Date.parse(first.at), + last: Date.parse(last.at), + }); + } + run = []; + }; + for (const e of events) { + if (COLLAPSIBLE_EVENT_TYPES.has(e.type)) { + if (run.length > 0 && run[0]!.type === e.type) run.push(e); + else { + flush(); + run = [e]; + } + } else { + flush(); + out.push({ kind: 'single', event: e }); + } + } + flush(); + return out; +} + /** Sum cost / tokens / wall-time across a job's runs. */ function runTotals(runs: FleetRun[]) { let costUsd = 0;