feat(perception): integrate calibrated operator pipeline
Add calibrated K1 projection, recorded and near-live perception qualification, unified Rerun operator layers, bounded replay admission, audited viewer controls, worker experiments, and lab evidence.
This commit is contained in:
@@ -484,6 +484,31 @@ test("202 preparation polls through explicit phases and reveals launch only when
|
||||
assert.deepEqual(calls.map((entry) => entry[2]), [null, preparationEtag, preparationEtag]);
|
||||
});
|
||||
|
||||
test("initial replay restore is not mistaken for a stalled preparation poll", async () => {
|
||||
const sessionId = "session-20260716T205632Z";
|
||||
let requestSignal;
|
||||
const launch = await resolveObservationSessionReplay(sessionId, {
|
||||
signal: new AbortController().signal,
|
||||
requestTimeoutMs: 100,
|
||||
fetcher: async (_input, init) => {
|
||||
requestSignal = init.signal;
|
||||
await new Promise((resolve, reject) => {
|
||||
const timer = setTimeout(resolve, 150);
|
||||
init.signal.addEventListener("abort", () => {
|
||||
clearTimeout(timer);
|
||||
reject(new DOMException("cancelled", "AbortError"));
|
||||
}, { once: true });
|
||||
});
|
||||
return new Response(JSON.stringify(replay({ session_id: sessionId })), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
},
|
||||
});
|
||||
assert.equal(requestSignal.aborted, false);
|
||||
assert.equal(launch.sessionId, sessionId);
|
||||
});
|
||||
|
||||
test("status-ready response must match the preparation ETag before launch is accepted", async () => {
|
||||
const decoded = decodeObservationSessionPreparation(
|
||||
preparation({ state: "finalizing", progress: 0.95 }),
|
||||
@@ -704,6 +729,29 @@ test("switching saved sessions aborts only local polling and never cancels share
|
||||
assert.doesNotMatch(selectorSource, /cancelReplay|>\s*Отменить\s*</);
|
||||
});
|
||||
|
||||
test("recording preparation never presents phase heartbeats as fake percentages", async () => {
|
||||
const selectorSource = await readFile(
|
||||
new URL("../src/components/ObservationSessionSelect.tsx", import.meta.url),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
assert.match(selectorSource, /exporting:\s*["']Готовим операторскую сцену["']/);
|
||||
assert.doesNotMatch(selectorSource, /Math\.round\(progress\s*\*\s*100\)/);
|
||||
});
|
||||
|
||||
test("unified recorded AI view keeps the raw camera mounted but does not cover overlays", async () => {
|
||||
const workspaceSource = await readFile(
|
||||
new URL("../src/workspaces/Workspaces.tsx", import.meta.url),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
assert.match(workspaceSource, /hidden=\{pointCloudFocused \|\| unifiedPerception\}/);
|
||||
assert.match(
|
||||
workspaceSource,
|
||||
/presentedMediaSourceCount = unifiedPerception \? 0 : visibleMediaSources\.length/,
|
||||
);
|
||||
});
|
||||
|
||||
test("replay descriptor rejects path leaks, mismatched sessions and non-seekable data", () => {
|
||||
assert.throws(
|
||||
() => decodeObservationSessionReplay(replay({ source_url: "file:///private/session.rrd" })),
|
||||
@@ -776,7 +824,7 @@ test("replay decodes opaque recorded cameras and their same-origin fMP4 manifest
|
||||
);
|
||||
|
||||
const manifest = decodeObservationRecordedMediaManifest({
|
||||
schema_version: "missioncore.observation-recorded-media/v2",
|
||||
schema_version: "missioncore.observation-recorded-media/v3",
|
||||
source_id: source.id,
|
||||
generation_sha256: "c".repeat(64),
|
||||
byte_length: 3_266,
|
||||
@@ -788,21 +836,15 @@ test("replay decodes opaque recorded cameras and their same-origin fMP4 manifest
|
||||
timeline_start_seconds: 0.25,
|
||||
timeline_end_seconds: 20,
|
||||
media_type: 'video/mp4; codecs="avc1.640028"',
|
||||
init_url: source.manifest_url.replace("/manifest", "/epochs/1/init.mp4"),
|
||||
init_byte_length: 128,
|
||||
init_sha256: "a".repeat(64),
|
||||
segment_count: 12,
|
||||
segment_url_prefix: source.manifest_url.replace("/manifest", "/epochs/1/segments/"),
|
||||
segments: Array.from({ length: 12 }, (_, index) => ({
|
||||
sequence: index + 1,
|
||||
url: source.manifest_url.replace("/manifest", `/epochs/1/segments/${index + 1}.m4s`),
|
||||
byte_length: 256 + index,
|
||||
sha256: "b".repeat(64),
|
||||
})),
|
||||
byte_length: 3_266,
|
||||
stream_url: source.manifest_url.replace(
|
||||
"/manifest",
|
||||
`/epochs/1/recording.mp4?generation=${"c".repeat(64)}`,
|
||||
),
|
||||
}],
|
||||
}, decoded.mediaSources[0]);
|
||||
assert.equal(manifest.epochs[0].segmentCount, 12);
|
||||
assert.equal(manifest.epochs[0].segments.length, 12);
|
||||
assert.equal(manifest.epochs[0].byteLength, 3_266);
|
||||
assert.match(manifest.epochs[0].streamUrl, /recording\.mp4\?generation=/);
|
||||
assert.equal(manifest.epochs[0].timelineStartSeconds, 0.25);
|
||||
assert.throws(
|
||||
() => decodeObservationRecordedMediaManifest({
|
||||
@@ -821,7 +863,7 @@ test("replay decodes opaque recorded cameras and their same-origin fMP4 manifest
|
||||
);
|
||||
assert.throws(
|
||||
() => decodeObservationRecordedMediaManifest({
|
||||
schema_version: "missioncore.observation-recorded-media/v2",
|
||||
schema_version: "missioncore.observation-recorded-media/v3",
|
||||
source_id: source.id,
|
||||
generation_sha256: "c".repeat(64),
|
||||
byte_length: 3_267,
|
||||
@@ -834,6 +876,53 @@ test("replay decodes opaque recorded cameras and their same-origin fMP4 manifest
|
||||
);
|
||||
});
|
||||
|
||||
test("replay decodes a synchronized full-epoch perception video", () => {
|
||||
const sessionId = "20260720T065719Z_viewer_live";
|
||||
const resultId = `result-${"d".repeat(64)}`;
|
||||
const generation = "e".repeat(64);
|
||||
const source = {
|
||||
id: "recorded.perception.right",
|
||||
label: "Сегментация · камера right",
|
||||
modality: "video",
|
||||
manifest_url: `/api/v1/observation-sessions/${sessionId}/perception-media/${resultId}/manifest`,
|
||||
manifest_generation_sha256: generation,
|
||||
byte_length: 12_345_678,
|
||||
media_type: "video/mp4",
|
||||
timeline_start_seconds: 35.421857292,
|
||||
timeline_end_seconds: 484.144857292,
|
||||
seekable: true,
|
||||
synchronization: "host-arrival-best-effort",
|
||||
};
|
||||
const decoded = decodeObservationSessionReplay(replay({
|
||||
session_id: sessionId,
|
||||
timeline_end_seconds: 500,
|
||||
media_sources: [source],
|
||||
}));
|
||||
assert.equal(decoded.mediaSources[0].id, "recorded.perception.right");
|
||||
assert.equal(decoded.mediaSources[0].manifestUrl, source.manifest_url);
|
||||
|
||||
const manifest = decodeObservationRecordedMediaManifest({
|
||||
schema_version: "missioncore.observation-recorded-media/v3",
|
||||
source_id: source.id,
|
||||
generation_sha256: generation,
|
||||
byte_length: source.byte_length,
|
||||
timeline_start_seconds: source.timeline_start_seconds,
|
||||
timeline_end_seconds: source.timeline_end_seconds,
|
||||
synchronization: "host-arrival-best-effort",
|
||||
epochs: [{
|
||||
ordinal: 1,
|
||||
timeline_start_seconds: source.timeline_start_seconds,
|
||||
timeline_end_seconds: source.timeline_end_seconds,
|
||||
media_type: 'video/mp4; codecs="avc1.640028"',
|
||||
byte_length: source.byte_length,
|
||||
stream_url: `/api/v1/observation-sessions/${sessionId}/perception-media/${resultId}/recording.mp4?generation=${generation}`,
|
||||
}],
|
||||
}, decoded.mediaSources[0]);
|
||||
assert.equal(manifest.epochs.length, 1);
|
||||
assert.equal(manifest.epochs[0].timelineStartSeconds, source.timeline_start_seconds);
|
||||
assert.equal(manifest.epochs[0].timelineEndSeconds, source.timeline_end_seconds);
|
||||
});
|
||||
|
||||
test("recorded camera contracts reject foreign origins, path escapes and unknown fields", () => {
|
||||
const sessionId = "session-20260716T205632Z";
|
||||
const base = {
|
||||
@@ -888,7 +977,7 @@ test("recorded camera contracts reject foreign origins, path escapes and unknown
|
||||
}));
|
||||
assert.throws(
|
||||
() => decodeObservationRecordedMediaManifest({
|
||||
schema_version: "missioncore.observation-recorded-media/v2",
|
||||
schema_version: "missioncore.observation-recorded-media/v3",
|
||||
source_id: base.id,
|
||||
generation_sha256: "c".repeat(64),
|
||||
byte_length: 384,
|
||||
@@ -900,17 +989,8 @@ test("recorded camera contracts reject foreign origins, path escapes and unknown
|
||||
timeline_start_seconds: 0,
|
||||
timeline_end_seconds: 20,
|
||||
media_type: 'video/mp4; codecs="avc1.640028"',
|
||||
init_url: "file:///private/init.mp4",
|
||||
init_byte_length: 128,
|
||||
init_sha256: "a".repeat(64),
|
||||
segment_count: 1,
|
||||
segment_url_prefix: "file:///private/segments/",
|
||||
segments: [{
|
||||
sequence: 1,
|
||||
url: "file:///private/segments/1.m4s",
|
||||
byte_length: 256,
|
||||
sha256: "b".repeat(64),
|
||||
}],
|
||||
byte_length: 384,
|
||||
stream_url: "file:///private/recording.mp4",
|
||||
}],
|
||||
}, decoded.mediaSources[0]),
|
||||
/небезопасный API URL/,
|
||||
|
||||
Reference in New Issue
Block a user