feat(lab): stabilize autonomous TGS playback

This commit is contained in:
DCCONSTRUCTIONS
2026-08-27 20:34:20 +03:00
parent c8593207d3
commit 95a1ef5057
26 changed files with 3326 additions and 253 deletions
@@ -1,4 +1,5 @@
import assert from "node:assert/strict";
import { createHash } from "node:crypto";
import { readFile } from "node:fs/promises";
import { after, before, test } from "node:test";
@@ -9,6 +10,8 @@ let fetchM4ThreatReplayResult;
let fetchM4ThreatVisual;
let fetchM4ThreatTimeline;
let fetchM4ThreatTimelineChunk;
let fetchM4ThreatPlaybackManifest;
let fetchM4ThreatPlaybackPointChunk;
let fetchM4ThreatCameraPointOverlay;
let hydrateM4ThreatTimelineFrame;
let selectM4ThreatTimelineFrame;
@@ -33,6 +36,8 @@ before(async () => {
fetchM4ThreatVisual,
fetchM4ThreatTimeline,
fetchM4ThreatTimelineChunk,
fetchM4ThreatPlaybackManifest,
fetchM4ThreatPlaybackPointChunk,
fetchM4ThreatCameraPointOverlay,
hydrateM4ThreatTimelineFrame,
selectM4ThreatTimelineFrame,
@@ -373,6 +378,76 @@ test("M4.6 hydrates a lightweight timeline frame from one retained binary point
assert.equal(typeof hydrateM4ThreatTimelineFrame, "function");
});
test("M4.6 source cloud opens from one verified bounded chunk instead of the 105 MiB track", async () => {
const pointOffsets = [0, ...Array(4489).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: 188 }, (_, index) => {
const start = index * 24;
const count = Math.min(24, 4489 - 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}/${resultId}/timeline/playback/chunks/${index}`,
media_type: "application/octet-stream",
dtype: "<f4",
shape: [pointCount, 3],
bytes: pointCount * 3 * 4,
sha256: index === 0 ? pointSha256 : "0".repeat(64),
};
});
const manifestPayload = {
schema_version: "missioncore.recorded-spatial-playback/v1",
result_id: resultId,
frame_count: 4489,
point_count: 2,
point_offsets: pointOffsets,
chunk_frame_count: 24,
resident_chunk_count_max: 4,
forward_prefetch_chunk_count: 1,
chunks,
track: {
id: "points-map-f32",
url: `${endpointRoot}/${resultId}/timeline/playback/tracks/points-map-f32`,
media_type: "application/octet-stream",
dtype: "<f4",
shape: [2, 3],
bytes: pointBytes.byteLength,
sha256: pointSha256,
},
coordinate_frame: "map",
access: "read-only-sealed-binary-playback",
};
const requested = [];
const fetcher = async (input) => {
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(resultId, { fetcher });
const chunk = await fetchM4ThreatPlaybackPointChunk(manifest, 0, { fetcher });
assert.deepEqual(requested, [
`${endpointRoot}/${resultId}/timeline/playback`,
`${endpointRoot}/${resultId}/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";
@@ -825,10 +900,15 @@ test("M4.6 viewer keeps media and spatial panes on one playback clock", async ()
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, max-content\)/);
assert.match(visualCss, /width: max-content/);
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, /<RecordedFmp4Player/);
@@ -842,16 +922,18 @@ test("M4.6 viewer keeps media and spatial panes on one playback clock", async ()
assert.match(visual, /showLocalSurface/);
assert.match(
visual,
/pointCloudBodyXyzM=\{displayedClassifiedSpatialFrame && replaceClassifiedPointCloud[\s\S]*\? classifiedPointsBody[\s\S]*: activeSpatialFrame\?\.pointCloudBodyXyzM \?\? \[\]\}/,
/pointCloudBodyXyzM=\{displayedClassifiedSpatialFrame && replaceClassifiedPointCloud[\s\S]*\? classifiedPointsBody[\s\S]*: classifiedContextSpatialFrame\?\.pointCloudBodyXyzM \?\? \[\]\}/,
);
assert.match(
visual,
/const classifiedSpatialFrame = classifiedSpatialLayer\?\.frame\?\.sourceSequence === timelineFrame\.activeSequence[\s\S]*const displayedClassifiedSpatialFrame = classifiedSpatialFrame[\s\S]*lastClassifiedSpatialFrameRef/,
/const classifiedSpatialFrame = classifiedSpatialLayer\?\.frame\?\.sourceSequence === timelineFrame\.activeSequence[\s\S]*lastClassifiedSpatialFrameRef[\s\S]*const displayedClassifiedSpatialFrame = classifiedSpatialFrame\s*&&\s*classifiedSpatialFrame\.sampleAvailable !== false/,
);
assert.doesNotMatch(visual, /classifiedSpatialFrame\?\.sampleAvailable !== false/);
assert.match(visual, /timelineFrame\.availableFrames\.find/);
assert.match(visual, /localSurfaceBodyXyzM=\{localSurface\.pointsBodyXyzM\}/);
assert.match(visual, /showLocalSurface=\{showLocalSurface\}/);
assert.match(visual, /\{semantic \? \([\s\S]*>\s*SEMANTICS\s*<\/Button>/);
assert.match(visual, /все 2 244 TGS-ячейки явно UNOBSERVED/);
assert.match(visual, /current safety — все \{classifiedCellCount\.toLocaleString\("ru-RU"\)\} TGS-ячейки UNOBSERVED/);
assert.match(
visual,
/mapGravityLocalSensorToBodyGround[\s\S]*rotated\[2\] \+ nominalSensorHeightM/,