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 (
+
+ );
+ })()}
+
{/* 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;