TCS → guardrails: recall-first integration plan

2026-07-18 · AI3D guardrails + tablecloth (TCS) · Claude Fable 5

Summary

Problem: only about half of the guardrails present in a segment are ever detected. Directive: the implementation agent optimizes recall now — precision is protected by a floor, not by tight candidate gates.

Approach: use the tablecloth (TCS) ground/object separation as a second, high-recall evidence source. Its removal mask captured 98–100 % of guardrail and wall-face returns in the 2026-07-18 experiments (segments 064–076 visual QC; walls 134/135 measured), so most misses cannot be blamed on missing returns — they die later in the pipeline. The plan therefore starts by measuring where misses actually happen (miss taxonomy), then attacks the two classes TCS can fix: candidate starvation (residue-union candidates) and DEM/height-band errors (SMRF surface as the height reference), then extends the same machinery to walls.

North star metric: per-length guardrail recall on a frozen reference set of ~20–30 non-bridge segments, re-measured at the end of every phase.

Key decisions

Phases

Phase 0 — Recall truth harness & miss taxonomy experiment · ~1–2 days

Goal: turn “about half are detected” into a frozen, re-runnable measurement and a taxonomy of why each rail is missed.

  • Answered 2026-07-18 (Miro): the ≈50 % figure is Miro's visual observation, not a measured number — no ground truth or prior comparison/QC exists to trace it back to. There is nothing to "pin down"; the Phase-0 baseline must be built visually, from scratch. Starting denominator: the existing 367 w-beam-run audit on battlebox (2026-07-17 asphalt-edge research note) plus the reference-set overlays below.
  • Reuse the already-designed blinded-window protocol from that note (252 random 20 m windows, 2/segment + 96 targeted, 10 % double-labeled, lateral buffers 0.25/0.5/1/2 m, locked 32-segment test set) instead of inventing tagging from scratch. Beware self-referential truth: same-cloud manual references were measured ~10 pp too forgiving on curbs; step7_xml/abschnitt_4_5 is empty and lane_state_snapshot.json is pipeline-derived — neither is independent.
  • Render top-down + perspective overlays with current detections; tag every visible rail run (Opus for visual tagging, human spot-check on the double-labeled sample). Exclude historically flaky segments (Long-production failure list) from the reference set.
  • Classify each miss into: (a) no returns / occlusion — the documented #1 published recall killer, (b) candidate starvation — points exist but never enter the candidate set, (c) DEM/HAG error — points enter but fall outside the 0.42–0.78 m rail band (p8 contamination under rail occlusion and slope terracing at break lines are both documented mechanisms), (d) killed by cluster gates (length / spacing / heading / qualifying ratio), (e) lost in merge/dedupe or occlusion bridging, (f) mislabeled as corridor exclusion, (g) record-boundary artifact gap — data artifact, excluded from the recall denominator.
  • Deliverables: per-class counts, per-segment recall baseline, and a frozen exemplar list (segment/record/station ranges) checked into the repo for regression re-runs.

Gate: taxonomy exists; classes (b)+(c) quantified — these are the TCS-addressable classes the rest of the plan bets on. If (a) occlusion dominates, revisit targets before implementing.

Phase 1 — Residue headroom experiment experiment · ~1 day, battlebox

Goal: measure the recall ceiling the residue offers before writing any detector code.

  • Rail analogue of the wall-survival experiment: for every Phase-0 missed rail, compute the fraction of its neighborhood points present in ~kept_mask and inside the corridor (variants: elev_scalar 0.0 vs 1.25).
  • Prototype (standalone script, no repo changes): candidates = current set ∪ residue-in-corridor → existing occupancy/DBSCAN parameters → count how many Phase-0 miss exemplars now form clusters, and how many new non-rail clusters appear (FP preview).
  • Reuse the battlebox experiment scaffold from the wall run (/home/ai/tcs-wall-exp/ pattern; per-segment out dirs to avoid the run_summary clobber).
  • Add the TCS embankment calibration grid already proposed in the 2026-07-17 note — window {3, 6, 12 m} × elev diff {0.05, 0.15, 0.30 m} × slope {0.15, 0.30} — on embankment-heavy segments: tablecloth defaults are lip-tuned for asphalt-edge and were never validated on >15 % grades, exactly where rails stand.
  • Known residue blind spot to measure, not discover later: SMRF's ≤3 m window lets trucks/decks survive into the ground surface → suppressed HAG and missing residue near large vehicles; rails alongside parked trucks will not be rescued by the union.

Gate: residue union recovers a majority of class-(b)/(c) misses on the exemplars. Otherwise stop and re-plan around the dominant miss class.

Phase 2 — Recall-first candidate union in guardrails implement · ~2–3 days

Goal: ship the recall lever. Guardrails learns to consume TCS masks.

  • New inputs: --tablecloth-masks-dir (per-record *_tablecloth_masks.npz); config flag default off, bit-identical when off.
  • In detect._accumulate_candidates: candidate points = (HAG band ∩ corridor) ∪ (residue ∩ corridor ∩ sanity band 0.15–2.5 m). Sanity band uses the best available height reference (p8 now, SMRF surface after Phase 3).
  • Recall lever in geometry.select_candidate_cells: for cells that are ≥~80 % residue-backed, widen the rail mean-HAG acceptance (e.g. 0.30–1.20 m instead of 0.42–0.78) — exact numbers tuned on the Phase-0 exemplars, not invented.
  • TDD workflow (Red: Grok writes failing tests incl. bit-identical-off and vehicle-not-imported adversarial cases; Green: Sol implements; Review: Opus correctness / Sonnet constraints / Grok test adequacy / Sol second opinion; battlebox suite).

Gate: recall on the reference set rises by the Phase-1-predicted amount for classes (b)/(c); FP looks acceptable under visual QC (no numeric ceiling — no ground truth to measure one against; see Risks). Visual QC round on 5 segments.

Phase 3 — Ground-model upgrade: Option C first, native SMRF surface if needed implement · ~3–4 days, both repos

Goal: fix miss class (c) at the root. Staged per the recorded 2026-07-17 decision (Option C preferred; native TCS only on escalation) — that decision was made for precision-era criteria, so the recall re-measure is the new deciding metric.

  • 3a — Option C hybrid: build the existing 0.75 m p8 DEM from TCS-ground-only points (mask input, no grid change, all ~15 height-gate constants untouched, streaming contract preserved). Removes object contamination under rails/trucks/canopy. Adopt criteria: recall gain on class-(c) exemplars; churn on clean segments reported (the recorded <2 % criterion is re-evaluated for the recall goal, not blindly enforced).
  • 3b — native surface (escalation only): if slope/embankment false negatives persist: tablecloth persists SmrfSurface per record behind --set surface_output=true (npz: grid, grad, xmin, ymin, cell_m, elev_scalar; version bump + Nexus); guardrails mosaics per-record surfaces onto the tile frame (cellwise min overlap), GroundModel adapter, config-gated with p8 fallback. De-quantizes the rail band (±25 cm raster error at 0.75 m vs 0.20 m). Memory note: 0.20 m segment-wide grids are ~10 GB-class at full-frame histogramming — keep the streaming path.
  • Either stage: min(ground_model, p8) inside wall corridor bands; validation via label-free ΔDEM raster + HAG band-flip census across the 0.20/0.30/0.42/0.78/2.0 m gates on non-bridge segments (AI3D-339 audit pattern), plus recall re-measure on the reference set; segment-033 bridge-guard regression test mandatory.

Gate: class-(c) misses collapse on the reference set; band-flip census shows no mass migration of pavement/lip points; suite green on battlebox.

Phase 4 — Wall dual-path + disagreement QC implement · ~2 days
  • Wall evidence = residue clusters (clean walls: bodies were 98.5–100 % captured) merged with the banded-cell channel (covers grazing-angle faces). Footing z from the surface sample, not residue bottom (footing bands measured 0–60 % removed — ambiguous by nature).
  • Kept∩wall-candidate flag: kept-as-ground points inside strong wall-candidate cells → annotate instance for review. Diagnostics showed this flag catches bridge artifacts (segment-135 wall 2 = overpass deck top, a wall-channel false positive the residue correctly ignored) as well as potentially climbed terrain — route flagged instances toward the bridge-artifact rejection rule first, banded-cell recovery second.
  • Disagreement QC into run_summary.json: removed∩HAG<0.2 m rate (lip erosion), kept∩candidate-cell rate (wall vanishing), removed-fraction outliers (vehicle-heavy records).

Gate: wall recall on 134/135 unchanged-or-better with no new FPs between edge lines (carriageway rejection rule still authoritative); QC fields present and sane across the reference set.

Phase 5 — Rollout & pipeline wiring ~1–2 days
  • Decide AML pipeline ordering: run tablecloth once upstream and pass masks/surfaces to both asphaltedge (cleaned) and guardrails (masks + surface) — one filter run, two consumers — vs on-demand inside guardrails. Default recommendation: upstream stage, cached like ACC LAS.
  • Full non-bridge A4/5 sweep on battlebox; final recall/precision report vs the Phase-0 baseline; visual QC round.
  • Wrap-up both repos (version bump, Nexus, Jira-tagged commits); PRs per phase merged in order.

Gate: headline number — per-length recall on the reference set — reported against the ≈50 % baseline, with FP judged acceptable via visual QC (no measurable ceiling).

Risks

RiskSeverityMitigation
Residue union imports vehicles/vegetation as candidates → FP growthhighCorridor + sanity band at ingestion; existing vehicle/carriageway rejects unchanged. Answered 2026-07-18 (Miro): the FP ceiling is unmeasurable — no ground truth exists to quantify a baseline + 10 % (or any numeric) ceiling against. Make FP as good as possible; judge via good visualizations checked visually (colored-PLY/rasterization overlays, or CloudCompare on battlebox). Adversarial tests in Phase 2 TDD still apply.
Miss taxonomy shows occlusion (class a) dominates → TCS can't reach the recall targethighPhase 0/1 gates exist precisely for this; occlusion-bridging parameters and multi-run fusion would become the follow-up plan instead.
SMRF surface climbs steep faces → footing/HAG bias near walls, wall heights wrongmedmin(smrf, p8) guard in wall corridors; wall-vanishing QC flag; band-flip census before enabling.
Per-record AABB surface mosaic seams (record-boundary dig)medsmrf_edge_pad_enabled=true (AI3D-345 fix, tested); cellwise-min overlap rule; seam-crossing test fixtures.
Reference-set tagging is subjective / driftsmedFreeze exemplars in-repo; double-tag 20 % sample; Opus tags reviewed by human once, then only re-run mechanically.
Battlebox/VPN availability; shared out-dir clobber; nexus creds for uvmedRetry policy in run scripts; per-segment out dirs (lesson from wall experiment); source /home/ai/.env before uv (lesson from setup agent).
Pipeline cost: TCS adds ~12 s/record + surface artifactslowMasks ~1–2 MB/record, surface grids modest; run once upstream, cache, share across consumers.
Self-referential ground truth inflates measured recall (same-cloud references were ~10 pp too forgiving on curbs)medBlinded-window protocol with double-labeled sample; locked test set; report both lenient and strict buffers.
Geoshift mismatch between frames (historic trap; per Miro 2026-07-18 the latest production — A1–3 on Azure, A4_5 on battlebox — carries corrected geo-shifts)lowVerify once on the reference set that wall/rail polylines overlay run3 points; keep the native station_range_m/mean_offset_m/side convention as belt-and-braces.
TCS defaults are lip-tuned (0.05 m gate, 3 m window) and unvalidated on >15 % embankmentsmedPhase-1 calibration grid before any production reliance; elev_scalar=1.25 already covers part of the slope gap.
Inherited feature quirks starve new scoring features (LAS return numbers unread; intensity 16-bit in npz vs 8-bit via ply; undocumented 43000 intensity cutoff)lowNo new intensity/echo gates in the recall path without first documenting which representation is read; the 43000 cutoff is not reused.

Open questions

  1. Where does “≈50 % detected” come from — which comparison/QC, which Abschnitt, per-instance or per-length? Defines the Phase-0 baseline and the target (proposal: ≥85 % per-length on non-bridge segments).
    Answered 2026-07-18 (Miro): it's Miro's visual observation, not a measured figure — no ground truth or QC comparison exists to trace it back to. The Phase-0 baseline has to be built visually, from scratch.
  2. Ground truth (partly answered by the vault): no client Bestand/asset inventory exists; step7_xml/abschnitt_4_5 is empty; the 367 w-beam-run audit + blinded-window protocol are the usable starting points. Remaining question: should recall be reported per Saferoad type taxonomy (ESP 4.0, EDSP 2.0, Super-Rail Eco, Eco-Safe — the classes the client counts)?
    Answered 2026-07-18 (Miro): ground truth is none — do not report per Saferoad taxonomy, there's nothing to support it. Evaluation is visual: a vision-capable agent inspects result overlays. Options: colored PLYs + rasterizations via 3dai.iolabs.pointcloud.3dsegmentation, or CloudCompare screenshots/videos on battlebox. If a visible rail is undetected, fix it.
  3. Answered (2026-07-18 diagnostics): segment-135 wall 2 is the deck top of an overpass crossing the highway (horizontal plane fit nz=1.0, planarity 0.02; wide slab at +4–4.5 m spanning the ROI with parapets and abutment portals; all four "walls" share station range 6802–6821 m = one overpass site; walls 0/1/3 are its upright abutment/wing faces). RGB is dead (constant 65535). The residue's blindness to wall 2 was correct behavior — the kept∩wall-candidate flag doubles as a bridge-artifact detector.
    Answered 2026-07-18 (Miro): confirmed — overpass bridge. Consistent with the standing no-bridge rule: it and its abutment/wing faces are a bridge-site artifact, out of scope for detection/tuning/QC, not reportable to the client under this plan.
  4. AML pipeline ordering: is an upstream tablecloth stage acceptable operationally (cache location, versioning), or must guardrails invoke it internally?
    Answered 2026-07-18 (Miro): upstream tablecloth stage approved — run once upstream, cache like ACC LAS, guardrails consumes the masks/surfaces.
  5. A1/A3 generalization: data reachable for the reference set? (RGB only live in A1; scan_angle dead in A3.)
    Answered 2026-07-18 (Miro): A1/A3 data is on Azure; download to D: locally, or preferably to battlebox (faster Azure access, better for heavy compute). Confirmed: RGB only in A1, no scan_angle in A3.
  6. FP ceiling: is baseline + 10 % FP length acceptable while recall is the priority, or stricter?
    Answered 2026-07-18 (Miro): unmeasurable — no ground truth to set a numeric ceiling against. Make FP as good as possible; judge via good visualizations checked visually.