feat(lab): stabilize autonomous TGS playback

This commit is contained in:
DCCONSTRUCTIONS
2026-08-27 20:34:20 +03:00
parent c8593207d3
commit 95a1ef5057
26 changed files with 3326 additions and 253 deletions
@@ -0,0 +1,186 @@
# ADR 0043: Physical safety shadow and bounded operator visual
Date: 2026-08-27
Status: autonomous transport slice implemented; 0.15 m challenger and measured acceptance incomplete
## Context
Mission Core has accepted a source-paced RF-DETR-native plus TRAVEL TGS
recorded shadow on RAVNOVES00. The retained TGS result uses a `0.45 m` cell,
`12 m` radius and four explicit states. It is useful operator evidence but is
not a planner-authoritative terrain provider. The integrated acceptance joins
TGS and the reference graph as evidence; TGS does not modify graph state.
The intended physical rover is not a lightweight laboratory fixture. The
operator supplied the following planning facts, not yet independently measured:
- body `1.0 x 0.8 x 0.4 m`;
- ground clearance `0.15 m`;
- mass approximately `100 kg`;
- one nominal `500 W` motor per side;
- nominal speed `0.2778 m/s` (`1 km/h`);
- maximum operating speed `0.5556 m/s` (`2 km/h`).
Controller, remote dead-man, braking behavior, physical E-stop, body/sensor
extrinsics, center of gravity and negative-obstacle coverage are unavailable.
Commands therefore remain disabled.
The current full TGS playback pack is about `88 MiB`: approximately `9.6 MiB`
states, `77 MiB` z-bounds and `1.1 MiB` frame metadata. Holding the same
`12 m` disk for all `4,489` frames would scale to roughly `0.8 GiB` at `0.15 m`
and `1.8 GiB` at `0.10 m`, before richer terrain features, video, semantics and
renderer allocations. Full-session high-resolution browser preload is not an
admitted design for the current 18 GiB MacBook host.
## Decision
Recorded LAB and realtime perception are different runtime contours. Worker
006 is reserved for realtime perception. A new recorded LAB is built by a
bounded sequential offline builder on the MacBook, or admits an already sealed
immutable artifact. The offline build may take longer than source duration. It
must not become a hidden Worker job. An opened LAB never depends on Worker 006.
```text
recorded LAB publication, Worker 006 absent
recorded source -> local sequential offline build
-> seal immutable result + binary LOD tracks
|
v
local/CAS artifact store
|
Worker 006 remains absent
|
v
canonical local backend, read-only
|
v
MacBook LAB CAMERA + 3D + PLAN
separate future realtime contour
K1 -> Worker 006 -> live world-state/planner shadow
```
Opening, seeking, looping and visually inspecting a sealed LAB must perform
zero requests to Worker 006. If the worker, its host, Docker or the network path
to it is unavailable, a locally present sealed result opens unchanged. If a
manifest-declared local object is absent or corrupt, LAB fails with an explicit
artifact error; it does not start compute, scan worker results or silently
rebuild evidence. This preserves ADR 0033.
Publishing a new LAB also performs zero Worker requests. Slow local preparation
is acceptable, but it is explicit and bounded: build first, seal second, open
third. Historical LAB artifacts that were originally computed on Worker 006
remain valid after sealing because replay depends only on their immutable
artifacts; they do not justify a Worker dependency for new LABs.
Visual performance may never change a safety state, erase unknown space or
reduce the resolution used by the safety consumer. Conversely, the MacBook does
not need every cell of every high-resolution frame resident at once in order to
provide a complete operator explanation.
The retained `0.45 m` M49T5 profile and sealed result remain immutable. A new
physical-safety challenger may evaluate `0.15 m` and `0.10 m` cells without
rewriting that baseline. The first candidate resolution is `0.15 m`; `0.10 m`
is admitted only if LiDAR density improves the evidence. Worker compute
acceptance and autonomous LAB viewer acceptance are measured separately.
The operator transport uses binary typed arrays. It must not serialize one JSON
object per cell or expand binary frames into nested JavaScript objects before
updating GPU instances. Recorded high-resolution inspection reads only sealed
local binary chunks and active-frame detail, not a full-session high-resolution
preload.
The proposed spatial chunk is `32` source frames (`3.2 s` at `10 Hz`). Before
the spatial scene declares itself ready, it may preload the first two chunks,
or `6.4 s`, from the local artifact. The browser retains at most three chunks
(`9.6 s`), normally previous/current/next, and prefetches one forward chunk.
A backward seek loads the target and next chunk from the same sealed artifact.
This bounded startup delay is preferable to either Worker dependency or a
multi-gigabyte browser preload.
## Implemented autonomous transport slice
The first executable transport slice is now present without creating a new LAB
surface or transport clock:
- `m49_physical_safety_playback.py` is a local, sequential, filesystem-only
sealer. It accepts an already sealed source, verifies its declared hashes,
and writes immutable binary chunks atomically. It contains no Worker client,
job submission or network path.
- `m49_physical_safety_playback_api.py` exposes only the configured local
artifact root. Manifest, shared centers, frame catalog and every requested
chunk are hash-verified. Corruption returns an explicit artifact failure.
- `m49PhysicalSafetyPlayback.ts` rejects non-canonical URLs, verifies byte
length and SHA-256 in the browser, prebuffers two chunks, retains no more than
three and loads target plus next on seek.
- the existing M49 evidence composition resolves this transport by exact
`source_result_id`. If no chunked derivative has been published, it may still
read the old sealed local full pack; neither path uses Worker 006.
A real transport canary was generated from the accepted immutable `0.45 m`
M49T5 result without recomputing TGS or changing that source result. The canary
identity is
`m49-physical-safety-playback-0d0e41a995a902a4701935a79655d93f2f1898806f8fa82ebbd207129f111d69`.
It contains all `4,489` frames and `2,244` cells in `141` chunks. A normal
32-frame chunk is `646,300` bytes; two startup chunks are about `1.23 MiB` and
three spatial chunks are about `1.85 MiB`, plus the shared centers and frame
catalog. This is the transport canary only. It is not a `0.15 m` safety result
and no upsampled baseline is presented as new evidence.
The `0.15 m` shape, fail-closed missing-sample rule, bounded seek behavior and
zero-Worker URL policy are covered with synthetic contract fixtures. A real
`0.15 m` challenger still requires the local sequential terrain computation
and a separately sealed result.
The visual uses explicit LOD:
- `0-4 m`: `0.15 m` near-field cells;
- `4-8 m`: `0.30 m` explanatory cells;
- `8-12 m`: `0.45 m` context cells;
- pause/anchor inspection: full available active-frame resolution.
LOD changes only presentation. The sealed result retains the full candidate
evidence needed to reproduce its decisions; a future realtime worker separately
retains the full live safety grid across the configured safety radius.
The metric Three.js scene retains instanced meshes and all evidence layers. It
renders on evidence, camera interaction, resize or layer changes. It does not
run a permanent animation loop while idle. The scene exposes render-pass time,
draw calls, triangles, cell count and pixel ratio in the operator surface.
## Acceptance budget
Acceptance is measured on the named 14-inch 2023 MacBook Pro with 18 GiB RAM,
with recorded video, semantic overlay and TGS 3D/PLAN evidence available:
- source pace: `10 Hz` without evidence loss;
- main-thread frame preparation p95 at most `10 ms`;
- CPU-side WebGL render submission p95 target `16.7 ms`, hard maximum
`33.3 ms`; GPU completion requires a separate supported timer query;
- evidence-to-visible p95 at most `100 ms`;
- incremental visual resident memory at most `256 MiB`;
- post-warmup growth at most `32 MiB` over a ten-minute soak;
- zero browser long tasks above `50 ms` during source-paced playback;
- zero WebGL context losses;
- zero Worker 006 requests while opening, seeking or playing a LAB;
- zero Worker 006 requests while building a new recorded LAB;
- the sealed LAB opens with Worker 006 unavailable;
- idle metric scene performs no continuous render loop.
These are proposed thresholds until a canonical browser run emits a sealed
performance ledger. Passing them does not grant navigation, safety or actuation
authority.
## Consequences
- The operator keeps the full explanatory visual instead of receiving a
stripped-down safety UI.
- High-resolution terrain work does not turn the MacBook into a second
perception worker.
- Historical LAB remains usable during Worker maintenance, Docker failure or
loss of the Worker network path.
- Evidence identity and safety decisions remain independent of display LOD.
- The next implementation boundary is a packed, chunked terrain contract plus
footprint-aware states; no physical connection or command path is introduced.
- Physical authority remains blocked by controller/E-stop, measured braking,
vehicle geometry, sensor extrinsics and negative-obstacle coverage.