From 2e5c4ba1c595b03ffe203fd46b7e2c6b0968fe51 Mon Sep 17 00:00:00 2001 From: DCCONSTRUCTIONS Date: Sat, 25 Jul 2026 17:02:35 +0300 Subject: [PATCH] fix(polygon): focus runs on operator playback --- .../control-station/src/styles/workspaces.css | 9 ++- .../src/workspaces/LidarGroundPointCloud.tsx | 20 +++--- .../src/workspaces/PolygonRunWorkspace.tsx | 70 +++++++++---------- docs/12_SIMULATION_POLYGON_PRODUCT_AND_SRS.md | 39 ++++++++--- docs/14_LIDAR_DATASET_GATEWAY.md | 27 +++++-- 5 files changed, 100 insertions(+), 65 deletions(-) diff --git a/apps/control-station/src/styles/workspaces.css b/apps/control-station/src/styles/workspaces.css index 75b8f27..91dad5f 100644 --- a/apps/control-station/src/styles/workspaces.css +++ b/apps/control-station/src/styles/workspaces.css @@ -1244,7 +1244,7 @@ display: flex; height: 2.4rem; align-items: stretch; - gap: 1px; + gap: 0; overflow: hidden; margin: 0 0.65rem; border-radius: 0.42rem; @@ -1253,8 +1253,8 @@ } .polygon-review-timeline button { - min-width: 1px; - flex: 1 1 1px; + min-width: 0; + flex: 1 1 0; border: 0; border-radius: 0; outline: 0; @@ -1266,9 +1266,8 @@ .polygon-review-timeline button:hover, .polygon-review-timeline button[data-active="true"] { - min-width: 3px; opacity: 1; - box-shadow: 0 0 0 1px rgb(255 255 255 / 0.86); + box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.95); } .polygon-review-timeline-note { diff --git a/apps/control-station/src/workspaces/LidarGroundPointCloud.tsx b/apps/control-station/src/workspaces/LidarGroundPointCloud.tsx index 113074d..5cb0a81 100644 --- a/apps/control-station/src/workspaces/LidarGroundPointCloud.tsx +++ b/apps/control-station/src/workspaces/LidarGroundPointCloud.tsx @@ -88,17 +88,17 @@ function frameColors( setRgb( colors, offset, - groundTruth ? 0.78 : 0.29, - groundTruth ? 0.9 : 0.33, - groundTruth ? 0.42 : 0.38, + groundTruth ? 0.76 : 0.29, + groundTruth ? 0.86 : 0.33, + groundTruth ? 0.52 : 0.36, ); } else if (mode === "current") { setRgb( colors, offset, - current ? 0.73 : 0.29, - current ? 1 : 0.36, - current ? 0.29 : 0.43, + current ? 0.88 : 0.29, + current ? 0.68 : 0.34, + current ? 0.28 : 0.37, ); } else if (mode === "candidate") { if (!candidateAssigned) { @@ -107,9 +107,9 @@ function frameColors( setRgb( colors, offset, - candidate ? 0.24 : 0.29, - candidate ? 0.84 : 0.36, - candidate ? 1 : 0.43, + candidate ? 0.78 : 0.29, + candidate ? 0.91 : 0.34, + candidate ? 0.48 : 0.37, ); } } else if (mode === "disagreement") { @@ -131,7 +131,7 @@ function frameColors( disagreement ? 0.22 : 0.35, ); } else { - setRgb(colors, offset, candidate ? 0.24 : 0.29, candidate ? 0.84 : 0.36, 0.43); + setRgb(colors, offset, candidate ? 0.78 : 0.29, candidate ? 0.91 : 0.34, 0.4); } } return colors; diff --git a/apps/control-station/src/workspaces/PolygonRunWorkspace.tsx b/apps/control-station/src/workspaces/PolygonRunWorkspace.tsx index cbb1c40..0d74277 100644 --- a/apps/control-station/src/workspaces/PolygonRunWorkspace.tsx +++ b/apps/control-station/src/workspaces/PolygonRunWorkspace.tsx @@ -430,6 +430,41 @@ export function PolygonRunWorkspace({ route }: PolygonRunWorkspaceProps) { +
+ + + + selectPosition(Number(event.target.value))} + /> + {selectedPosition + 1} / {orderedFrames.length} +
+
{scene ? ( @@ -469,41 +504,6 @@ export function PolygonRunWorkspace({ route }: PolygonRunWorkspaceProps) {
) : null} -
- - - - selectPosition(Number(event.target.value))} - /> - {selectedPosition + 1} / {orderedFrames.length} -
-
{orderLabels.map(([order, label]) => ( diff --git a/docs/12_SIMULATION_POLYGON_PRODUCT_AND_SRS.md b/docs/12_SIMULATION_POLYGON_PRODUCT_AND_SRS.md index 28dbaa8..296e546 100644 --- a/docs/12_SIMULATION_POLYGON_PRODUCT_AND_SRS.md +++ b/docs/12_SIMULATION_POLYGON_PRODUCT_AND_SRS.md @@ -847,7 +847,8 @@ show an explicit offline state. The Polygon navigation is task-oriented: -- `Прогоны` owns live simulation lifecycle, history and qualification evidence; +- `Прогоны` owns recorded replay/simulation history and operator review of + qualification evidence; - `Датасеты` owns admitted replay inputs and the entry point for a future qualification run. @@ -857,16 +858,27 @@ remain under Fleet. A dataset preview is not a qualification result; the result is a versioned run with pipeline, sensor profile, metrics, provenance and decision. +Live simulation is a different operator task. A rover scene, worker health and +start/control actions must not be mounted above an archived dataset replay. +They require a separate live surface that appears only when the Simulation +Worker capability is available. The current `Прогоны` implementation is +read-only and remains fully usable while that worker is offline. + ### UI-0 — early read-only run view -Target S1B proves persisted start/health/stop history. UI-0 is implemented as a -direct internal run view and exposes: +Target S1B proves persisted start/health/stop history. The first direct +developer-oriented view exposed lifecycle, events, provider pins and artifact +hashes on the main screen. Operator review rejected that composition. The +current UI-0 makes the recorded evidence primary: -- run identity, lifecycle and terminal reason; -- authoritative clock and current pause/running state; -- provider health/process ownership; -- qualification events and admitted artifact links; -- explicit limitations and gate status. +- full source-order frame index instead of five selected examples; +- Play/pause, previous/next and arbitrary scrub; +- direct ground-truth, Current, Patchwork++ and error-map modes; +- current-frame metrics and a clickable all-frame improvement/regression strip; +- automatic best/worst ordering without preventing arbitrary manual selection; +- aggregate comparison after, rather than before, visual evidence; +- acceptance/degradation and run identity/provider/artifact details collapsed + below the operator workflow. The backend reads the configured repository from `MISSIONCORE_POLYGON_RUNS_ROOT` using @@ -875,12 +887,17 @@ The backend reads the configured repository from ```text GET /api/v1/polygon/runs GET /api/v1/polygon/runs/{run-id} +GET /api/v1/polygon/runs/{run-id}/qualification +GET /api/v1/polygon/runs/{run-id}/qualification/review +GET /api/v1/polygon/runs/{run-id}/qualification/review/frames/{frame-id} ``` Missing/malformed configuration returns `503`; invalid or corrupt evidence -fails closed. Responses never contain the configured root, artifact bytes or -command payloads. `?workspace=polygon-run[&run=]` remains a compatible -deep-link into the same product workspace. +fails closed. The review index exposes no paths or digests. A selected frame is +verified against the content-bound review manifest before its bounded point +preview is decoded. Responses never contain the configured root, raw dataset +bytes or command payloads. `?workspace=polygon-run[&run=]` remains a +compatible deep-link into the same product workspace. UI-0 itself has no PX4 transport or lifecycle/command operations. It remains a read-only evidence contract backed by the server-owned run repository and is diff --git a/docs/14_LIDAR_DATASET_GATEWAY.md b/docs/14_LIDAR_DATASET_GATEWAY.md index 9b4b7d6..e98ae84 100644 --- a/docs/14_LIDAR_DATASET_GATEWAY.md +++ b/docs/14_LIDAR_DATASET_GATEWAY.md @@ -312,7 +312,7 @@ points (required `>= 7`), natural-ground recall gain is `24.46` points (required `>= 90%`), assigned fraction is `100%` (required `>= 99.9%`) and p95 latency is `23.40 ms` (required `<= 50 ms`). No frame exceeded the catastrophic regression boundary of `-20` Ground-IoU points; the worst observed -delta was `-13.51` points and remains visible as a bounded failure preview. +delta was `-13.51` points. | Deterministic profile | Source coverage | Ground IoU | Natural recall | p95 latency | | --- | ---: | ---: | ---: | ---: | @@ -327,9 +327,28 @@ delta was `-13.51` points and remains visible as a bounded failure preview. Every degradation profile stayed inside the predeclared `15`-point Ground-IoU loss, `20`-point natural-recall loss and `50 ms` p95 limits. The sealed decision is therefore `shadow-candidate`, explicitly -`promoted_to_navigation_or_safety = false`. The compact `12 MB` run journal, -report and five worst-frame previews are available in `Polygon -> Runs`; the -source archive and crash-resume frame cache remain only on worker D. +`promoted_to_navigation_or_safety = false`. + +The first aggregate-only Polygon screen was rejected as an operator product: +five selected failure previews could not let an operator verify the decision. +Commit `b037076` adds a separate immutable visual derivative bound to the +qualification report: + +- schema `missioncore.goose-ground-review-pack/v1`; +- identity + `6ddc2de0154196088049b8654d9187fba0c52e28783e5ada6be5266dd16bd641`; +- all `961/961` validation frames in source order; +- deterministic `12,000`-point frame previews with remission, public + point-aligned ground truth, Current and Patchwork++ masks; +- compact size `67 MB`, versus multiple gigabytes for equivalent JSON; +- `Play`, frame scrubber, a clickable all-frame delta strip, best/worst + ordering and direct modes for geometry, ground truth, both providers and + both error maps. + +The source archive and full-resolution crash-resume cache remain only on worker +D. A bounded review mirror may be served by a Mission Core backend, but SSH is +not a product data plane. The replay UI does not render the unrelated live +Ackermann rover and does not depend on Simulation Worker online status. Primary source evidence: