import assert from "node:assert/strict"; import { createHash } from "node:crypto"; import { readFile } from "node:fs/promises"; import { after, before, test } from "node:test"; import { createServer } from "vite"; let server; let fetchM4ThreatReplayResult; let fetchM4ThreatVisual; let fetchM4ThreatTimeline; let fetchM4ThreatTimelineChunk; let fetchM4ThreatPlaybackManifest; let fetchM4ThreatPlaybackPointChunk; let fetchM4ThreatCameraPointOverlay; let hydrateM4ThreatTimelineFrame; let selectM4ThreatTimelineFrame; let selectM4ThreatTimelineSequence; let advanceRecordedEvidencePlayback; let synchronizeRecordedEvidencePlayback; let m4ThreatChunkWindowStarts; let cancelM4ThreatChunkRequestsOutsideWindow; let buildM4LocalSurface; let buildM4StaticObstacleBoxes; const resultId = `m4-threat-replay-${"a".repeat(64)}`; before(async () => { server = await createServer({ appType: "custom", logLevel: "silent", server: { middlewareMode: true }, }); ({ fetchM4ThreatReplayResult, fetchM4ThreatVisual, fetchM4ThreatTimeline, fetchM4ThreatTimelineChunk, fetchM4ThreatPlaybackManifest, fetchM4ThreatPlaybackPointChunk, fetchM4ThreatCameraPointOverlay, hydrateM4ThreatTimelineFrame, selectM4ThreatTimelineFrame, selectM4ThreatTimelineSequence, } = await server.ssrLoadModule("/src/core/laboratory/m4ReplayThreat.ts")); ({ advanceRecordedEvidencePlayback, synchronizeRecordedEvidencePlayback, } = await server.ssrLoadModule( "/src/components/laboratory/useRecordedEvidencePlayback.ts", )); ({ m4ThreatChunkWindowStarts, cancelM4ThreatChunkRequestsOutsideWindow, } = await server.ssrLoadModule( "/src/workspaces/laboratory/useM4ThreatTimeline.ts", )); ({ buildM4LocalSurface } = await server.ssrLoadModule( "/src/core/laboratory/m4LocalSurface.ts", )); ({ buildM4StaticObstacleBoxes } = await server.ssrLoadModule( "/src/workspaces/laboratory/m4StaticObstacleBoxes.ts", )); }); after(async () => { await server?.close(); }); function proposal(overrides = {}) { return { proposal_id: "proposal-1", bbox_xyxy: [100, 120, 240, 360], objectness: 0.91, semantic_hint: "person", occupied_support: false, range_m: null, threat_decision: "unknown", threat_reason_codes: ["camera-only-no-metric-geometry"], ...overrides, }; } function timelineFrame(sequence, sessionSeconds, overrides = {}) { return { schema_version: "missioncore.recorded-spatial-evidence-frame/v1", sequence, frame_id: `frame-${String(sequence).padStart(6, "0")}`, source_time_ns: Math.round(sessionSeconds * 1_000_000_000), session_seconds: sessionSeconds, source_available: true, spatial_available: true, body_frame: { origin_map_xyz_m: [sequence, 0, 0], basis_map_from_body: [[1, 0, 0], [0, 1, 0], [0, 0, 1]], }, point_cloud_body_xyz_m: [[1, 0, 0.1]], point_cloud_source_count: 1, point_cloud_sample_count: 1, point_cloud_layer: "current-increment", rolling_map_component_count: 0, metric_obstacles: [], camera_proposals: [], decision_counts: { threat: 0, "not-threat": 0, unknown: 0 }, camera_url: `/api/v1/laboratory/m4-threat/results/${resultId}/timeline/frames/${sequence}/camera`, authority: "replay-simulated", ...overrides, }; } test("M4.6 decodes accepted dual-evidence result without physical authority", async () => { const result = await fetchM4ThreatReplayResult({ fetcher: async () => new Response(JSON.stringify({ schema_version: "missioncore.m4-threat-replay-catalog/v1", items: [{ schema_version: "missioncore.m4-threat-replay-view/v1", result_id: resultId, created_at_utc: "2026-08-05T15:36:01.553Z", status: "accepted", profile_id: "m4-ravnoves00-virtual-corridor/v1", rig_profile_id: "virtual-base-footprint-1000x600/v2", corridor_profile_id: "ravnoves00-forward-corridor-8m/v2", source_result_ids: { detector: `m4-detector-replay-${"b".repeat(64)}`, geometry: `m4-geometry-replay-${"c".repeat(64)}`, temporal: `m4-temporal-replay-${"d".repeat(64)}`, }, metrics: { decisions: { threat: 8010, "not-threat": 6610, unknown: 60832 }, evidence: { "camera-only": 10158, "current-metric": 28081, "rolling-map-retained": 70989, "stale-or-held": 38025 }, fixtures: { critical: 4, critical_false_not_threat: 0, passed: 9, total: 9 }, runtime: { frames_per_second: 116.4, provider_latency_p50_ms: 4.3, provider_latency_p95_ms: 19.8, provider_latency_max_ms: 194.3, }, body_frame: { available: 3928, qualified: 3861, rejected: 67, camera_forward_alignment_deg: { p95: 8.439, maximum: 24.252 }, }, reason_counts: { "geometry-only-evidence": 21958 }, }, configuration: { virtual_body_m: [1, 0.6], nominal_sensor_height_m: 1.25, forward_corridor_m: 8, prediction_horizon_seconds: 5, body_frame: { origin: "local-surface-vertical-projection", up: "vendor-slam-map-gravity-axis", forward: "smoothed-slam-trajectory-validated-by-camera-axis", }, }, limitations: ["replay only"], accepted: true, authority: "replay-simulated", physical_collision_accepted: false, actuation_allowed: false, }], }), { status: 200 }), }); assert.equal(result.resultId, resultId); assert.equal(result.metrics.evidence.currentMetric, 28081); assert.equal(result.metrics.fixtures.criticalFalseNotThreat, 0); assert.equal(result.metrics.bodyFrame.qualified, 3861); assert.equal(result.metrics.bodyFrame.cameraForwardAlignmentDeg.p95, 8.439); assert.deepEqual(result.configuration.virtualBodyM, [1, 0.6]); assert.equal(result.configuration.bodyFrame.up, "vendor-slam-map-gravity-axis"); }); test("M4.6 binds exact CAMERA and metric 3D evidence to one replay frame", async () => { const frame = await fetchM4ThreatVisual(resultId, 1, { fetcher: async () => new Response(JSON.stringify({ schema_version: "missioncore.perception-threat-visual-frame/v1", result_id: resultId, camera_url: `/api/v1/laboratory/m4-threat/results/${resultId}/visuals/1/camera`, ordinal: 1, sequence: 20, frame_id: "frame-000020", source_time_ns: 37421857292, point_cloud_body_xyz_m: [[1, 0, 0.1], [2, 0.2, 0.3]], point_cloud_source_count: 12000, point_cloud_sample_count: 2, metric_obstacles: [{ component_id: "temporal-20-1", state: "current", motion: "moving", centroid_body_xyz_m: [2, 0.1, 0.4], cell_centers_body_xyz_m: [[2, 0.1, 0.4]], assessment: { component_id: "temporal-20-1", decision: "threat", corridor_intersection: "intersects", relative_speed_mps: 1.2, closest_approach_m: 0.4, ttc_seconds: 1.6, reason_codes: ["geometry-only-evidence"], }, }], camera_proposals: [proposal()], rig: { length_m: 1, width_m: 0.6, nominal_sensor_height_m: 1.25 }, corridor: { forward_length_m: 8, rear_margin_m: 0.5, half_width_m: 0.5, prediction_horizon_seconds: 5, }, }), { status: 200 }), }); assert.equal(frame.sequence, 20); assert.match(frame.cameraUrl, /\/visuals\/1\/camera$/); assert.equal(frame.metricObstacles[0].assessment.decision, "threat"); assert.equal(frame.cameraProposals[0].threatDecision, "unknown"); assert.equal(frame.pointCloudSampleCount, 2); }); test("M4.6 v2 keeps CURRENT INCREMENT separate from ROLLING MAP", async () => { const frame = await fetchM4ThreatVisual(resultId, 14, { fetcher: async () => new Response(JSON.stringify({ schema_version: "missioncore.perception-threat-visual-frame/v2", result_id: resultId, camera_url: `/api/v1/laboratory/m4-threat/results/${resultId}/visuals/14/camera`, ordinal: 14, sequence: 1880, frame_id: "frame-001880", source_time_ns: 223304857292, point_cloud_body_xyz_m: [[1, 0, 0.1]], point_cloud_source_count: 1652, point_cloud_sample_count: 1652, point_cloud_layer: "current-increment", rolling_map_component_count: 10, metric_obstacles: [{ component_id: "rolling-sphere-near", state: "retained", motion: "unknown", centroid_body_xyz_m: [0.76, -0.27, 0.38], cell_centers_body_xyz_m: [[0.52, -0.3, 0.08]], assessment: { component_id: "rolling-sphere-near", decision: "threat", corridor_intersection: "intersects", relative_speed_mps: null, closest_approach_m: 0.1, ttc_seconds: null, reason_codes: ["retained-corridor-intersection"], }, }], camera_proposals: [], rig: { length_m: 1, width_m: 0.6, nominal_sensor_height_m: 1.25 }, corridor: { forward_length_m: 8, rear_margin_m: 0.5, half_width_m: 0.5, prediction_horizon_seconds: 5, }, }), { status: 200 }), }); assert.equal(frame.pointCloudLayer, "current-increment"); assert.equal(frame.rollingMapComponentCount, 10); assert.equal(frame.metricObstacles[0].state, "retained"); assert.equal(frame.metricObstacles[0].assessment.decision, "threat"); }); test("M4.6 timeline keeps only a compact index and decodes bounded spatial chunks", async () => { const frameTimesNs = Array.from( { length: 4489 }, (_, index) => 35_421_857_292 + index * 100_000_000, ); const timeline = await fetchM4ThreatTimeline(resultId, { fetcher: async () => new Response(JSON.stringify({ schema_version: "missioncore.recorded-spatial-evidence-timeline/v1", result_id: resultId, recorded_source: { session_id: "20260720T065719Z_viewer_live", source_id: "RAVNOVES00", representation_id: "registered-map-increment-v1", synchronization: "host-arrival-best-effort", }, image_width: 800, image_height: 600, frame_count: 4489, frame_times_ns: frameTimesNs, timeline_start_seconds: 35.421857292, timeline_end_seconds: 484.221857292, nominal_frame_interval_seconds: 0.1, nominal_rate_hz: 10, max_chunk_frames: 24, point_sample_limit: 4096, maximum_source_points_per_frame: 3092, point_delivery: "exact-current-increment", local_surface_visualization: { derivation: "bounded-registered-increment-accumulation", window_seconds: 2, voxel_size_m: 0.1, radius_m: 12, point_limit: 20000, authority: "visual-derived", }, rig: { length_m: 1, width_m: 0.6, nominal_sensor_height_m: 1.25 }, corridor: { forward_length_m: 8, rear_margin_m: 0.5, half_width_m: 0.5, occupied_voxel_size_m: 0.45, prediction_horizon_seconds: 5, }, authority: "replay-simulated", }), { status: 200 }), }); assert.equal(timeline.frameTimesNs.length, 4489); assert.equal(timeline.pointDelivery, "exact-current-increment"); assert.equal(timeline.maximumSourcePointsPerFrame, 3092); assert.equal(timeline.occupiedVoxelSizeM, 0.45); assert.equal(timeline.localSurfaceVisualization.windowSeconds, 2); assert.equal(timeline.localSurfaceVisualization.authority, "visual-derived"); assert.equal(selectM4ThreatTimelineSequence(timeline.frameTimesNs, 35.50), 1); const chunk = await fetchM4ThreatTimelineChunk(resultId, 0, 2, { fetcher: async () => new Response(JSON.stringify({ schema_version: "missioncore.recorded-spatial-evidence-chunk/v1", result_id: resultId, start_sequence: 0, frame_count: 2, next_sequence: 2, frames: [ timelineFrame(0, 35.421857292), timelineFrame(1, 35.521857292, { camera_proposals: [proposal()], decision_counts: { threat: 0, "not-threat": 0, unknown: 1 }, }), ], authority: "replay-simulated", }), { status: 200 }), }); assert.equal(chunk.frames[1].cameraProposals[0].rangeM, null); assert.equal(selectM4ThreatTimelineFrame(chunk.frames, 35.50).sequence, 1); }); test("M4.6 hydrates a lightweight timeline frame from one retained binary point track", async () => { const raw = timelineFrame(0, 35.421857292, { body_frame: { origin_map_xyz_m: [10, 20, 30], basis_map_from_body: [[1, 0, 0], [0, 1, 0], [0, 0, 1]], }, point_cloud_body_xyz_m: [], point_cloud_source_count: 2, point_cloud_sample_count: 2, }); const parsed = await fetchM4ThreatTimelineChunk(resultId, 0, 1, { playbackPointPack: { resultId, frameCount: 4489, pointCount: 2, pointOffsets: new Uint32Array([0, 2, ...Array(4488).fill(2)]), pointsMapXyzM: new Float32Array([11, 20, 30.25, 12, 19.5, 30]), }, fetcher: async (input) => { assert.match(String(input), /include_points=false/); return new Response(JSON.stringify({ schema_version: "missioncore.recorded-spatial-evidence-chunk/v1", result_id: resultId, start_sequence: 0, frame_count: 1, next_sequence: 1, frames: [raw], authority: "replay-simulated", }), { status: 200 }); }, }); assert.deepEqual(parsed.frames[0].pointCloudBodyXyzM, [ [1, 0, 0.25], [2, -0.5, 0], ]); assert.equal(parsed.frames[0].pointCloudSampleCount, 2); assert.equal(typeof hydrateM4ThreatTimelineFrame, "function"); }); test("M4.6 source cloud opens from one verified bounded chunk instead of the 105 MiB track", async () => { const playbackResultId = `lab-v1-vegetation-shadow-${"b".repeat(64)}`; const frameCount = 48; const pointOffsets = [0, ...Array(frameCount).fill(2)]; const points = new Float32Array([11, 20, 30.25, 12, 19.5, 30]); const pointBytes = points.buffer; const pointSha256 = createHash("sha256").update(Buffer.from(pointBytes)).digest("hex"); const endpointRoot = "/api/v1/laboratory/m4-threat/results"; const chunks = Array.from({ length: Math.ceil(frameCount / 24) }, (_, index) => { const start = index * 24; const count = Math.min(24, frameCount - start); const pointStart = pointOffsets[start]; const pointStop = pointOffsets[start + count]; const pointCount = pointStop - pointStart; return { index, start, count, point_start: pointStart, point_count: pointCount, url: `${endpointRoot}/${playbackResultId}/timeline/playback/chunks/${index}`, media_type: "application/octet-stream", dtype: " { const url = String(input); requested.push(url); if (url.endsWith("/timeline/playback")) return Response.json(manifestPayload); if (url.endsWith("/timeline/playback/chunks/0")) return new Response(pointBytes.slice(0)); return new Response(null, { status: 404 }); }; const manifest = await fetchM4ThreatPlaybackManifest(playbackResultId, { fetcher }); const chunk = await fetchM4ThreatPlaybackPointChunk(manifest, 0, { fetcher }); assert.deepEqual(requested, [ `${endpointRoot}/${playbackResultId}/timeline/playback`, `${endpointRoot}/${playbackResultId}/timeline/playback/chunks/0`, ]); assert.equal(chunk.pointCount, 2); assert.equal(chunk.pointStart, 0); assert.equal(chunk.sequenceCount, 24); assert.equal(chunk.pointsMapXyzM.byteLength, 24); assert.equal(requested.some((url) => url.endsWith("points-map-f32")), false); }); test("M4.8S timeline binds factory-KB4 camera points through its exact endpoint", async () => { const replayResultId = `m48s-fixed-class-detector-lab-${"b".repeat(64)}`; const endpointRoot = "/api/v1/laboratory/m48s/fixed-class-detector"; const frameTimesNs = Array.from( { length: 4489 }, (_, index) => 35_421_857_292 + index * 100_000_000, ); let requested = ""; const timeline = await fetchM4ThreatTimeline(replayResultId, { endpointRoot, fetcher: async (input) => { requested = String(input); return new Response(JSON.stringify({ schema_version: "missioncore.recorded-spatial-evidence-timeline/v1", result_id: replayResultId, recorded_source: { session_id: "20260720T065719Z_viewer_live", source_id: "RAVNOVES00", representation_id: "registered-map-increment-v1", synchronization: "host-arrival-best-effort", }, image_width: 800, image_height: 600, frame_count: 4489, frame_times_ns: frameTimesNs, timeline_start_seconds: 35.421857292, timeline_end_seconds: 484.221857292, nominal_frame_interval_seconds: 0.1, nominal_rate_hz: 10, max_chunk_frames: 24, point_sample_limit: 4096, maximum_source_points_per_frame: 3092, point_delivery: "exact-current-increment", camera_point_delivery: "factory-kb4-causal-registered-accumulation", camera_point_window_seconds: 2, camera_point_sample_limit: 20000, world_state_delivery: "source-paced-latest-wins", occupancy_provenance_delivery: "baseline-versus-additive-component-diff", camera_obstacle_projection_delivery: "factory-kb4-actionable-added-corridor-bounds", world_state_frame_count: 4481, superseded_frame_count: 8, local_surface_visualization: { derivation: "bounded-registered-increment-accumulation", window_seconds: 2, voxel_size_m: 0.1, radius_m: 12, point_limit: 20000, authority: "visual-derived", }, rig: { length_m: 1, width_m: 0.6, nominal_sensor_height_m: 1.25 }, corridor: { forward_length_m: 8, rear_margin_m: 0.5, half_width_m: 0.5, occupied_voxel_size_m: 0.45, prediction_horizon_seconds: 5, }, authority: "replay-simulated", }), { status: 200 }); }, }); assert.equal(requested, `${endpointRoot}/${replayResultId}/timeline`); assert.equal(timeline.cameraPointDelivery, "factory-kb4-causal-registered-accumulation"); assert.equal(timeline.cameraPointWindowSeconds, 2); assert.equal(timeline.worldStateFrameCount, 4481); assert.equal(timeline.supersededFrameCount, 8); assert.equal( timeline.cameraObstacleProjectionDelivery, "factory-kb4-actionable-added-corridor-bounds", ); const chunk = await fetchM4ThreatTimelineChunk(replayResultId, 1, 1, { endpointRoot, cameraObstacleProjectionDelivery: timeline.cameraObstacleProjectionDelivery, fetcher: async (input) => { requested = String(input); return new Response(JSON.stringify({ schema_version: "missioncore.recorded-spatial-evidence-chunk/v1", result_id: replayResultId, start_sequence: 1, frame_count: 1, next_sequence: 2, frames: [timelineFrame(1, 35.521857292, { world_state_available: false, terminal_outcome: "superseded", camera_projected_points_xyd: [[100.5, 200.25, 3.75]], camera_projected_source_count: 847, camera_projected_point_count: 1, camera_projected_sample_count: 1, camera_projection: "factory-kb4-exact", metric_obstacles: [{ component_id: "temporal-1855-7", state: "current", motion: "stationary", centroid_body_xyz_m: [2.4, 0.1, 0.3], cell_centers_body_xyz_m: [[2.4, 0.1, 0.3]], occupancy_source: "additive-low-step", camera_projection: { bbox_xyxy: [390.5, 280.25, 408.75, 318.5], nearest_depth_m: 2.3, projected_cell_count: 1, projection: "factory-kb4-occupied-voxel-bounds", authority: "visual-derived", }, assessment: { component_id: "temporal-1855-7", decision: "threat", corridor_intersection: "intersects", relative_speed_mps: null, closest_approach_m: 0.2, ttc_seconds: null, reason_codes: ["current-corridor-intersection"], }, }], camera_url: `${endpointRoot}/${replayResultId}/timeline/frames/1/camera`, })], authority: "replay-simulated", }), { status: 200 }); }, }); assert.match(requested, new RegExp(`^${endpointRoot}/${replayResultId}/timeline/chunk`)); assert.match( requested, /obstacle_projection=factory-kb4-actionable-added-corridor-bounds/, ); assert.equal(chunk.frames[0].worldStateAvailable, false); assert.equal(chunk.frames[0].terminalOutcome, "superseded"); assert.deepEqual(chunk.frames[0].cameraProjectedPointsXyd[0], [100.5, 200.25, 3.75]); assert.equal(chunk.frames[0].cameraProjection, "factory-kb4-exact"); assert.deepEqual( chunk.frames[0].metricObstacles[0].cameraProjection.bboxXyxy, [390.5, 280.25, 408.75, 318.5], ); const overlay = await fetchM4ThreatCameraPointOverlay(replayResultId, 1, { endpointRoot, fetcher: async (input) => { requested = String(input); return new Response(JSON.stringify({ schema_version: "missioncore.m48s-camera-point-overlay/v1", result_id: replayResultId, sequence: 1, source_time_ns: 35_521_857_292, points_xyd: [[100.5, 200.25, 3.75], [101.5, 201.25, 3.8]], source_frame_count: 11, source_point_count: 28000, front_point_count: 18000, projected_point_count: 12000, sample_count: 2, window_seconds: 2, projection: "factory-kb4-causal-registered-accumulation", authority: "visual-derived", }), { status: 200 }); }, }); assert.equal( requested, `${endpointRoot}/${replayResultId}/timeline/frames/1/camera-points`, ); assert.equal(overlay.sourceFrameCount, 11); assert.equal(overlay.sampleCount, 2); assert.equal(overlay.projection, "factory-kb4-causal-registered-accumulation"); }); test("M4.8R3 turns active low-step components into native fisheye obstacle boxes", () => { const obstacle = { componentId: "temporal-1855-7", state: "current", motion: "stationary", centroidBodyXyzM: [2.4, 0.1, 0.3], cellCentersBodyXyzM: [[2.4, 0.1, 0.3]], occupancySource: "additive-low-step", cameraProjection: { bboxXyxy: [398, 298, 402, 302], nearestDepthM: 2.3, projectedCellCount: 1, projection: "factory-kb4-occupied-voxel-bounds", authority: "visual-derived", }, assessment: { componentId: "temporal-1855-7", decision: "threat", corridorIntersection: "intersects", relativeSpeedMps: null, closestApproachM: 0.2, ttcSeconds: null, reasonCodes: ["current-corridor-intersection"], }, }; const boxes = buildM4StaticObstacleBoxes([ obstacle, { ...obstacle, componentId: "baseline", occupancySource: "baseline" }, { ...obstacle, componentId: "held", state: "held" }, { ...obstacle, componentId: "unknown", assessment: { ...obstacle.assessment, decision: "unknown", corridorIntersection: "unknown", }, }, { ...obstacle, componentId: "clear", assessment: { ...obstacle.assessment, decision: "not-threat", corridorIntersection: "clear", }, }, ], 800, 600); assert.equal(boxes.length, 1); assert.deepEqual(boxes[0].boxXyxy, [394, 294, 406, 306]); assert.equal(boxes[0].label, "OBS #7 · 2,3 м"); assert.equal(boxes[0].tone, "danger"); assert.equal(boxes[0].dashed, false); }); test("M4.8R3 keeps separate CURRENT threats and suppresses their spanning ROLLING box", () => { const current = { componentId: "temporal-left-1", state: "current", motion: "stationary", centroidBodyXyzM: [3, 0, 0.3], cellCentersBodyXyzM: [[3, 0, 0.3]], occupancySource: "additive-low-step", cameraProjection: { bboxXyxy: [350, 260, 410, 310], nearestDepthM: 3, projectedCellCount: 2, projection: "factory-kb4-occupied-voxel-bounds", authority: "visual-derived", }, assessment: { componentId: "temporal-left-1", decision: "threat", corridorIntersection: "intersects", relativeSpeedMps: null, closestApproachM: 2.5, ttcSeconds: null, reasonCodes: ["current-corridor-intersection"], }, }; const boxes = buildM4StaticObstacleBoxes([ current, { ...current, componentId: "temporal-right-2", cameraProjection: { ...current.cameraProjection, bboxXyxy: [405, 265, 445, 320], }, }, { ...current, componentId: "rolling-spanning", state: "retained", cameraProjection: { ...current.cameraProjection, bboxXyxy: [340, 255, 450, 325], }, }, ], 800, 600); assert.equal(boxes.length, 2); assert.deepEqual(boxes.map((box) => box.label).sort(), [ "OBS #1 · 3 м", "OBS #2 · 3 м", ]); }); test("M4.6 local SLAM surface reprojects registered increments into the active body frame", () => { const frames = [ timelineFrame(0, 10, { body_frame: { origin_map_xyz_m: [0, 0, 0], basis_map_from_body: [[0, -1, 0], [1, 0, 0], [0, 0, 1]], }, point_cloud_body_xyz_m: [[1, 0, 0]], }), timelineFrame(1, 10.1, { body_frame: { origin_map_xyz_m: [0, 0, 0], basis_map_from_body: [[1, 0, 0], [0, 1, 0], [0, 0, 1]], }, point_cloud_body_xyz_m: [[1, 0, 0]], }), ].map((raw, index) => ({ sequence: raw.sequence, frameId: raw.frame_id, sourceTimeNs: raw.source_time_ns, sessionSeconds: raw.session_seconds, sourceAvailable: true, spatialAvailable: true, bodyFrame: { originMapXyzM: raw.body_frame.origin_map_xyz_m, basisMapFromBody: raw.body_frame.basis_map_from_body, }, pointCloudBodyXyzM: raw.point_cloud_body_xyz_m, pointCloudSourceCount: 1, pointCloudSampleCount: 1, pointCloudLayer: "current-increment", rollingMapComponentCount: 0, metricObstacles: [], cameraProposals: [], decisionCounts: { threat: 0, "not-threat": 0, unknown: 0 }, cameraUrl: raw.camera_url, })); const surface = buildM4LocalSurface(frames, frames[1], { windowSeconds: 2, voxelSizeM: 0.1, radiusM: 12, pointLimit: 20_000, }); assert.equal(surface.sourceFrameCount, 2); assert.equal(surface.sourcePointCount, 2); assert.deepEqual(surface.pointsBodyXyzM, [[0, 1, 0], [1, 0, 0]]); }); test("M4.6 spatial buffering keeps the active and one future chunk", () => { assert.deepEqual(m4ThreatChunkWindowStarts(48, 24, 4489), [48, 72, 24]); assert.deepEqual(m4ThreatChunkWindowStarts(0, 24, 4489), [0, 24]); }); test("M4.6 spatial buffering drops stale in-flight windows across rapid jumps", () => { const aborted = []; const controller = (start) => ({ abort: () => aborted.push(start) }); const inFlight = new Map( m4ThreatChunkWindowStarts(0, 24, 4489).map((start) => [start, controller(start)]), ); for (const activeStart of [1488, 4488]) { const desired = m4ThreatChunkWindowStarts(activeStart, 24, 4489); cancelM4ThreatChunkRequestsOutsideWindow(inFlight, desired); for (const start of desired) { if (!inFlight.has(start)) inFlight.set(start, controller(start)); } } assert.deepEqual([...inFlight.keys()], [4488, 4464]); assert.deepEqual(aborted, [0, 24, 1488, 1512, 1464]); }); test("recorded evidence clock advances by selected rate and stops at the sealed end", () => { const range = { startSeconds: 10, endSeconds: 20 }; assert.deepEqual( advanceRecordedEvidencePlayback( { currentSeconds: 12, playing: true, rate: 2 }, 1.5, range, ), { currentSeconds: 15, playing: true, rate: 2 }, ); assert.deepEqual( advanceRecordedEvidencePlayback( { currentSeconds: 19.5, playing: true, rate: 1 }, 1, range, ), { currentSeconds: 20, playing: false, rate: 1 }, ); }); test("recorded VIDEO clock cannot reverse an explicit operator pause", () => { const range = { startSeconds: 10, endSeconds: 20 }; assert.deepEqual( synchronizeRecordedEvidencePlayback( { currentSeconds: 15, playing: false, rate: 2 }, { currentSeconds: 15.1, playing: true, rate: 1 }, range, ), { currentSeconds: 15, playing: false, rate: 2 }, ); assert.deepEqual( synchronizeRecordedEvidencePlayback( { currentSeconds: 10, playing: false, rate: 2 }, { currentSeconds: 15.1, playing: true, rate: 1 }, range, ), { currentSeconds: 10, playing: false, rate: 2 }, ); assert.deepEqual( synchronizeRecordedEvidencePlayback( { currentSeconds: 12, playing: true, rate: 2 }, { currentSeconds: 15.1, playing: true, rate: 1 }, range, ), { currentSeconds: 15.1, playing: true, rate: 2 }, ); assert.deepEqual( synchronizeRecordedEvidencePlayback( { currentSeconds: 19.9, playing: true, rate: 1 }, { currentSeconds: 20, playing: false, rate: 1 }, range, ), { currentSeconds: 20, playing: false, rate: 1 }, ); }); test("M4.6 viewer keeps media and spatial panes on one playback clock", async () => { const [visual, canonical, visualCss, imageScene, videoScene, pointOverlay, metricScene] = await Promise.all([ readFile(new URL("../src/workspaces/laboratory/M4ReplayThreatVisual.tsx", import.meta.url), "utf8"), readFile(new URL("../src/components/laboratory/CanonicalRecordedLabReplay.tsx", import.meta.url), "utf8"), readFile(new URL("../src/styles/m4-replay-threat.css", import.meta.url), "utf8"), readFile(new URL("../src/components/laboratory/RecordedEvidenceImageScene.tsx", import.meta.url), "utf8"), readFile(new URL("../src/components/laboratory/RecordedEvidenceVideoScene.tsx", import.meta.url), "utf8"), readFile(new URL("../src/components/laboratory/RecordedEvidencePointCloudOverlay.tsx", import.meta.url), "utf8"), readFile(new URL("../src/components/laboratory/LaboratoryMetricEvidenceScene.tsx", import.meta.url), "utf8"), ]); assert.match(visual, /\s*POINTS\s*\s*OBSTACLES\s* \.nodedc-split-pane/); assert.match(visualCss, /m4-replay-threat-visual__pane-toolbar\[data-pane-toolbar="media"\]/); assert.match(visualCss, /m4-replay-threat-visual__pane-toolbar\[data-pane-toolbar="spatial"\]/); assert.match( visualCss, /data-mode-controls="content"\]:has\([\s\S]*m4-replay-threat-visual__review-controls[\s\S]*data-pane-toolbar="media"\][^{]*\{[^}]*top:\s*3\.8rem/s, ); assert.match(visualCss, /width: 33\.333333%/); assert.match(visualCss, /flex-flow: column nowrap/); assert.match(visualCss, /m4-replay-threat-visual__overlay > div/); assert.match(visualCss, /grid-template-columns: minmax\(0, 1fr\)/); assert.match(visualCss, /width: min\(17\.5rem/); assert.match(visualCss, /grid-auto-rows: 3\.8rem/); assert.match(visualCss, /--m4-replay-threat-overlay-pane-width/); assert.match(visualCss, /white-space: nowrap/); assert.match(visualCss, /-webkit-line-clamp: 2/); assert.match(visual, /classifiedCellCount/); assert.match(visual, /lastAvailableClassifiedSpatialFrame/); assert.match(visual, /current UNOBSERVED/); assert.match(visualCss, /laboratory-metric-evidence-scene__legend/); assert.match(visualCss, /bottom: auto/); assert.match(videoScene, / 0\.35/); assert.match(imageScene, /\s*SEMANTICS\s*<\/Button>/); assert.match(visual, /current safety — все \{classifiedCellCount\.toLocaleString\("ru-RU"\)\} TGS-ячейки UNOBSERVED/); assert.match( visual, /mapGravityLocalSensorToBodyGround[\s\S]*rotated\[2\] \+ nominalSensorHeightM/, ); assert.match( visual, /zBoundsM: \[[\s\S]*minimumSensorRelativeZ \+ nominalSensorHeightM[\s\S]*maximumSensorRelativeZ \+ nominalSensorHeightM/, ); assert.match(visual, /classifiedCells=\{classifiedCellsBody\}/); assert.match(metricScene, /Локальная SLAM-поверхность/); assert.match(visual, /showJumpToEnd=\{false\}/); assert.doesNotMatch(visual, /Назад на 5 секунд/); assert.doesNotMatch(visual, /Вперёд на 5 секунд/); assert.doesNotMatch(metricScene, /ЛКМ · вращение/); }); test("M4.6 keeps the recorded VIDEO player mounted across media mode toggles", async () => { const [visual, canonical] = await Promise.all([ readFile( new URL("../src/workspaces/laboratory/M4ReplayThreatVisual.tsx", import.meta.url), "utf8", ), readFile( new URL("../src/components/laboratory/CanonicalRecordedLabReplay.tsx", import.meta.url), "utf8", ), ]); assert.match(canonical, /const mediaPane = \(/); assert.match(canonical, /hidden=\{mediaMode === "none"\}/); assert.match(visual, /data-media="video"/); assert.match(visual, /hidden=\{mediaMode !== "video"\}/); assert.match(visual, /\{videoSource \? \(/); assert.doesNotMatch(visual, /\{mediaMode === "video" \? videoSource \? \(/); });