diff --git a/apps/control-station/src/components/RerunViewport.tsx b/apps/control-station/src/components/RerunViewport.tsx index a53cf9f..a1e5cb7 100644 --- a/apps/control-station/src/components/RerunViewport.tsx +++ b/apps/control-station/src/components/RerunViewport.tsx @@ -551,6 +551,12 @@ export function rerunViewerInitialSource( return resolvedSourceUrl; } +export function rerunViewerOpenOptions( + followLive: boolean, +): { follow_if_http: true } | null { + return followLive ? { follow_if_http: true } : null; +} + export function resolveRecordedBlueprintUrl(sourceUrl: string, origin: string): string | null { const normalized = sourceUrl.trim(); if (!RECORDED_RRD_PATH.test(normalized)) return null; @@ -1631,7 +1637,7 @@ export function RerunViewport({ rerunViewerInitialSource(resolvedSource), host, viewerOptions, - null, + rerunViewerOpenOptions(followLive), ); if (disposed) { disposeViewer(); diff --git a/apps/control-station/test/rerunViewportAtomicAdmission.test.mjs b/apps/control-station/test/rerunViewportAtomicAdmission.test.mjs index bb7e5e1..2aebb05 100644 --- a/apps/control-station/test/rerunViewportAtomicAdmission.test.mjs +++ b/apps/control-station/test/rerunViewportAtomicAdmission.test.mjs @@ -10,6 +10,7 @@ let createRecordedOpenWatchdog; let createReentrantViewerDisposer; let recordedOpenWatchdogTimeoutMs; let rerunViewerInitialSource; +let rerunViewerOpenOptions; let resolveRecordedViewerSourceUrl; before(async () => { @@ -24,6 +25,7 @@ before(async () => { createReentrantViewerDisposer, recordedOpenWatchdogTimeoutMs, rerunViewerInitialSource, + rerunViewerOpenOptions, resolveRecordedViewerSourceUrl, } = await server.ssrLoadModule("/src/components/RerunViewport.tsx")); }); @@ -63,6 +65,11 @@ test("only the canonical digest-bound generation URL reaches the native Rerun re } }); +test("only the live receiver opens on the native following edge", () => { + assert.deepEqual(rerunViewerOpenOptions(true), { follow_if_http: true }); + assert.equal(rerunViewerOpenOptions(false), null); +}); + test("recorded admission watchdog is size-aware and exits an incomplete load", () => { const smallDelay = recordedOpenWatchdogTimeoutMs(4); const currentDelay = recordedOpenWatchdogTimeoutMs(246_331_680); @@ -170,6 +177,7 @@ test("recorded RRD bytes are never split across LogChannel.send_rrd calls", asyn assert.doesNotMatch(source, /missioncore\/recorded-recording/); assert.doesNotMatch(source, /recordedChannel/); assert.match(source, /viewer\.start\(\s*rerunViewerInitialSource\(resolvedSource\)/s); + assert.match(source, /rerunViewerOpenOptions\(followLive\)/); assert.match( source, /recordingOpened = true;[\s\S]*diagnosticLifecycle\.markAdmitted\(\);/,