fix(lab): stabilize recorded spatial playback

This commit is contained in:
DCCONSTRUCTIONS
2026-08-06 08:51:10 +03:00
parent 9df9f58ab8
commit e38f2fb1da
11 changed files with 316 additions and 99 deletions
@@ -12,6 +12,7 @@ let fetchM4ThreatTimelineChunk;
let selectM4ThreatTimelineFrame;
let selectM4ThreatTimelineSequence;
let advanceRecordedEvidencePlayback;
let m4ThreatChunkWindowStarts;
const resultId = `m4-threat-replay-${"a".repeat(64)}`;
@@ -32,6 +33,9 @@ before(async () => {
({ advanceRecordedEvidencePlayback } = await server.ssrLoadModule(
"/src/components/laboratory/useRecordedEvidencePlayback.ts",
));
({ m4ThreatChunkWindowStarts } = await server.ssrLoadModule(
"/src/workspaces/laboratory/useM4ThreatTimeline.ts",
));
});
after(async () => {
@@ -243,6 +247,7 @@ test("M4.6 timeline keeps only a compact index and decodes bounded spatial chunk
recorded_source: {
session_id: "20260720T065719Z_viewer_live",
source_id: "RAVNOVES00",
representation_id: "registered-map-increment-v1",
synchronization: "host-arrival-best-effort",
},
image_width: 800,
@@ -254,18 +259,24 @@ test("M4.6 timeline keeps only a compact index and decodes bounded spatial chunk
nominal_frame_interval_seconds: 0.1,
nominal_rate_hz: 10,
max_chunk_frames: 24,
point_sample_limit: 2000,
point_sample_limit: 4096,
maximum_source_points_per_frame: 3092,
point_delivery: "exact-current-increment",
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(selectM4ThreatTimelineSequence(timeline.frameTimesNs, 35.50), 1);
const chunk = await fetchM4ThreatTimelineChunk(resultId, 0, 2, {
@@ -289,6 +300,11 @@ test("M4.6 timeline keeps only a compact index and decodes bounded spatial chunk
assert.equal(selectM4ThreatTimelineFrame(chunk.frames, 35.50).sequence, 1);
});
test("M4.6 spatial buffering keeps previous, active and two future chunks", () => {
assert.deepEqual(m4ThreatChunkWindowStarts(48, 24, 4489), [24, 48, 72, 96]);
assert.deepEqual(m4ThreatChunkWindowStarts(0, 24, 4489), [0, 24, 48]);
});
test("recorded evidence clock advances by selected rate and stops at the sealed end", () => {
const range = { startSeconds: 10, endSeconds: 20 };
assert.deepEqual(
@@ -319,6 +335,8 @@ test("M4.6 viewer reuses shared camera, video and metric evidence renderers", as
assert.match(visual, /<RecordedEvidenceVideoScene/);
assert.match(visual, /<RecordedEvidenceImageScene/);
assert.match(visual, /<LaboratoryMetricEvidenceScene/);
assert.match(visual, /m4-replay-threat-visual__deck/);
assert.match(visual, /lastFrameRef/);
assert.match(visual, /<ObservationTimeline/);
assert.match(visual, /useM4ThreatTimelineFrame/);
assert.match(visual, /label: "VIDEO"/);