Стабилизация синхронного LAB-воспроизведения
This commit is contained in:
@@ -11,6 +11,7 @@ let AdvancedLaboratoryContractError;
|
||||
let buildLaboratoryCatalog;
|
||||
let buildLaboratoryProfiles;
|
||||
let experimentOptionsForProfile;
|
||||
let freshestLaboratorySelection;
|
||||
let workOptionsForExperiment;
|
||||
let fetchL34RightYoloxTruthIsland;
|
||||
let fetchL34RightYoloxTruthIslandFrame;
|
||||
@@ -853,6 +854,7 @@ before(async () => {
|
||||
buildLaboratoryCatalog,
|
||||
buildLaboratoryProfiles,
|
||||
experimentOptionsForProfile,
|
||||
freshestLaboratorySelection,
|
||||
workOptionsForExperiment,
|
||||
} = await server.ssrLoadModule(
|
||||
"/src/workspaces/laboratory/laboratoryArchiveProfiles.ts",
|
||||
@@ -930,6 +932,37 @@ test("LAB catalog is pipeline-scoped and ordered by real run time", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("LAB entry defaults atomically to the freshest pipeline, experiment and run", () => {
|
||||
const catalog = buildLaboratoryCatalog({
|
||||
rigLabel: "K1",
|
||||
knownWorks: [],
|
||||
advancedIndex: [
|
||||
{
|
||||
workId: "e46d-temporal-failure-audit",
|
||||
resultId: `e46d-temporal-failure-audit-${"d".repeat(64)}`,
|
||||
createdAtUtc: "2026-08-04T07:49:43.801Z",
|
||||
},
|
||||
{
|
||||
workId: "m4-replay-threat",
|
||||
resultId: `m4-threat-replay-${"4".repeat(64)}`,
|
||||
createdAtUtc: "2026-08-05T18:00:00.000Z",
|
||||
},
|
||||
{
|
||||
workId: "e47-semantic-slam-shadow",
|
||||
resultId: `e47-semantic-slam-${"7".repeat(64)}`,
|
||||
createdAtUtc: "2026-08-06T08:13:48.601Z",
|
||||
},
|
||||
],
|
||||
publishedWorks: [],
|
||||
});
|
||||
|
||||
assert.deepEqual(freshestLaboratorySelection(catalog), {
|
||||
profileId: "rig-dual-evidence-virtual-corridor-v1",
|
||||
experimentId: "ravnoves00-semantic-slam-shadow-r1",
|
||||
workId: "e47-semantic-slam-shadow",
|
||||
});
|
||||
});
|
||||
|
||||
test("E46E is exposed as the newest independent NVIDIA pipeline", () => {
|
||||
const catalog = buildLaboratoryCatalog({
|
||||
rigLabel: "K1",
|
||||
|
||||
@@ -224,7 +224,9 @@ test("E30 uses one reusable evidence viewer with camera, 3D and expand controls"
|
||||
assert.match(workspaceSource, /review: "Проверка"/);
|
||||
assert.doesNotMatch(workspaceSource, /e30-review-evidence__facts/);
|
||||
assert.doesNotMatch(workspaceSource, /E30EngineeringAuditPanel/);
|
||||
assert.match(viewerSource, /createPortal/);
|
||||
assert.match(viewerSource, /viewer\.showModal\(\)/);
|
||||
assert.match(viewerSource, /viewer\.show\(\)/);
|
||||
assert.doesNotMatch(viewerSource, /createPortal/);
|
||||
assert.match(viewerSource, /name=\{expanded \? "minimize" : "expand"\}/);
|
||||
assert.match(
|
||||
laboratoryStyles,
|
||||
|
||||
@@ -391,9 +391,10 @@ test("recorded evidence clock advances by selected rate and stops at the sealed
|
||||
);
|
||||
});
|
||||
|
||||
test("M4.6 viewer reuses shared camera, video and metric evidence renderers", async () => {
|
||||
const [visual, imageScene, videoScene, metricScene] = await Promise.all([
|
||||
test("M4.6 viewer keeps media and spatial panes on one playback clock", async () => {
|
||||
const [visual, visualCss, imageScene, videoScene, metricScene] = await Promise.all([
|
||||
readFile(new URL("../src/workspaces/laboratory/M4ReplayThreatVisual.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/LaboratoryMetricEvidenceScene.tsx", import.meta.url), "utf8"),
|
||||
@@ -403,17 +404,56 @@ test("M4.6 viewer reuses shared camera, video and metric evidence renderers", as
|
||||
assert.match(visual, /<LaboratoryMetricEvidenceScene/);
|
||||
assert.match(visual, /m4-replay-threat-visual__deck/);
|
||||
assert.match(visual, /lastFrameRef/);
|
||||
assert.match(visual, /lastSpatialFrameRef/);
|
||||
assert.match(visual, /const spatialFrame = frame\?\.spatialAvailable/);
|
||||
assert.match(visual, /<ObservationTimeline/);
|
||||
assert.match(visual, /useM4ThreatTimelineFrame/);
|
||||
assert.match(visual, /label: "VIDEO"/);
|
||||
assert.match(visual, /label: "CAMERA"/);
|
||||
assert.match(visual, /label: "3D"/);
|
||||
assert.match(visual, /label: "PLAN"/);
|
||||
assert.match(visual, /mediaMode/);
|
||||
assert.match(visual, /spatialMode/);
|
||||
assert.match(visual, /current === next \? null : next/);
|
||||
assert.match(visual, /data-split=\{splitView \? "true" : undefined\}/);
|
||||
assert.match(visual, /<SplitPane/);
|
||||
assert.match(visual, /primarySize=\{splitView \? splitPrimarySize : mediaMode \? 100 : 0\}/);
|
||||
assert.match(visual, /resizable=\{splitView\}/);
|
||||
assert.match(visual, /separatorLabel="Изменить размер VIDEO\/CAMERA и 3D\/PLAN"/);
|
||||
assert.match(visual, /secondaryMode=\{\{/);
|
||||
assert.match(visual, /playback=\{playbackController\.playback\}/);
|
||||
assert.match(visual, /currentSeconds: playbackController\.playback\.currentSeconds/);
|
||||
assert.doesNotMatch(visual, /setPlaying\(false\)/);
|
||||
assert.match(visualCss, /m4-replay-threat-visual__deck > \.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, /width: 33\.333333%/);
|
||||
assert.match(visualCss, /flex-flow: column nowrap/);
|
||||
assert.match(visualCss, /m4-replay-threat-visual__overlay > div/);
|
||||
assert.match(visualCss, /laboratory-metric-evidence-scene__legend/);
|
||||
assert.match(visualCss, /bottom: auto/);
|
||||
assert.match(videoScene, /<RecordedFmp4Player/);
|
||||
assert.match(imageScene, /<RecordedEvidenceBoxOverlay/);
|
||||
assert.match(metricScene, /OrbitControls/);
|
||||
assert.match(visual, /LOCAL SLAM/);
|
||||
assert.match(visual, /showLocalSurface/);
|
||||
assert.match(visual, /pointCloudBodyXyzM=\{spatialFrame\.pointCloudBodyXyzM\}/);
|
||||
assert.match(metricScene, /Local SLAM surface/);
|
||||
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 = await readFile(
|
||||
new URL("../src/workspaces/laboratory/M4ReplayThreatVisual.tsx", import.meta.url),
|
||||
"utf8",
|
||||
);
|
||||
assert.match(visual, /const mediaPane = \(/);
|
||||
assert.match(visual, /hidden=\{!mediaMode\}/);
|
||||
assert.match(visual, /data-media="video"/);
|
||||
assert.match(visual, /hidden=\{mediaMode !== "video"\}/);
|
||||
assert.match(visual, /\{videoSource \? \(/);
|
||||
assert.doesNotMatch(visual, /\{mediaMode === "video" \? videoSource \? \(/);
|
||||
});
|
||||
|
||||
@@ -209,7 +209,8 @@ test("data recordings keep the compact session dropdown and laboratory results s
|
||||
assert.match(laboratorySource, /experimentOptionsForProfile/);
|
||||
assert.match(laboratorySource, /workOptionsForExperiment/);
|
||||
assert.doesNotMatch(laboratorySource, /laboratoryWorkOrdinal/);
|
||||
assert.match(laboratorySource, /initialWorkSelectedRef/);
|
||||
assert.match(laboratorySource, /freshestLaboratorySelection\(catalog\)/);
|
||||
assert.match(laboratorySource, /initialSelectionAppliedRef/);
|
||||
assert.match(laboratorySource, /pollingEnabled:\s*false/);
|
||||
assert.match(laboratorySource, /useAdvancedLaboratoryCatalog/);
|
||||
assert.doesNotMatch(laboratorySource, /fetchAdvancedLaboratoryResults/);
|
||||
|
||||
@@ -4,18 +4,30 @@ import { test } from "node:test";
|
||||
|
||||
const component = (name) => new URL(`../src/components/laboratory/${name}`, import.meta.url);
|
||||
|
||||
test("semantic evidence mask is decoded, cached, cancelled and object-contained client-side", async () => {
|
||||
test("semantic evidence mask is GPU-colored, bounded, cancelled and object-contained client-side", async () => {
|
||||
const source = await readFile(component("RecordedEvidenceSemanticMaskOverlay.tsx"), "utf8");
|
||||
assert.match(source, /decodedMaskCache/);
|
||||
assert.match(source, /pendingMaskCache/);
|
||||
assert.match(source, /MASK_CACHE_LIMIT = 20/);
|
||||
assert.match(source, /MASK_PREFETCH_LIMIT = 12/);
|
||||
assert.match(source, /prefetchSrcs\?: readonly string\[\]/);
|
||||
assert.match(source, /\.slice\(0, MASK_PREFETCH_LIMIT\)/);
|
||||
assert.match(source, /AbortController/);
|
||||
assert.match(source, /createSemanticMaskRenderer/);
|
||||
assert.match(source, /getContext\("webgl"/);
|
||||
assert.match(source, /preserveDrawingBuffer: true/);
|
||||
assert.match(source, /vec2\(v_uv\.x, 1\.0 - v_uv\.y\)/);
|
||||
assert.match(source, /UNPACK_FLIP_Y_WEBGL, 0/);
|
||||
assert.match(source, /gl\.isContextLost\(\)/);
|
||||
assert.match(source, /webglcontextlost/);
|
||||
assert.match(source, /setRendererMode\("2d"\)/);
|
||||
assert.match(source, /gl\.texImage2D/);
|
||||
assert.match(source, /u_palette/);
|
||||
assert.match(source, /getImageData/);
|
||||
assert.match(source, /8-bit grayscale class-id PNG/);
|
||||
assert.match(source, /ResizeObserver/);
|
||||
assert.match(source, /Math\.min\(width \/ imageWidth, height \/ imageHeight\)/);
|
||||
assert.match(source, /Math\.min\(width \/ mask\.width, height \/ mask\.height\)/);
|
||||
assert.match(source, /decoded\.key !== expectedKey/);
|
||||
assert.match(source, /mask\?\.key === expectedKey/);
|
||||
assert.match(source, /необъявленный class ID/);
|
||||
assert.match(source, /recorded-evidence-semantic-mask-overlay__error/);
|
||||
assert.match(source, /role="alert"/);
|
||||
});
|
||||
@@ -43,27 +55,40 @@ test("metric evidence keeps missing semantic assignments as context and exposes
|
||||
assert.match(source, /recordedEvidenceSemanticCssColor/);
|
||||
});
|
||||
|
||||
test("semantic point alignment is enforced only when M4 exposes the exact spatial increment", async () => {
|
||||
test("semantic point alignment follows the last qualified spatial increment", async () => {
|
||||
const source = await readFile(
|
||||
new URL("../src/workspaces/laboratory/M4ReplayThreatVisual.tsx", import.meta.url),
|
||||
"utf8",
|
||||
);
|
||||
assert.match(source, /semantic && frame\?\.spatialAvailable && semanticFrame/);
|
||||
assert.match(source, /\|\| !frame\.spatialAvailable\s*\|\| !semanticFrame/);
|
||||
assert.match(source, /semanticFrame\.sourcePointCount !== frame\.pointCloudSourceCount/);
|
||||
assert.match(source, /frame\?\.spatialAvailable && semanticFrame/);
|
||||
assert.match(source, /lastSpatialSemanticFrameRef/);
|
||||
assert.match(source, /\|\| !spatialFrame\s*\|\| !spatialSemanticFrame/);
|
||||
assert.match(source, /spatialSemanticFrame\.sourcePointCount !== spatialFrame\.pointCloudSourceCount/);
|
||||
});
|
||||
|
||||
test("M4 mounts semantic mask overlays only for the active VIDEO or CAMERA layer", async () => {
|
||||
test("M4 keeps independent semantic controls in media and spatial panes", async () => {
|
||||
const source = await readFile(
|
||||
new URL("../src/workspaces/laboratory/M4ReplayThreatVisual.tsx", import.meta.url),
|
||||
"utf8",
|
||||
);
|
||||
assert.match(
|
||||
source,
|
||||
/semanticOverlay=\{mode === "video" \? semanticOverlay : undefined\}/,
|
||||
);
|
||||
assert.match(
|
||||
source,
|
||||
/semanticOverlay=\{mode === "camera" \? semanticOverlay : undefined\}/,
|
||||
);
|
||||
assert.match(source, /showMediaSemantic/);
|
||||
assert.match(source, /showSpatialSemantic/);
|
||||
assert.match(source, /semantic && showMediaSemantic && frame/);
|
||||
assert.match(source, /Array\.from\(\{ length: 12 \}, \(_, index\) => index \+ 1\)/);
|
||||
assert.match(source, /\|\| !showSpatialSemantic/);
|
||||
assert.match(source, /aria-label="Слои камеры и видео"/);
|
||||
assert.match(source, /aria-label="Слои 3D и плана"/);
|
||||
assert.match(source, /data-pane-mode="media"/);
|
||||
assert.match(source, /data-pane-mode="spatial"/);
|
||||
assert.match(source, /modeControlsVisible=\{!splitView\}/);
|
||||
assert.match(source, /semanticOverlay=\{mediaMode === "video" \? semanticOverlay : undefined\}/);
|
||||
});
|
||||
|
||||
test("laboratory fullscreen preserves the mounted evidence subtree", async () => {
|
||||
const source = await readFile(component("LaboratoryEvidenceViewer.tsx"), "utf8");
|
||||
assert.match(source, /useLayoutEffect/);
|
||||
assert.match(source, /viewer\.showModal\(\)/);
|
||||
assert.match(source, /viewer\.show\(\)/);
|
||||
assert.match(source, /<dialog/);
|
||||
assert.doesNotMatch(source, /createPortal/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user