feat(perception): qualify E35 degradation recovery

This commit is contained in:
DCCONSTRUCTIONS
2026-07-27 17:53:59 +03:00
parent 621084fcd6
commit b894945344
21 changed files with 3985 additions and 17 deletions
@@ -206,6 +206,99 @@ function e34() {
};
}
function e35() {
return {
result_id: `e35-degradation-recovery-${"5".repeat(64)}`,
created_at_utc: "2026-07-27T15:00:00Z",
source_session_id: "20260720T065719Z_viewer_live",
status: "accepted-deterministic-degradation-recovery",
e32_result_id: e32().result_id,
e33_result_id: e33().result_id,
e34_result_id: e34().result_id,
profile_id: "e35-six-channel-degradation-recovery/v1",
pipeline_id: "track-geometry/temporal-layer/degradation-recovery/v1",
coordinate_frame: "map",
configuration: {
maximum_recovery_seconds: 0.25,
scenario_count: 6,
},
metrics: {
source_frames: 4489,
variant_count: 6,
variant_frame_outcomes: 26934,
injection_records: 360,
variant_frame_processing_p95_ms: 1.08,
build_elapsed_ms: 18618,
},
scenarios: [{
scenario_id: "camera-loss",
kind: "camera-loss",
frame_start: 600,
frame_end: 659,
frames_processed: 4489,
injected_frames: 60,
dropped_frames: 0,
hidden_success_frames: 0,
false_free_rows: 0,
semantic_claims_during_camera_loss: 0,
metric_rows_during_lidar_or_pose_loss: 0,
agree_claims_during_timing_offset: 0,
late_results_reintroduced: 0,
maximum_current_components_during_fault: 13,
maximum_held_components_during_fault: 24,
expired_components_during_fault: 60,
recovery_frame_index: 660,
recovery_seconds: 0.086,
}],
review: {
schema_version: "missioncore.e35-recovery-review/v1",
result_id: `e35-degradation-recovery-${"5".repeat(64)}`,
scenarios: [{
scenario: {
schema_version: "missioncore.e35-degradation-scenario/v1",
scenario_id: "camera-loss",
kind: "camera-loss",
frame_start: 600,
frame_end: 659,
parameters: { drop_camera_observations: true },
},
frames: [{
scenario_id: "camera-loss",
kind: "camera-loss",
frame_index: 600,
source_frame_index: 600,
session_seconds: 95.4,
fault_phase: "during",
action: "camera-observations-removed",
channels: {
camera: "unavailable",
lidar: "available",
pose: "available",
delivery: "on-time",
},
input_point_rows: 300,
transformed_point_rows: 300,
layer_state: "current",
counts: { current: 5, held: 2, expired: 0 },
components: [{
temporal_id: 10,
state: "current",
occupancy_state: "occupied",
owner_kind: "geometry-cluster",
semantic_labels: [],
last_observed_age_seconds: 0,
centroid_map_xyz_m: [1, 2, 0.5],
}],
cell_centers_map_xyz_m: [[1, 2, 0.5]],
}],
}],
},
acceptance: { accepted: true },
authority,
access: "read-only",
};
}
before(async () => {
server = await createServer({
appType: "custom",
@@ -222,9 +315,9 @@ after(async () => {
await server?.close();
});
test("decodes E31E34 from separate read-only catalogs", async () => {
test("decodes E31E35 from separate read-only catalogs", async () => {
const requests = [];
const items = [e31(), e32(), e33(), e34()];
const items = [e31(), e32(), e33(), e34(), e35()];
const decoded = await fetchAdvancedLaboratoryResults({
fetcher: async (input, init) => {
requests.push({ input: String(input), method: init?.method });
@@ -241,11 +334,15 @@ test("decodes E31E34 from separate read-only catalogs", async () => {
assert.equal(decoded.e33.metrics.resultAgeMaxMs, 13.638);
assert.equal(decoded.e34.metrics.processedFrames, 4489);
assert.equal(decoded.e34.reviewFrames[0].components[0].state, "expired");
assert.equal(decoded.e35.metrics.variantFrameOutcomes, 26934);
assert.equal(decoded.e35.scenarios[0].recoverySeconds, 0.086);
assert.equal(decoded.e35.reviewScenarios[0].frames[0].faultPhase, "during");
assert.deepEqual(requests, [
{ input: "/api/v1/laboratory/e31/results?limit=1", method: "GET" },
{ input: "/api/v1/laboratory/e32/results?limit=1", method: "GET" },
{ input: "/api/v1/laboratory/e33/results?limit=1", method: "GET" },
{ input: "/api/v1/laboratory/e34/results?limit=1", method: "GET" },
{ input: "/api/v1/laboratory/e35/results?limit=1", method: "GET" },
]);
});
@@ -259,7 +356,8 @@ test("rejects authority escalation in an accepted-looking result", async () => {
fetcher: async (input) => new Response(JSON.stringify(catalog(
String(input).includes("/e31/") ? forged
: String(input).includes("/e32/") ? e32()
: String(input).includes("/e33/") ? e33() : e34(),
: String(input).includes("/e33/") ? e33()
: String(input).includes("/e34/") ? e34() : e35(),
)), { status: 200 }),
}),
AdvancedLaboratoryContractError,
@@ -26,6 +26,10 @@ const e34ResultUrl = new URL(
"../src/workspaces/laboratory/E34Result.tsx",
import.meta.url,
);
const e35ResultUrl = new URL(
"../src/workspaces/laboratory/E35Result.tsx",
import.meta.url,
);
const advancedLaboratoryResultUrl = new URL(
"../src/workspaces/laboratory/AdvancedLaboratoryResult.tsx",
import.meta.url,
@@ -161,6 +165,25 @@ test("E34 keeps temporal evidence inside the canonical LAB and viewer contracts"
assert.match(advancedSource, /<E34Result/);
});
test("E35 extends the canonical LAB with fault and recovery evidence", async () => {
const [e35Source, advancedSource] = await Promise.all([
readFile(e35ResultUrl, "utf8"),
readFile(advancedLaboratoryResultUrl, "utf8"),
]);
assert.match(e35Source, /<LaboratoryWorkTemplate/);
assert.match(e35Source, /<LaboratoryEvidenceViewer/);
assert.match(e35Source, /\{ value: "3d", label: "3D" \}/);
assert.match(e35Source, /\{ value: "plan", label: "План" \}/);
assert.match(e35Source, /Шесть неизменяемых полных replay-вариантов/);
assert.match(e35Source, /небезопасных утверждений —/);
assert.match(e35Source, /Следующий критический gate — A9\/E36/);
assert.match(e35Source, /SCENARIO_LABELS/);
assert.match(e35Source, /PHASE_LABELS/);
assert.match(advancedSource, /id: "e35-degradation-recovery"/);
assert.match(advancedSource, /<E35Result/);
});
test("the primary point-cloud viewer restores from fullscreen on Escape", async () => {
const workspacesSource = await readFile(workspacesUrl, "utf8");