chore(k1): checkpoint connection recovery work

This commit is contained in:
DCCONSTRUCTIONS
2026-08-21 08:12:22 +03:00
parent a3138f3d71
commit c7843a3c7e
22 changed files with 969 additions and 293 deletions
@@ -292,6 +292,21 @@ export function isLiveRerunPresentationReady(
isUsableRecordedPlaybackRange(rangeNs);
}
/**
* `recording_open` can arrive before Rerun has registered the live timeline.
* Selecting it at that point is a silent no-op, so keep retrying only until
* the exact live timeline is both available and active.
*/
export function liveTimelineNeedsSynchronization(
followLive: boolean,
activeTimeline: string | null | undefined,
rangeNs: { min: number; max: number } | null,
): boolean {
return followLive &&
isUsableRecordedPlaybackRange(rangeNs) &&
activeTimeline !== "stream_time";
}
/**
* Key the native receiver to its data-plane binding. Recovery authority is a
* retry fence projected from changing supervisor snapshots; it must not tear
@@ -1435,6 +1450,7 @@ export function RerunViewport({
let rangeNs = viewer.get_time_range(event.recording_id, timeline);
let currentNs = viewer.get_current_time(event.recording_id, timeline);
let playing = viewer.get_playing(event.recording_id);
let liveTimelineSynchronized = !followLive;
if (!followLive && playing) {
try {
viewer.set_playing(event.recording_id, false);
@@ -1496,6 +1512,17 @@ export function RerunViewport({
if (disposed || !playbackState) return;
try {
rangeNs = viewer.get_time_range(event.recording_id, timeline);
if (followLive && !liveTimelineSynchronized) {
let activeTimeline = viewer.get_active_timeline(event.recording_id);
if (liveTimelineNeedsSynchronization(followLive, activeTimeline, rangeNs)) {
// The first selection above may have raced timeline
// creation. Once a real range exists this retry is safe
// and preserves Rerun's native live-following cursor.
viewer.set_active_timeline(event.recording_id, timeline);
activeTimeline = viewer.get_active_timeline(event.recording_id);
}
liveTimelineSynchronized = activeTimeline === timeline;
}
currentNs = viewer.get_current_time(event.recording_id, timeline);
playing = viewer.get_playing(event.recording_id);
} catch {
@@ -1511,7 +1538,7 @@ export function RerunViewport({
setRecordingBufferProgress(recordedBuffer.bufferProgress);
}
const readyToRender = followLive
? isLiveRerunPresentationReady(
? liveTimelineSynchronized && isLiveRerunPresentationReady(
viewerStartResolved,
rangeNs,
liveActivitySequenceRef.current,
@@ -157,6 +157,7 @@ function SpatialWorkspace({
const [showSegmentation, setShowSegmentation] = useState(false);
const [showCuboids3d, setShowCuboids3d] = useState(false);
const recordedSource = Boolean(recordedReplay) || /\.rrd(?:$|[?#])/i.test(sourceUrl);
const liveRerunSource = !recordedSource && /^rerun\+https?:\/\//i.test(sourceUrl.trim());
const recordedSessionGate: RecordedAdmissionPhase = recordedSource
? recordedSessionAdmission?.phase ?? "loading"
: "ready";
@@ -165,6 +166,10 @@ function SpatialWorkspace({
isRecordedPlaybackPresentationReady(viewerStatus, playbackState));
const streamActive = state?.sourceMode === "live" || state?.sourceMode === "replay";
const metrics = streamActive ? state?.metrics : undefined;
// An explicit manual gRPC source has no Mission Core metrics producer. Its
// native Rerun range is therefore the only available activity proof.
const livePresentationActivitySequence = metrics?.publishedFrameCount ??
(liveRerunSource && !streamActive ? 1 : null);
const latency = pipelineLatency(metrics);
const frameRate = finiteMetric(metrics?.frameRateHz);
const points = finiteMetric(metrics?.pointCount);
@@ -495,8 +500,8 @@ function SpatialWorkspace({
<RerunViewport
sourceUrl={sourceUrl}
recordedArtifact={recordedSource ? recordedReplay : null}
followLive={!recordedReplay && streamActive}
liveActivitySequence={metrics?.publishedFrameCount}
followLive={liveRerunSource}
liveActivitySequence={livePresentationActivitySequence}
liveStreamId={state?.spatialSource?.id}
liveRecoveryAuthorityIdentity={!recordedSource && streamActive ? liveRerunRecoveryAuthorityIdentity(pointCloudSource, state?.spatialSource) : null}
autoplayWhenReady={recordedSource}
@@ -590,7 +590,14 @@ test("canonical K1 preparation stops before START and guards every async stage",
canonicalPreparation.match(
/expected_snapshot_runtime_id: actionSnapshotRuntimeId/g,
)?.length,
3,
4,
);
assert.match(canonicalPreparation, /xgridsK1Api\.openApplicationControlSession\(\{/);
assert.match(canonicalPreparation, /\.\.\.request\.physicalAcceptance/);
assert.ok(
canonicalPreparation.indexOf("xgridsK1Api.openApplicationControlSession")
< canonicalPreparation.indexOf("xgridsK1Api.enterApplicationWorkspace"),
"Verify inspection must be replaced before workspace entry",
);
assert.match(canonicalPreparation, /xgridsK1Api\.reconcilePhysicalCommand\(\{/);
assert.doesNotMatch(canonicalPreparation, /await xgridsK1Api\./);
@@ -308,7 +308,7 @@ test("connected presentation uses canonical process copy", () => {
assert.match(connection, /<h2>Подключение \{model\.displayName\}<\/h2>/);
assert.match(
connection,
/const operationalPanelsVisible = shouldRenderK1OperationalPanels\(state\)/,
/const operationalPanelsVisible = shouldRenderK1OperationalPanels\(\s*state,\s*controller\.pendingAction,\s*\)/,
);
assert.match(
connection,
@@ -395,7 +395,7 @@ test("K1 START renders an in-button spinner for the complete live orchestration"
assert.doesNotMatch(acquisition, /readOnlyConnectionObservationTarget\(state\)/);
assert.match(acquisition, /appliedTopology\?\.status === "active"\s*&& desiredModeMatchesActive/);
assert.match(acquisition, /if \(!draftPreparationTarget\) return;/);
assert.match(acquisition, /START не используется для установки связи/);
assert.doesNotMatch(acquisition, /START не используется для установки связи/);
assert.match(acquisition, /Синхронизация…/);
});
@@ -502,7 +502,7 @@ test("K1 mode reset is explicit while Scan and Apply keep exact backend CAS", ()
assert.match(acquisition, /state\?\.active_connection_mode/);
assert.match(acquisition, /desiredSelectionCommitted/);
assert.match(acquisition, /configuredConnectionMode !== desiredConnectionMode/);
assert.match(acquisition, /Выбран другой способ связи/);
assert.doesNotMatch(acquisition, /Выбран другой способ связи/);
});
test("top-right device utility is an explicit pending-aware K1 scenario reset", async () => {
@@ -990,7 +990,7 @@ test("every K1 connection and acquisition action is fenced to the accepted backe
[...runtime.matchAll(
/expected_snapshot_runtime_id: actionSnapshotRuntimeId/g,
)].length,
3,
4,
);
assert.match(
runtime,
@@ -1064,7 +1064,7 @@ test("K1 orchestration accepts backend recovery but still requires exact topolog
);
assert.match(acquisition, /desiredModeMatchesActive/);
assert.match(acquisition, /modeSwitchRequired/);
assert.match(acquisition, /Выбран другой способ связи/);
assert.doesNotMatch(acquisition, /Выбран другой способ связи/);
assert.match(acquisition, /prepareCanonicalAcquisition/);
assert.match(acquisition, /startPreparedAcquisition/);
assert.match(acquisition, /operatorActionPhysicalAcceptance\(\)/);
@@ -65,6 +65,7 @@ let shellPresentation;
let reconfigurationAllowsFreshDevice;
let readOnlyObservationShowsNetworkUnavailable;
let readOnlyFailureShowsNetworkUnavailable;
let savedBridgeRequiresNetworkSetup;
let provisioningFailureRequiresFreshCandidate;
let trustedConnectionBinding;
let transportRefEquivalenceKey;
@@ -183,6 +184,7 @@ before(async () => {
reconfigurationAllowsFreshDevice,
readOnlyObservationShowsNetworkUnavailable,
readOnlyFailureShowsNetworkUnavailable,
savedBridgeRequiresNetworkSetup,
provisioningFailureRequiresFreshCandidate,
trustedConnectionBinding,
transportRefEquivalenceKey,
@@ -1057,12 +1059,15 @@ function connectionPipelinesController(state) {
};
}
function renderConnectionPipelines(state) {
function renderConnectionPipelines(state, pendingAction = null) {
return renderToStaticMarkup(createElement(K1ConnectionPipelines, {
controller: connectionPipelinesController(state),
controller: {
...connectionPipelinesController(state),
pendingAction,
},
desiredConnectionMode: "bridge",
onDesiredConnectionModeChange() {},
operationalPanelsVisible: shouldRenderK1OperationalPanels(state),
operationalPanelsVisible: shouldRenderK1OperationalPanels(state, pendingAction),
openSpatialScene() {},
activateAutomaticSpatialSource() {},
sourceLabel: "Ожидание",
@@ -2872,7 +2877,7 @@ test("runtime errors borrow diagnostics only from their exact Connect attempt",
);
});
test("connection recovery observation follows recommended exact policy then safe priority", () => {
test("connection recovery keeps current then durable priority over a stale fresh recommendation", () => {
const state = durableTopologyState();
state.snapshot_runtime_id = "runtime-recovery-priority";
state.devices = [{
@@ -2893,7 +2898,7 @@ test("connection recovery observation follows recommended exact policy then safe
state.connection_policy = {
schema_version: "missioncore.xgrids-k1-connection-policy/v1",
facts: { retained_context_is_presence: false },
recommended_action: "observe-configured-device-network",
recommended_action: "observe-fresh-device-network",
allowed_actions: [
"observe-current-device-network",
"observe-configured-device-network",
@@ -2913,10 +2918,21 @@ test("connection recovery observation follows recommended exact policy then safe
};
const recommended = recommendedConnectionRecoveryObservationTarget(state);
assert.equal(recommended?.action, "observe-configured-device-network");
assert.equal(recommended?.deviceId, "configured-k1");
assert.equal(recommended?.action, "observe-current-device-network");
assert.equal(recommended?.deviceId, "current-k1");
state.connection_policy.actions["observe-current-device-network"].allowed = false;
const durable = recommendedConnectionRecoveryObservationTarget(state);
assert.equal(durable?.action, "observe-configured-device-network");
assert.equal(durable?.deviceId, "configured-k1");
state.connection_policy.actions["observe-configured-device-network"].allowed = false;
const fresh = recommendedConnectionRecoveryObservationTarget(state);
assert.equal(fresh?.action, "observe-fresh-device-network");
assert.equal(fresh?.deviceId, "fresh-k1");
state.connection_policy.recommended_action = "scan-ble";
state.connection_policy.actions["observe-current-device-network"].allowed = true;
const fallback = recommendedConnectionRecoveryObservationTarget(state);
assert.equal(fallback?.action, "observe-current-device-network");
assert.equal(fallback?.deviceId, "current-k1");
@@ -3109,6 +3125,19 @@ test("cold disconnected connection SSR hides every operational panel", () => {
assert.doesNotMatch(unresolvedHistoryMarkup, /class="device-workspace__side/);
});
test("live preparation keeps operational panels mounted across a control handoff", () => {
const state = durableTopologyState();
const markup = renderConnectionPipelines(state, "live");
assert.equal(shouldRenderK1OperationalPanels(state, "live"), true);
assert.match(markup, /class="metrics-grid/);
assert.match(markup, /class="[^"]*\bsession-panel\b/);
assert.match(markup, /class="diagnostics-grid/);
assert.match(markup, /class="device-workspace__side/);
assert.match(markup, /Подключение установлено/);
assert.doesNotMatch(markup, /Переподключиться|Подключить заново/);
});
test("connected, active, replay and recovery SSR retain operational panels", () => {
const connected = runtimeState();
connected.phase = "connected";
@@ -3911,6 +3940,34 @@ test("explicit read-only recovery keeps its network-unavailable classification",
}
});
test("a BLE-proven missing Bridge address requires network setup across later retries", () => {
const state = {
connection_verification: {
status: "unreachable",
reason_code: "connection-verify-address-unavailable",
},
last_operation: {
action: "connection.verify",
status: "failed",
error: { code: "connection-verify-device-not-rediscovered" },
},
};
assert.equal(savedBridgeRequiresNetworkSetup(state), true);
assert.equal(savedBridgeRequiresNetworkSetup({
last_operation: {
action: "connection.verify",
status: "failed",
error: { code: "connection-verify-address-unavailable" },
},
}), true);
assert.equal(savedBridgeRequiresNetworkSetup({
connection_verification: {
status: "unreachable",
reason_code: "connection-verify-device-not-rediscovered",
},
}), false);
});
test("pre-write candidate loss is classified stale without granting UI continuation", () => {
for (const reasonCode of [
"BleakDeviceNotFoundError",
@@ -4256,7 +4313,7 @@ test("fresh Scan keeps retired audit rows selectable without recovery I/O", () =
assertCanonicalConnectionCopy(historicalAuditMarkup);
});
test("only current network recovery safe-next states retain a historical applied attempt", () => {
test("only an active network operation owns an applied-attempt screen", () => {
const attempt = {
schema_version: "missioncore.xgrids-k1-connection-attempt/v1",
attempt_id: "attempt-network-recovery-ownership",
@@ -4283,7 +4340,7 @@ test("only current network recovery safe-next states retain a historical applied
...attempt,
safe_next_action: safeNextAction,
}),
true,
false,
safeNextAction,
);
}
@@ -5205,6 +5262,51 @@ test("an unresolved physical command has one explicit server-bound read-only rec
/Результаты последнего Bluetooth-поиска|nearby-unrelated-device|>Выбрать<|>Применить</,
);
const networkSetupState = structuredClone(state);
networkSetupState.connection_verification = {
status: "unreachable",
lease_state: "disconnected",
network_reachability: "unreachable",
reason_code: "connection-verify-address-unavailable",
};
networkSetupState.last_operation = {
action: "connection.verify",
status: "failed",
error: { code: "connection-verify-device-not-rediscovered" },
};
const networkSetupMarkup = renderToStaticMarkup(createElement(
K1ProvisioningPipeline,
{
controller: provisioningController(networkSetupState),
desiredMode: "bridge",
},
));
const networkSetupReconnect = buttonMarkupWithText(
networkSetupMarkup,
"Переподключиться",
);
assert.equal(networkSetupReconnect.length, 1);
assert.doesNotMatch(networkSetupReconnect[0], /\bdisabled(?:=|\s|>)/);
const networkSetupAction = buttonMarkupWithText(
networkSetupMarkup,
"Подключить K1 к общей сети",
);
assert.equal(networkSetupAction.length, 1);
assert.doesNotMatch(networkSetupAction[0], /\bdisabled(?:=|\s|>)/);
assert.match(
networkSetupMarkup,
/K1 не подключён к сохранённой общей сети/,
);
assert.match(networkSetupMarkup, /не сообщил адрес Bridge/);
assert.doesNotMatch(
networkSetupMarkup,
/Локальная операция завершилась ошибкой|Проверьте питание и сеть/,
);
assert.match(
physicalRecoveryConnectionDetail(networkSetupState),
/K1 ответил по Bluetooth, но не подключён к сохранённой общей сети/,
);
const policyDeniedState = structuredClone(state);
policyDeniedState.connection_policy.allowed_actions = ["scan-ble"];
delete policyDeniedState.connection_policy.actions["observe-configured-device-network"];
@@ -5258,9 +5360,10 @@ test("an unresolved physical command has one explicit server-bound read-only rec
/scanWithResult\(|connect\(|retireUnavailable|reopenRetired|reconcilePhysicalCommand/,
);
assert.match(physicalRecovery, /physicalRecoveryTarget\?\.serverBound/);
assert.match(physicalRecovery, /surfaceErrors: false/);
});
test("supervisor DeviceInfo Verify keeps the exact physical reconnect visible", () => {
test("supervisor DeviceInfo Verify outranks a stale exact fresh row for physical recovery", () => {
const state = durableTopologyState();
const recoveryTransport = "F89438FA-55ED-85AD-EED7-734AC84746D8";
state.snapshot_runtime_id = "runtime-terminal-control-physical-recovery";
@@ -5299,11 +5402,20 @@ test("supervisor DeviceInfo Verify keeps the exact physical reconnect visible",
recommended_action: "scan-ble",
allowed_actions: [
"scan-ble",
"observe-fresh-device-network",
"inspect-configured-endpoint",
"verify-control-device-info",
],
actions: {
"observe-fresh-device-network": deniedObservation("fresh-scan"),
"observe-fresh-device-network": {
allowed: true,
reason_codes: [],
target_source: "fresh-scan",
required_transport_ref: recoveryTransport,
required_connection_mode: "bridge",
requires_live_gatt_validation: true,
automatic_retry: false,
},
"observe-current-device-network": deniedObservation(
"retained-current-process",
),
@@ -5320,6 +5432,13 @@ test("supervisor DeviceInfo Verify keeps the exact physical reconnect visible",
},
},
};
state.devices = [{
device_id: recoveryTransport,
name: "Projected K1",
connectable: true,
likely_k1: true,
}];
state.ble_discovery_generation = 2;
assert.deepEqual(readOnlyConnectionObservationTarget(state), {
action: "verify-control-device-info",
@@ -5341,6 +5460,7 @@ test("supervisor DeviceInfo Verify keeps the exact physical reconnect visible",
const mismatched = structuredClone(state);
mismatched.semantic_topology_store.record.transport_ref = "another-k1";
mismatched.connection_policy.actions["observe-fresh-device-network"].allowed = false;
assert.equal(readOnlyConnectionObservationTarget(mismatched), null);
});
@@ -5929,8 +6049,16 @@ test("terminal Apply recovery is bounded and never claims that the network is re
controller: provisioningController(state),
desiredMode: "bridge",
}, presentation);
assert.match(markup, /Управление не подтверждено/);
assert.match(markup, /Попытка настройки завершена/);
assert.match(markup, /Сохранённое подключение/);
assert.match(markup, /Подключить заново/);
assert.equal(
buttonMarkupWithText(markup, "Подключить новый K1").length,
1,
);
assert.doesNotMatch(
markup,
/Управление не подтверждено|выбор заблокирован|Попытка настройки завершена/,
);
assert.doesNotMatch(markup, /Сеть (?:готова|настроена)|Сетевые настройки уже применены/);
assert.doesNotMatch(markup, /Пароль передан|FIELD-NET|>Применить</);
assert.doesNotMatch(markup, /aria-busy="true"/);
@@ -6231,7 +6359,7 @@ test("unknown and cold durable recovery offer one reconnect and one new-device p
desiredMode: "bridge",
}, presentation);
assert.doesNotMatch(unrelatedMarkup, /op-b7ea404d/);
assert.match(unrelatedMarkup, /Результат применения сети не подтверждён/);
assert.match(unrelatedMarkup, /Сохранённое подключение/);
});
test("read-only reconnect keeps its card and loader across a transient projection", async () => {
@@ -6294,7 +6422,7 @@ test("read-only reconnect keeps its card and loader across a transient projectio
assert.match(pendingReconnect[0], /disabled/);
assert.match(pendingReconnect[0], /aria-busy="true"/);
assert.match(pendingReconnect[0], /nodedc-activity-indicator/);
assert.match(pendingMarkup, /Сохранённое подключение требует проверки/);
assert.match(pendingMarkup, /Сохранённое подключение/);
assert.doesNotMatch(pendingMarkup, /connection-action-progress/);
assert.equal(
harness.stateValue(emptyReadOnlyReconnectPresentation)?.kind,
@@ -6320,7 +6448,7 @@ test("read-only reconnect keeps its card and loader across a transient projectio
}
});
test("cold saved new-device path resets once, performs zero Scan, and survives reload", async () => {
test("cold saved target keeps fast reconnect after a reset and reload", async () => {
const state = terminalConnectionRecoveryState();
state.connection_attempt = null;
const target = recommendedConnectionRecoveryObservationTarget(state);
@@ -6424,14 +6552,18 @@ test("cold saved new-device path resets once, performs zero Scan, and survives r
},
desiredMode: "bridge",
});
assert.equal(buttonMarkupWithText(reloadedMarkup, "Переподключиться").length, 0);
const reloadedReconnect = buttonMarkupWithText(
reloadedMarkup,
"Переподключиться",
);
assert.equal(reloadedReconnect.length, 1);
assert.doesNotMatch(reloadedReconnect[0], /\bdisabled(?:=|\s|>)/);
const cleanScan = buttonMarkupWithText(reloadedMarkup, "Найти по Bluetooth");
assert.equal(cleanScan.length, 1);
assert.doesNotMatch(cleanScan[0], /\bdisabled(?:=|\s|>)/);
assert.doesNotMatch(
reloadedMarkup,
/Нужна проверка|Прежнее подключение не подтверждено|Проверяем прежний K1/,
);
assert.match(reloadedMarkup, /Сохранённое подключение/);
assert.match(reloadedMarkup, /Можно переподключиться/);
assert.doesNotMatch(reloadedMarkup, /Подключить новый K1/);
});
test("a current post-reset failed or unknown attempt outranks the durable reset marker after reload", () => {
@@ -6478,7 +6610,7 @@ test("a current post-reset failed or unknown attempt outranks the durable reset
},
desiredMode: "bridge",
});
assert.match(unknownReloadMarkup, /Результат применения сети не подтверждён/);
assert.match(unknownReloadMarkup, /Сохранённое подключение/);
assert.equal(
buttonMarkupWithText(unknownReloadMarkup, "Переподключиться").length,
1,
@@ -6501,9 +6633,20 @@ test("a current post-reset failed or unknown attempt outranks the durable reset
controller: provisioningController(failed),
desiredMode: "bridge",
});
assert.match(failedReloadMarkup, /Управление не подтверждено/);
assert.match(failedReloadMarkup, /Новый выбор временно заблокирован/);
assert.doesNotMatch(failedReloadMarkup, /Совпадений нет|Ожидает/);
assert.match(failedReloadMarkup, /Сохранённое подключение/);
assert.match(failedReloadMarkup, /Можно переподключиться/);
assert.equal(
buttonMarkupWithText(failedReloadMarkup, "Переподключиться").length,
1,
);
assert.equal(
buttonMarkupWithText(failedReloadMarkup, "Подключить новый K1").length,
1,
);
assert.doesNotMatch(
failedReloadMarkup,
/Управление не подтверждено|выбор заблокирован|Новый выбор временно заблокирован/,
);
});
test("Apply never owns hidden refresh or an automatic continuation", () => {
@@ -9,6 +9,7 @@ let claimExclusiveLiveViewer;
let createRecordedOpenWatchdog;
let createReentrantViewerDisposer;
let isLiveRerunPresentationReady;
let liveTimelineNeedsSynchronization;
let liveRerunReceiverBindingIdentity;
let recordedOpenWatchdogTimeoutMs;
let rerunViewerInitialSource;
@@ -26,6 +27,7 @@ before(async () => {
createRecordedOpenWatchdog,
createReentrantViewerDisposer,
isLiveRerunPresentationReady,
liveTimelineNeedsSynchronization,
liveRerunReceiverBindingIdentity,
recordedOpenWatchdogTimeoutMs,
rerunViewerInitialSource,
@@ -82,6 +84,14 @@ test("live presentation waits for the exact receiver to expose a usable range",
assert.equal(isLiveRerunPresentationReady(true, { min: 1, max: 1 }, 1), true);
});
test("live timeline is retried only after stream_time exists and until it is active", () => {
assert.equal(liveTimelineNeedsSynchronization(false, undefined, { min: 1, max: 2 }), false);
assert.equal(liveTimelineNeedsSynchronization(true, undefined, null), false);
assert.equal(liveTimelineNeedsSynchronization(true, undefined, { min: 1, max: 2 }), true);
assert.equal(liveTimelineNeedsSynchronization(true, "log_time", { min: 1, max: 2 }), true);
assert.equal(liveTimelineNeedsSynchronization(true, "stream_time", { min: 1, max: 2 }), false);
});
test("live receiver binding stays stable across recovery authority projections", () => {
const sourceUrl = "rerun+http://127.0.0.1:9877/proxy";
const streamId = "acq-001";
@@ -217,7 +227,11 @@ test("recorded RRD bytes are never split across LogChannel.send_rrd calls", asyn
);
assert.match(
source,
/const readyToRender = followLive\s*\? isLiveRerunPresentationReady\(/,
/const readyToRender = followLive\s*\? liveTimelineSynchronized && isLiveRerunPresentationReady\(/,
);
assert.match(
source,
/viewer\.get_active_timeline\(event\.recording_id\)[\s\S]*viewer\.set_active_timeline\(event\.recording_id, timeline\)/,
);
assert.match(
source,
@@ -257,7 +271,16 @@ test("raw replay exercises the same streaming receiver lifecycle as a live scan"
new URL("../src/workspaces/Workspaces.tsx", import.meta.url),
"utf8",
);
assert.match(source, /followLive=\{!recordedReplay && streamActive\}/);
assert.match(
source,
/const liveRerunSource = !recordedSource && \/\^rerun\\\+https\?:\\\/\\\//,
);
assert.match(
source,
/const livePresentationActivitySequence = metrics\?\.publishedFrameCount \?\?[\s\S]*liveRerunSource && !streamActive \? 1 : null/,
);
assert.match(source, /followLive=\{liveRerunSource\}/);
assert.match(source, /liveActivitySequence=\{livePresentationActivitySequence\}/);
assert.match(
source,
/sourceUrl\.trim\(\) && pointCloudVisible && !intentionalSourceEnd/,