feat: add local surface review triage
This commit is contained in:
@@ -7,6 +7,8 @@ let server;
|
||||
let parseLidarLocalSurfaceCatalog;
|
||||
let parseLidarLocalSurfaceFrame;
|
||||
let parseLidarLocalSurfaceTimeline;
|
||||
let parseLidarLocalSurfaceReview;
|
||||
let fetchLidarLocalSurfaceReview;
|
||||
let fetchLidarLocalSurfaceTimeline;
|
||||
let LidarLocalSurfaceContractError;
|
||||
|
||||
@@ -237,6 +239,106 @@ function timeline(overrides = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
function review(overrides = {}) {
|
||||
return {
|
||||
schema_version: "missioncore.k1-local-surface-review/v1",
|
||||
review_profile_id: "missioncore-local-surface-attention/v1",
|
||||
model_id: modelId,
|
||||
source_pack_id: sourcePackId,
|
||||
session_id: "20260720T065719Z_viewer_live",
|
||||
available: true,
|
||||
criteria: {
|
||||
prediction_tail_residual_p95_m: 0.45,
|
||||
prediction_inlier_fraction_floor: 0.85,
|
||||
surface_height_jump_m: 0.03,
|
||||
surface_slope_jump_deg: 0.5,
|
||||
surface_roughness_jump_m: 0.015,
|
||||
high_attention_score: 2,
|
||||
episode_max_frame_gap: 2,
|
||||
},
|
||||
summary: {
|
||||
item_count: 2,
|
||||
episode_count: 2,
|
||||
high_attention_count: 1,
|
||||
review_attention_count: 1,
|
||||
reason_counts: {
|
||||
"prediction-tail": 1,
|
||||
"prediction-inlier-drop": 1,
|
||||
"surface-height-jump": 1,
|
||||
"surface-slope-jump": 0,
|
||||
"surface-roughness-jump": 0,
|
||||
},
|
||||
},
|
||||
items: [
|
||||
{
|
||||
rank: 1,
|
||||
frame_index: 2,
|
||||
source_frame_index: 1002,
|
||||
session_seconds: 0.2,
|
||||
episode_id: "episode-02",
|
||||
attention: "high",
|
||||
attention_score: 2.4,
|
||||
reasons: ["prediction-tail", "prediction-inlier-drop"],
|
||||
prediction: {
|
||||
available: true,
|
||||
residual_p50_m: 0.05,
|
||||
residual_p95_m: 1.08,
|
||||
inlier_fraction: 0.64,
|
||||
},
|
||||
temporal: {
|
||||
compared: true,
|
||||
height_delta_m: 0.01,
|
||||
slope_delta_deg: 0.1,
|
||||
roughness_delta_m: 0.002,
|
||||
},
|
||||
surface: {
|
||||
sensor_height_m: 1.3,
|
||||
slope_deg: 2,
|
||||
roughness_m: 0.04,
|
||||
confidence: 0.8,
|
||||
},
|
||||
step_candidate_point_count: 13,
|
||||
},
|
||||
{
|
||||
rank: 2,
|
||||
frame_index: 1,
|
||||
source_frame_index: 1001,
|
||||
session_seconds: 0.1,
|
||||
episode_id: "episode-01",
|
||||
attention: "review",
|
||||
attention_score: 1.2,
|
||||
reasons: ["surface-height-jump"],
|
||||
prediction: {
|
||||
available: true,
|
||||
residual_p50_m: 0.04,
|
||||
residual_p95_m: 0.2,
|
||||
inlier_fraction: 0.95,
|
||||
},
|
||||
temporal: {
|
||||
compared: true,
|
||||
height_delta_m: 0.036,
|
||||
slope_delta_deg: 0.1,
|
||||
roughness_delta_m: 0.002,
|
||||
},
|
||||
surface: {
|
||||
sensor_height_m: 1.34,
|
||||
slope_deg: 2,
|
||||
roughness_m: 0.04,
|
||||
confidence: 0.8,
|
||||
},
|
||||
step_candidate_point_count: 20,
|
||||
},
|
||||
],
|
||||
ground_truth: false,
|
||||
access: "read-only",
|
||||
authority: {
|
||||
commands_enabled: false,
|
||||
navigation_or_safety_accepted: false,
|
||||
},
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
before(async () => {
|
||||
server = await createServer({
|
||||
appType: "custom",
|
||||
@@ -247,6 +349,8 @@ before(async () => {
|
||||
parseLidarLocalSurfaceCatalog,
|
||||
parseLidarLocalSurfaceFrame,
|
||||
parseLidarLocalSurfaceTimeline,
|
||||
parseLidarLocalSurfaceReview,
|
||||
fetchLidarLocalSurfaceReview,
|
||||
fetchLidarLocalSurfaceTimeline,
|
||||
LidarLocalSurfaceContractError,
|
||||
} = await server.ssrLoadModule("/src/core/lidar/localSurface.ts"));
|
||||
@@ -276,6 +380,14 @@ test("decodes passive local-surface evidence", () => {
|
||||
assert.equal(decodedTimeline.frameCount, 4);
|
||||
assert.deepEqual(decodedTimeline.temporalJump, [0, 0, 1, 0]);
|
||||
assert.equal(decodedTimeline.predictionResidualP50M[2], 0.05);
|
||||
|
||||
const decodedReview = parseLidarLocalSurfaceReview(review());
|
||||
assert.equal(decodedReview.summary.itemCount, 2);
|
||||
assert.equal(decodedReview.items[0].attention, "high");
|
||||
assert.deepEqual(decodedReview.items[0].reasons, [
|
||||
"prediction-tail",
|
||||
"prediction-inlier-drop",
|
||||
]);
|
||||
});
|
||||
|
||||
test("rejects inferred free space", () => {
|
||||
@@ -318,3 +430,30 @@ test("fetches the complete local-surface timeline read-only", async () => {
|
||||
}]);
|
||||
assert.equal(decoded.frameCount, 4);
|
||||
});
|
||||
|
||||
test("fetches a deterministic local-surface review queue read-only", async () => {
|
||||
const requests = [];
|
||||
const decoded = await fetchLidarLocalSurfaceReview(modelId, {
|
||||
fetcher: async (input, init) => {
|
||||
requests.push({ input: String(input), method: init?.method });
|
||||
return new Response(JSON.stringify(review()), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
},
|
||||
});
|
||||
assert.deepEqual(requests, [{
|
||||
input: `/api/v1/lidar/local-surfaces/${modelId}/review`,
|
||||
method: "GET",
|
||||
}]);
|
||||
assert.equal(decoded.items[0].sourceFrameIndex, 1002);
|
||||
});
|
||||
|
||||
test("rejects a review queue with forged priority", () => {
|
||||
const forged = review();
|
||||
forged.items[0].attention = "review";
|
||||
assert.throws(
|
||||
() => parseLidarLocalSurfaceReview(forged),
|
||||
LidarLocalSurfaceContractError,
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user