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 fetchM49TgsFullShadowSpatialChunk; let parseM49TgsNpyTrack; const resultId = `m49-tgs-full-shadow-${"a".repeat(64)}`; before(async () => { server = await createServer({ appType: "custom", logLevel: "silent", server: { middlewareMode: true }, }); ({ fetchM49TgsFullShadowSpatialChunk, parseM49TgsNpyTrack } = await server.ssrLoadModule( "/src/core/laboratory/m49TgsFullShadow.ts", )); }); after(async () => { await server?.close(); }); test("M4.9T5 chunk keeps every missing-LiDAR cell explicitly UNOBSERVED", async () => { let requestedUrl = ""; const centers = Array.from({ length: 2244 }, (_, index) => [index * 0.45, 0]); const unobserved = Array.from({ length: 2244 }, () => 0); const zBounds = Array.from({ length: 2244 }, () => [null, null]); const metrics = { eligible_point_count: 0, ground_point_count: 0, nonground_point_count: 0, rejected_point_count: 0, occupied_cell_count: 0, }; const chunk = await fetchM49TgsFullShadowSpatialChunk(resultId, 7, 1, { fetcher: async (url) => { requestedUrl = String(url); return new Response(JSON.stringify({ schema_version: "missioncore.m49-tgs-full-shadow-spatial-chunk/v1", result_id: resultId, start: 7, count: 1, coordinate_frame: "map-gravity-local", costmap: { cell_size_m: 0.45, radius_m: 12, centers_xy_m: centers, }, frames: [{ source_sequence: 7, source_frame_index: 7, session_seconds: 36.119857292, sample_available: false, states: unobserved, z_bounds_m: zBounds, metrics, }], }), { status: 200, headers: { "Content-Type": "application/json" } }); }, }); assert.equal( requestedUrl, `/api/v1/laboratory/m49/tgs-full-shadow/${resultId}/spatial/chunk?start=7&count=1`, ); assert.equal(chunk.count, 1); assert.equal(chunk.frames[0].sampleAvailable, false); assert.equal(chunk.frames[0].costmap.states.length, 2244); assert.deepEqual(new Set(chunk.frames[0].costmap.states), new Set([0])); }); test("M4.9T5 viewer prefers autonomous chunks and keeps a sealed legacy fallback", async () => { const [source, visual, scene, contract] = await Promise.all([ readFile( new URL("../src/workspaces/laboratory/M49TgsFullShadowEvidence.tsx", import.meta.url), "utf8", ), readFile( new URL("../src/workspaces/laboratory/M4ReplayThreatVisual.tsx", import.meta.url), "utf8", ), readFile( new URL("../src/components/laboratory/LaboratoryMetricEvidenceScene.tsx", import.meta.url), "utf8", ), readFile( new URL("../src/core/laboratory/m49TgsFullShadow.ts", import.meta.url), "utf8", ), ]); assert.match(source, /fetchM49PhysicalSafetyPlaybackIdForSource/); assert.match(source, /M49PhysicalSafetyPlaybackBuffer\.open/); assert.match(source, /physicalPlayback\.frameIfResident/); assert.match(source, /physicalPlayback\.prepare/); assert.match(source, /fetchM49TgsFullShadowPlaybackPack/); assert.match(source, /playbackProgress/); assert.doesNotMatch(source, /fetchM49TgsFullShadowSpatialChunk/); assert.match(source, /sampleAvailable: frame\.sampleAvailable/); assert.match(source, /packedCellsMapGravityLocal/); assert.match(source, /playbackPack\.states\.subarray/); assert.match(source, /playbackPack\.zBoundsM\.subarray/); assert.doesNotMatch(source, /Array\.from\(\s*playbackPack\.states/); assert.doesNotMatch(source, /centersXyM\.map\(/); assert.match(source, /fetchE47SemanticSlamResult/); assert.match(source, /next\.baseM4ResultId !== result\.source\.linkedVisualResultId/); assert.match(source, /semantic=\{semantic \? \{/); assert.match( visual, /classifiedSpatialFrame\s*&&\s*classifiedSpatialFrame\.sampleAvailable !== false/, ); assert.doesNotMatch(visual, /classifiedSpatialFrame\?\.sampleAvailable !== false/); assert.match(visual, /timelineFrame\.availableFrames\.find/); assert.match(visual, / resetView\(\), \[mode, resetView\]\)/); assert.match(contract, /linked_semantic_result_id/); assert.match(contract, /missioncore\.m49-tgs-full-shadow-playback\/v1/); }); function npyFloat32(values, shape) { const shapeText = shape.length === 1 ? `${shape[0]},` : shape.join(", "); const prefixLength = 10; let header = `{'descr': ' { const parsed = parseM49TgsNpyTrack( npyFloat32([1.25, -2.5, 3.75, 4.5], [2, 2]), "