From 3ca2f3b499c2fa22ae011e5fce632bd1a1d3880d Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Fri, 21 Aug 2026 00:02:26 +0200 Subject: [PATCH] refactor(web): collapse time provenance behind an inline toggle The labeled provenance rows duplicated values already visible in the raw JSON dump and inflated the metadata block for every IME event. The section is now collapsed by default behind a small "time provenance" toggle sitting inline on the Created row (whose value it explains) - zero extra height when collapsed, and the base label column returns to its original width, so the default detail view is pixel-identical to before P13. Expanding reveals the same rows, indented under Created. Co-Authored-By: Claude Fable 5 --- .../app/sessions/components/EventTimeline.tsx | 45 ++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/src/Web/autopilot-monitor-web/app/sessions/components/EventTimeline.tsx b/src/Web/autopilot-monitor-web/app/sessions/components/EventTimeline.tsx index 1b7a7de7..31272ef4 100644 --- a/src/Web/autopilot-monitor-web/app/sessions/components/EventTimeline.tsx +++ b/src/Web/autopilot-monitor-web/app/sessions/components/EventTimeline.tsx @@ -455,6 +455,10 @@ function EventRow({ event, showScriptOutput, prevEvent }: { event: EnrollmentEve const [showRaw, setShowRaw] = useState(false); const [copied, setCopied] = useState(false); const [copiedDetail, setCopiedDetail] = useState(false); + // Collapsed by default: the same values sit in the raw JSON dump — this labeled view is + // an opt-in dive, it must not inflate the metadata block (user decision 2026-08-20). + const [showProvenance, setShowProvenance] = useState(false); + const timeProvenance = useMemo(() => readTimeProvenance(event.data), [event.data]); const rawDetailData = useMemo(() => normalizeEventDataForDisplay(event.data), [event.data]); // Filter stdout from script events when showScriptOutput is false. @@ -723,12 +727,12 @@ function EventRow({ event, showScriptOutput, prevEvent }: { event: EnrollmentEve )}
- EventId + EventId {event.eventId}
{recordedAt && (
- Recorded + Recorded {recordedAt.toISOString().replace('T', ' ').replace('Z', '')} (event log, pre-agent) @@ -736,11 +740,26 @@ function EventRow({ event, showScriptOutput, prevEvent }: { event: EnrollmentEve
)}
- Created - {event.timestamp} + Created + + {event.timestamp} + {(timeProvenance || event.timestampClamped) && ( + + )} +
+ {showProvenance && (timeProvenance || event.timestampClamped) && ( + + )}
- Received + Received {event.receivedAt ? new Date(event.receivedAt).toISOString().replace('T', ' ').replace('Z', '') @@ -758,11 +777,10 @@ function EventRow({ event, showScriptOutput, prevEvent }: { event: EnrollmentEve
{hasPhase && (
- Phase + Phase {event.phaseName}
)} - ); })()} @@ -897,18 +915,15 @@ const ORIGIN_CHIP: Record = { }; // The raw CMTrace time-resolution values (P13): how this event's UTC timestamp was -// produced. Rendered inside the expanded metadata block only — per-row badges are -// reserved for the rare jump/clamp cases, everything else lives here on demand. -function TimeProvenanceRows({ event }: { event: EnrollmentEvent }) { - const provenance = readTimeProvenance(event.data); - if (!provenance && !event.timestampClamped) return null; - +// produced. Collapsed behind the "time provenance" toggle on the Created row — the same +// values sit in the raw JSON dump, so this labeled view is an opt-in dive that must not +// inflate the default metadata block. Per-row badges stay reserved for jump/clamp cases. +function TimeProvenanceRows({ event, provenance }: { event: EnrollmentEvent; provenance: ReturnType }) { const origin = provenance?.sourceOffsetOrigin; const originChip = origin ? ORIGIN_CHIP[origin] ?? { className: "bg-gray-100 text-gray-500", title: origin } : null; return ( -
-
Time provenance
+
{provenance?.sourceLocalTs && (
Local time