feat(perception): add E34 temporal occupied layer

This commit is contained in:
DCCONSTRUCTIONS
2026-07-27 16:55:40 +03:00
parent 95c6540691
commit 621084fcd6
22 changed files with 4732 additions and 104 deletions
@@ -0,0 +1,89 @@
# ADR 0027 — E34 short-TTL occupied/unknown temporal layer
Date: 2026-07-27
Status: accepted for source-scoped diagnostic/shadow use
## Context
E32 published exclusive, source-indexed `PointSlab` ownership over all 4,489
immutable RAVNOVES00 frames. E33 proved that the exact E32 publication stream
can be delivered at recorded `1.0×` pace through bounded worker channels with
closed accounting. Neither result is a local temporal model: geometry-only
component keys are frame-local, current support disappears immediately when a
source is unavailable, and there is no explicit expiration event.
The K1 stream is already registered mapped evidence. It does not retain the
beam origin and firing time required for honest ray-cleared free-space
mapping. The accepted persistent reconstruction must also remain a separate,
immutable derivative.
## Predeclared decision
1. E34 consumes only the accepted content-addressed E32 result under the
accepted E33 timing/accounting envelope. It never rewrites E32, E33, raw
evidence, the mapped stream or persistent reconstruction.
2. The output is a separate `lidar-local-map/v1` diagnostic derivative in the
E32 `map` frame. It publishes only hit-backed `occupied` and conservatively
aged `unknown` state. It never publishes `free`.
3. Current E32 point owners become `current/occupied` temporal components.
Camera track identity is retained only as source provenance. Geometry-only
components receive new temporal IDs and may be spatially re-associated
without inventing a semantic class.
4. A component without current accepted points becomes `held/unknown` for at
most `0.75 s`. Its last hit-backed cells remain explicitly stale evidence,
not current measurement and not free-space proof.
5. After the TTL, the component emits one `expired/unknown` tombstone and is
removed from the active occupied layer. Expired cells are never published
as occupied.
6. Geometry-only re-association is deterministic, one-to-one and bounded to a
`0.35 s` gap and `0.9 m` centroid distance. It additionally requires either
a `0.05` neighbor-expanded voxel overlap or a centroid distance no greater
than one `0.45 m` voxel.
7. The layer uses hit-only `0.45 m` voxels, at most `4,096` cells per component
and at most `256` active components. Crossing a bound fails closed; cells
are not silently truncated and components are not silently evicted.
8. A map-frame jump candidate is diagnostic only. It requires at least four
adjacent matched components within `0.25 s`, median displacement of at
least `1.5 m` and 25th-percentile displacement of at least `0.9 m`.
9. Acceptance requires complete 4,489-frame accounting, exact upstream
artifact identity, bounded state, no free-space publication, no component
held past TTL, expiry no later than one `0.25 s` observation interval after
the theoretical deadline and zero global map-frame jump candidates.
10. Continuity, re-association, geometry-only persistence and ghost lifetime
are measured and reported. They are not converted into detector accuracy
or ground truth and are not retuned after inspecting this run.
11. Dynamic class, traversability, planner input, commands, navigation and
safety authority remain unavailable.
## Consequences
- The E34 result can prove a bounded temporal contract without claiming
free-space quality or changing persistent mapping.
- Camera-only, conflict, unknown and source-unavailable inputs can preserve
uncertainty but cannot create new occupied cells without prior accepted
hit-backed provenance.
- A rejected run remains immutable evidence. Any later profile change requires
a new ADR decision, profile identity and LAB result rather than overwriting
E34.
## Execution outcome
The first immutable implementation result
`e34-temporal-occupied-1bab293c1867100e172923b189f8273c47eacca3dd179fd54573200906affd7c`
was rejected without changing the profile. It exposed two implementation-level
architecture errors:
- scalar nearest-neighbor displacement was not sufficient to call a jump
global; the corrected detector requires one coherent translation within the
already fixed voxel residual;
- frame-driven expiry could not meet the TTL across a recorded `0.333 s`
source gap; expiration now uses an independent logical layer deadline and
retains the later replay materialization time separately.
The accepted result is
`e34-temporal-occupied-8d9abb3f2cc072cfdbb16cc4e55798e05c35a0abe0b8f691096770e091573a73`.
It processes all 4,489 frames and all 2,119,302 E32 point rows, peaks at 37
active components and 324 cells per component, emits zero free cells, meets
the `0.75 s` TTL exactly and reports zero coherent global map-frame jump
candidates. A8 now continues with E35 deterministic degradation/recovery.