import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { after, before, test } from "node:test"; import { createServer } from "vite"; let server; let fetchM4ThreatReplayResult; let fetchM4ThreatVisual; let fetchM4ThreatVideoOverlay; let selectM4ThreatVideoFrame; const resultId = `m4-threat-replay-${"a".repeat(64)}`; before(async () => { server = await createServer({ appType: "custom", logLevel: "silent", server: { middlewareMode: true }, }); ({ fetchM4ThreatReplayResult, fetchM4ThreatVisual, fetchM4ThreatVideoOverlay, selectM4ThreatVideoFrame, } = await server.ssrLoadModule("/src/core/laboratory/m4ReplayThreat.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, }; } 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 full video preserves camera-only unknown and nearest-frame selection", async () => { const overlay = await fetchM4ThreatVideoOverlay(resultId, { fetcher: async () => new Response(JSON.stringify({ schema_version: "missioncore.m4-threat-video-overlay/v1", result_id: resultId, recorded_source: { session_id: "20260720T065719Z_viewer_live" }, image_width: 800, image_height: 600, timeline_start_seconds: 35.421857292, timeline_end_seconds: 484.044857292, frame_count: 4489, frames: [ { frame_index: 0, session_seconds: 35.421857292, source_available: true, camera_proposals: [], decision_counts: { threat: 0, "not-threat": 0, unknown: 0 }, }, { frame_index: 1, session_seconds: 35.521857292, source_available: true, camera_proposals: [proposal()], decision_counts: { threat: 0, "not-threat": 0, unknown: 1 }, }, ], authority: "replay-simulated", }), { status: 200 }), }); assert.equal(overlay.frames[1].cameraProposals[0].rangeM, null); assert.equal(selectM4ThreatVideoFrame(overlay.frames, 35.50).frameIndex, 1); }); test("M4.6 viewer reuses shared camera, video and metric evidence renderers", async () => { const [visual, imageScene, videoScene, metricScene] = await Promise.all([ readFile(new URL("../src/workspaces/laboratory/M4ReplayThreatVisual.tsx", 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/LaboratoryMetricEvidenceScene.tsx", import.meta.url), "utf8"), ]); assert.match(visual, /