feat(lab): publish fail-closed TGS evidence

This commit is contained in:
DCCONSTRUCTIONS
2026-08-26 21:32:35 +03:00
parent 67d5d6fa05
commit 6544d9e918
27 changed files with 2167 additions and 73 deletions
@@ -1,7 +1,8 @@
# M4.9 gravity-aligned TGS fail-closed evidence — 2026-08-26
Status: **evidence adapter completed**; visual obstacle/traversability quality,
full-source realtime, navigation and actuation remain disabled
Status: **evidence adapter and canonical LAB publication completed**; visual
obstacle/traversability quality, full-source realtime, navigation and actuation
remain disabled
## Decision
@@ -13,7 +14,9 @@ accounts for every point inside TRAVEL's declared `1–80 m` processing range.
This closes the representation and accounting gate. It does not accept visual
quality. Several anchors still contain a high non-ground share, so the next
gate is a 3D/costmap review of the sealed output rather than threshold tuning or
camera boxes.
camera boxes. The metric output is now available in the canonical LAB on port
`8000` as an operator-review surface; publication does not upgrade it to an
accepted terrain provider.
## Frozen identity
@@ -125,15 +128,73 @@ Worker root:
| `inputs/input-manifest.json` | `13,357` | `7a22e61606e1fa9ab61d47417f941b590a68b29e4529d4c290992ce7eb89a642` |
| `tgs-timing.tsv` | `638` | `a8f439996205286335ac392b37f51b54056d04e9cb07e03648c52c1e8f2f6ae8` |
## Canonical LAB publication
- LAB result:
`m49-tgs-fail-closed-9d5cb089bb5cc23f829acb47eda52eaa886db3b60f8fa7d57e02e27f642e837b`;
- linked current visual timeline:
`m4-threat-replay-2a953c5f27f2a5b1dddc5c658c1de2c323d7796084a099c024987a1da03aa324`;
- source LiDAR pack SHA-256 remains
`0685d24219d8236caf8b7f1685e93f6d6b59e7fd015a768d88a92bbe8b154944`;
- the earlier immutable seal beginning `200b57cc` is superseded only because it
linked the retired M4 v2 visual profile, whose timeline is incompatible with
the current v3 API. No Worker evidence byte or TGS result was changed.
The LAB reuses the canonical recorded-realtime camera and spatial instrument.
It exposes the ten anchors, the full classified TGS point set, the four-state
costmap, `VIDEO/CAMERA`, `3D/PLAN`, independent point/costmap visibility and
exact per-anchor counts. Camera proposal boxes, AOS clusters, future frames and
navigation authority are absent. Browser acceptance confirmed that every
operator control is independent and that a loading anchor cannot temporarily
display unrelated M4 obstacle statistics.
The published TGS coordinates are intentionally sensor-origin
`map-gravity-local`: the ground is therefore approximately `-1.25 m` below the
current LiDAR. The canonical LAB presentation converts these immutable values
to the scene's body-ground origin by adding the rig's sealed
`nominal_sensor_height_m = 1.25` after the gravity-to-body rotation. The same
offset is applied to point heights and costmap z-bounds; x/y evidence and the
sealed Worker result remain unchanged. A regression check across all ten
anchors puts the median displayed ground points in `-0.299…+0.135 m` and the
median ground-cell centres in `-0.308…+0.237 m`. On anchor `1856`, where the
presentation defect was reported, those medians are `+0.004 m` and `-0.063 m`.
The residual variation is measured terrain/pose variation, not the previous
systematic `1.25 m` lift.
## Preliminary corridor triage
The published evidence was also projected into the frozen virtual body
corridor (`-0.5…8.0 m` longitudinal, `±0.5 m` lateral) without changing the
sealed result. The table counts costmap cell centres inside that corridor:
| Anchor | Current occupied | Rolling occupied | Rolling unobserved | Preliminary reading |
| ---: | ---: | ---: | ---: | --- |
| `171` | `0` | `8` | `6` | unresolved rolling band at `5.63…7.90 m` |
| `306` | `0` | `0` | `12` | no corridor obstruction |
| `368` | `1` | `1` | `16` | compact occupied support at `6.34 m` |
| `402` | `0` | `1` | `10` | compact occupied support at `1.89 m` |
| `450` | `0` | `0` | `8` | no corridor obstruction |
| `509` | `0` | `0` | `7` | no corridor obstruction |
| `525` | `0` | `0` | `9` | no corridor obstruction |
| `744` | `0` | `3` | `25` | weakly observed; requires explicit review |
| `1122` | `0` | `2` | `24` | rolling recovers compact obstacle support |
| `1856` | `1` | `1` | `13` | compact occupied support at `4.14 m` |
This is a diagnostic, not ground truth. It shows why the causal window cannot
simply be removed: anchor `1122` is entirely unobserved in the current-only
corridor but gains ground and occupied evidence in rolling. It also identifies
the opposing risk: at anchor `171`, rolling adds eight occupied cells where the
camera/PLAN comparison appears to show an open route apart from side geometry.
Anchor `744` remains too weakly observed for acceptance. These two anchors keep
the visual gate open even though the remaining frames do not show a continuous
occupied carpet.
## Next gate
Import the sealed `evidence.npz` into one laboratory review surface with:
1. 3D points colored by the four evidence states;
2. top-down `0.45 m` costmap cells in the same local coordinate frame;
3. anchor selection and exact counts from `result.json`;
4. no AOS clusters, camera boxes, future frames or physical authority.
The operator review must focus on the mandatory obstacle/gap cases and on the
large non-ground populations listed above. Camera projection follows only if
the metric evidence is accepted.
Review the published ten anchors in both metric `3D` and `PLAN`. The operator
must focus on the mandatory obstacle/gap cases and the large non-ground
populations listed above. Accept TGS for a full recorded-source shadow only if
red non-ground evidence remains on real geometry without carpeting the visible
route, soft traversable vegetation or usable gaps. Otherwise reject this
candidate without tuning thresholds against these ten anchors. Camera
projection follows only if the metric evidence is accepted.
@@ -0,0 +1,36 @@
#!/usr/bin/env python3
"""Publish the verified Worker TGS pack as immutable Mission Core LAB evidence."""
from __future__ import annotations
import argparse
from pathlib import Path
from k1link.laboratory.m49_tgs_fail_closed import (
M49TgsFailClosedError,
seal_m49_tgs_fail_closed,
)
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--source-root", type=Path, required=True)
parser.add_argument("--destination-root", type=Path, required=True)
parser.add_argument("--profile", type=Path, required=True)
parser.add_argument("--linked-visual-result-id", required=True)
arguments = parser.parse_args()
try:
result = seal_m49_tgs_fail_closed(
source_root=arguments.source_root,
destination_root=arguments.destination_root,
profile_path=arguments.profile,
linked_visual_result_id=arguments.linked_visual_result_id,
)
except (M49TgsFailClosedError, OSError, ValueError) as exc:
parser.error(str(exc))
print(result.result_id)
return 0
if __name__ == "__main__":
raise SystemExit(main())