#!/usr/bin/env python3
"""Fuse LAB E5 tracks with factory-calibrated K1 LiDAR observations."""

from __future__ import annotations

import argparse
import hashlib
import io
import json
import math
import os
import resource
import shutil
import subprocess
import tarfile
import time
from collections import Counter, defaultdict, deque
from collections.abc import Iterator
from contextlib import suppress
from dataclasses import dataclass
from datetime import UTC, datetime
from pathlib import Path
from typing import Any

import numpy as np
import numpy.typing as npt
import rerun as rr
from PIL import Image, ImageDraw, ImageFont
from rerun.components import FillMode

from k1link.compute import (
    validate_recorded_perception_epoch_result,
    validate_tracking_qualification_result,
)
from k1link.device_plugins.xgrids_k1.analyze.calibrated_overlay import (
    _load_calibration_snapshot,
)
from k1link.device_plugins.xgrids_k1.analyze.calibrated_projection import (
    Kb4ProjectionProfile,
    depth_colors,
    map_points_to_lidar,
    project_map_points_kb4,
)
from k1link.device_plugins.xgrids_k1.mqtt.capture import read_capture_clock_origin
from k1link.device_plugins.xgrids_k1.protocol.streams import (
    LioPointCloudFrame,
    LioPoseFrame,
    decode_lio_pcl,
    decode_lio_pose,
)
from k1link.device_plugins.xgrids_k1.viewer.replay import iter_replay_messages

PROFILE_SCHEMA = "missioncore.e6-tracking-lidar-profile/v1"
RESULT_SCHEMA = "missioncore.e6-tracked-lidar-fusion-result/v1"
IDENTITY_SCHEMA = "missioncore.e6-tracked-lidar-fusion-identity/v1"
FRAME_SCHEMA = "missioncore.e6-tracked-lidar-frame/v1"
PIPELINE_ID = "factory-kb4-tracked-box-semantic-lidar/v1"
MAX_INDEX_LINE_BYTES = 64 * 1024
MAX_MASK_MEMBER_BYTES = 4 * 1024 * 1024
IMAGE_WIDTH = 800
IMAGE_HEIGHT = 600

FloatArray = npt.NDArray[np.float64]


@dataclass(frozen=True, slots=True)
class CameraAnchor:
    frame_index: int
    source_frame_index: int
    host_session_seconds: float
    video_session_seconds: float


@dataclass(frozen=True, slots=True)
class LidarSample:
    point_session_seconds: float
    pose_session_seconds: float
    point_frame: LioPointCloudFrame
    pose_frame: LioPoseFrame


@dataclass(frozen=True, slots=True)
class Cuboid:
    center_map: tuple[float, float, float]
    half_size: tuple[float, float, float]
    quaternion_xyzw: tuple[float, float, float, float]


@dataclass(frozen=True, slots=True)
class TrackFusion:
    track_id: int
    label: str
    association_group: str
    score: float
    bbox_xyxy: tuple[float, float, float, float]
    candidate_points: int
    semantic_points: int
    clustered_points: int
    distance_p10_m: float | None
    distance_median_m: float | None
    distance_smoothed_m: float | None
    status: str
    cuboid: Cuboid | None
    source_indices: npt.NDArray[np.int64]


def _arguments() -> argparse.Namespace:
    parser = argparse.ArgumentParser()
    parser.add_argument("--job", type=Path, required=True)
    parser.add_argument("--tracking", type=Path, required=True)
    parser.add_argument("--semantic-result", type=Path, required=True)
    parser.add_argument("--session", type=Path, required=True)
    parser.add_argument("--calibration", type=Path, required=True)
    parser.add_argument("--profile", type=Path, required=True)
    parser.add_argument("--output-root", type=Path, required=True)
    parser.add_argument("--ffmpeg", type=Path, required=True)
    return parser.parse_args()


def _canonical_json(value: object) -> bytes:
    return json.dumps(
        value,
        ensure_ascii=False,
        sort_keys=True,
        separators=(",", ":"),
        allow_nan=False,
    ).encode()


def _sha256(path: Path) -> str:
    digest = hashlib.sha256()
    with path.open("rb") as stream:
        while chunk := stream.read(1024 * 1024):
            digest.update(chunk)
    return digest.hexdigest()


def _read_profile(path: Path) -> tuple[dict[str, Any], str]:
    resolved = path.resolve(strict=True)
    value = json.loads(resolved.read_text(encoding="utf-8"))
    if not isinstance(value, dict) or value.get("schema_version") != PROFILE_SCHEMA:
        raise RuntimeError("LAB E6 profile is invalid")
    source = value.get("source")
    temporal = value.get("temporal")
    association = value.get("association")
    presentation = value.get("presentation")
    inputs = value.get("inputs")
    if (
        not isinstance(source, dict)
        or source.get("source_id") != "sensor.camera.right"
        or source.get("calibration_slot") != "camera_1"
        or source.get("resolution") != [IMAGE_WIDTH, IMAGE_HEIGHT]
        or not isinstance(temporal, dict)
        or temporal.get("binding") != "nearest-host-arrival-best-effort"
        or not 0 < float(temporal.get("maximum_lidar_camera_delta_ms", 0)) <= 250
        or not 0 < float(temporal.get("maximum_pose_point_delta_ms", 0)) <= 250
        or not isinstance(association, dict)
        or not isinstance(presentation, dict)
        or not isinstance(inputs, dict)
    ):
        raise RuntimeError("LAB E6 profile contract changed")
    groups = {"person", "bicycle", "motorcycle", "vehicle"}
    semantic_ids = association.get("semantic_ids")
    minimum_support = association.get("minimum_support_points")
    spatial_radius = association.get("spatial_cluster_radius_m")
    maximum_extent = association.get("maximum_oriented_extent_m")
    if (
        not isinstance(semantic_ids, dict)
        or set(semantic_ids) != groups
        or any(
            not isinstance(values, list)
            or not values
            or any(not isinstance(item, int) or not 1 <= item <= 15 for item in values)
            for values in semantic_ids.values()
        )
        or not isinstance(minimum_support, dict)
        or set(minimum_support) != groups
        or any(
            not isinstance(value, int) or not 2 <= value <= 100
            for value in minimum_support.values()
        )
        or not isinstance(spatial_radius, dict)
        or set(spatial_radius) != groups
        or any(not 0 < float(value) <= 5 for value in spatial_radius.values())
        or not isinstance(maximum_extent, dict)
        or set(maximum_extent) != groups
        or any(
            not isinstance(values, list)
            or len(values) != 3
            or any(not 0 < float(value) <= 20 for value in values)
            for values in maximum_extent.values()
        )
        or not 0 < float(association.get("group_nms_iou_threshold", 0)) < 1
        or not 0 < float(association.get("maximum_distance_innovation_m", 0)) <= 20
        or not 0
        < float(association.get("maximum_distance_innovation_fraction", 0))
        <= 1
    ):
        raise RuntimeError("LAB E6 semantic/support policy changed")
    return value, _sha256(resolved)


def _read_tracking_frames(path: Path, expected: int, source_start: int) -> list[dict[str, Any]]:
    frames: list[dict[str, Any]] = []
    with path.open("r", encoding="utf-8") as stream:
        for frame_index, line in enumerate(stream):
            value = json.loads(line)
            if (
                not isinstance(value, dict)
                or value.get("frame_index") != frame_index
                or value.get("source_frame_index") != source_start + frame_index
                or not isinstance(value.get("tracks"), list)
            ):
                raise RuntimeError("LAB E5 tracking frame metadata changed")
            frames.append(value)
    if len(frames) != expected:
        raise RuntimeError("LAB E5 tracking frame metadata is incomplete")
    return frames


def _camera_anchors(
    index_path: Path,
    tracking_frames: list[dict[str, Any]],
    *,
    origin_monotonic_ns: int,
) -> list[CameraAnchor]:
    by_source = {int(item["source_frame_index"]): item for item in tracking_frames}
    source_start = min(by_source)
    source_end = max(by_source)
    anchors: list[CameraAnchor] = []
    with index_path.open("rb") as stream:
        for source_index in range(source_end + 1):
            line = stream.readline(MAX_INDEX_LINE_BYTES + 1)
            if not line or len(line) > MAX_INDEX_LINE_BYTES or not line.endswith(b"\n"):
                raise RuntimeError("camera index is incomplete")
            if source_index < source_start:
                continue
            value = json.loads(line)
            monotonic_ns = value.get("host_monotonic_ns") if isinstance(value, dict) else None
            frame = by_source.get(source_index)
            if (
                not isinstance(value, dict)
                or value.get("sequence") != source_index + 1
                or not isinstance(monotonic_ns, int)
                or monotonic_ns < origin_monotonic_ns
                or frame is None
            ):
                raise RuntimeError("camera anchor is invalid")
            anchors.append(
                CameraAnchor(
                    frame_index=int(frame["frame_index"]),
                    source_frame_index=source_index,
                    host_session_seconds=(monotonic_ns - origin_monotonic_ns) / 1e9,
                    video_session_seconds=float(frame["session_seconds"]),
                )
            )
    if len(anchors) != len(tracking_frames):
        raise RuntimeError("camera anchor selection changed")
    return anchors


def _lidar_samples(
    raw_path: Path,
    anchors: list[CameraAnchor],
    *,
    origin_monotonic_ns: int,
    maximum_lidar_camera_delta_s: float,
    maximum_pose_point_delta_s: float,
) -> Iterator[LidarSample | None]:
    messages = iter(iter_replay_messages(raw_path))
    pending = next(messages, None)
    points: deque[tuple[float, LioPointCloudFrame]] = deque()
    poses: deque[tuple[float, LioPoseFrame]] = deque()
    window = max(maximum_lidar_camera_delta_s, maximum_pose_point_delta_s)

    def message_time(message: Any) -> float:
        monotonic_ns = message.received_monotonic_ns
        if not isinstance(monotonic_ns, int) or monotonic_ns < origin_monotonic_ns:
            raise RuntimeError("MQTT replay message has no compatible monotonic time")
        return (monotonic_ns - origin_monotonic_ns) / 1e9

    for anchor in anchors:
        target = anchor.host_session_seconds
        while pending is not None and message_time(pending) <= target + window:
            timestamp = message_time(pending)
            if timestamp >= target - window:
                if pending.topic.endswith("/lio_pcl"):
                    points.append((timestamp, decode_lio_pcl(pending.payload)))
                elif pending.topic.endswith("/lio_pose"):
                    poses.append((timestamp, decode_lio_pose(pending.payload)))
            pending = next(messages, None)
        while points and points[0][0] < target - window:
            points.popleft()
        while poses and poses[0][0] < target - window:
            poses.popleft()
        point_candidates = [
            item for item in points if abs(item[0] - target) <= maximum_lidar_camera_delta_s
        ]
        if not point_candidates:
            yield None
            continue
        point_time, point_frame = min(point_candidates, key=lambda item: abs(item[0] - target))
        pose_candidates = [
            item
            for item in poses
            if abs(item[0] - point_time) <= maximum_pose_point_delta_s
        ]
        if not pose_candidates:
            yield None
            continue
        pose_time, pose_frame = min(pose_candidates, key=lambda item: abs(item[0] - point_time))
        yield LidarSample(point_time, pose_time, point_frame, pose_frame)


def _extract_semantic_masks(
    archive: Path,
    destination: Path,
    source_start: int,
    source_end: int,
) -> None:
    expected = {
        f"semantic-masks/frame-{source_index + 1:06d}.png"
        for source_index in range(source_start, source_end + 1)
    }
    found: set[str] = set()
    with tarfile.open(archive, mode="r:gz") as source:
        for member in source:
            name = member.name.replace("\\", "/").removeprefix("./")
            if name not in expected:
                continue
            if (
                member.issym()
                or member.islnk()
                or not member.isfile()
                or not 0 < member.size <= MAX_MASK_MEMBER_BYTES
            ):
                raise RuntimeError("semantic mask archive member is unsafe")
            payload = source.extractfile(member)
            if payload is None:
                raise RuntimeError("semantic mask archive member is unavailable")
            target = destination / Path(name).name
            with target.open("xb") as sink:
                shutil.copyfileobj(payload, sink, length=1024 * 1024)
            if target.stat().st_size != member.size:
                raise RuntimeError("semantic mask archive member was truncated")
            found.add(name)
    if found != expected:
        raise RuntimeError("semantic mask archive does not contain the LAB E6 clip")


def _visible_projection_indices(
    pixels_xy: FloatArray,
    depths_m: FloatArray,
    *,
    width: int = IMAGE_WIDTH,
    height: int = IMAGE_HEIGHT,
) -> npt.NDArray[np.int64]:
    if pixels_xy.shape != (depths_m.shape[0], 2):
        raise ValueError("projection arrays are inconsistent")
    if depths_m.size == 0:
        return np.empty((0,), dtype=np.int64)
    pixel_x = np.clip(np.rint(pixels_xy[:, 0]).astype(np.int64), 0, width - 1)
    pixel_y = np.clip(np.rint(pixels_xy[:, 1]).astype(np.int64), 0, height - 1)
    keys = pixel_y * width + pixel_x
    order = np.lexsort((depths_m, keys))
    ordered_keys = keys[order]
    first = np.concatenate(([True], ordered_keys[1:] != ordered_keys[:-1]))
    return np.sort(order[first].astype(np.int64, copy=False))


def _association_group(label: str, vehicle_labels: set[str]) -> str:
    return "vehicle" if label in vehicle_labels else label


def _box_iou(
    one: tuple[float, float, float, float],
    two: tuple[float, float, float, float],
) -> float:
    x1 = max(one[0], two[0])
    y1 = max(one[1], two[1])
    x2 = min(one[2], two[2])
    y2 = min(one[3], two[3])
    intersection = max(0.0, x2 - x1) * max(0.0, y2 - y1)
    one_area = max(0.0, one[2] - one[0]) * max(0.0, one[3] - one[1])
    two_area = max(0.0, two[2] - two[0]) * max(0.0, two[3] - two[1])
    union = one_area + two_area - intersection
    return 0.0 if union <= 0 else intersection / union


def _suppress_duplicate_vehicle_tracks(
    tracks: list[dict[str, Any]],
    *,
    vehicle_labels: set[str],
    iou_threshold: float,
) -> list[dict[str, Any]]:
    accepted: list[dict[str, Any]] = []
    for track in sorted(tracks, key=lambda item: float(item["score"]), reverse=True):
        label = str(track["label"])
        bbox = tuple(float(value) for value in track["bbox_xyxy"])
        if label in vehicle_labels and any(
            str(other["label"]) in vehicle_labels
            and _box_iou(bbox, tuple(float(value) for value in other["bbox_xyxy"]))
            > iou_threshold
            for other in accepted
        ):
            continue
        accepted.append(track)
    return sorted(accepted, key=lambda item: int(item["track_id"]))


def _box_candidates(
    bbox_xyxy: tuple[float, float, float, float],
    pixels_xy: FloatArray,
    inset: dict[str, Any],
) -> npt.NDArray[np.int64]:
    x1, y1, x2, y2 = bbox_xyxy
    width = x2 - x1
    height = y2 - y1
    x1 += width * float(inset["horizontal_fraction"])
    x2 -= width * float(inset["horizontal_fraction"])
    y1 += height * float(inset["top_fraction"])
    y2 -= height * float(inset["bottom_fraction"])
    inside = (
        (pixels_xy[:, 0] >= x1)
        & (pixels_xy[:, 0] < x2)
        & (pixels_xy[:, 1] >= y1)
        & (pixels_xy[:, 1] < y2)
    )
    return np.flatnonzero(inside).astype(np.int64)


def _depth_cluster(
    indices: npt.NDArray[np.int64],
    depths: FloatArray,
    *,
    minimum_gap_m: float,
    gap_fraction: float,
) -> npt.NDArray[np.int64]:
    if indices.size < 2:
        return indices
    ordered = indices[np.argsort(depths[indices])]
    groups: list[npt.NDArray[np.int64]] = []
    start = 0
    for offset, gap in enumerate(np.diff(depths[ordered]), start=1):
        threshold = max(minimum_gap_m, gap_fraction * float(depths[ordered[offset - 1]]))
        if float(gap) > threshold:
            groups.append(ordered[start:offset])
            start = offset
    groups.append(ordered[start:])
    return min(groups, key=lambda group: (-int(group.size), float(np.median(depths[group]))))


def _spatial_cluster(
    source_indices: npt.NDArray[np.int64],
    points_lidar: FloatArray,
    *,
    radius_m: float,
) -> npt.NDArray[np.int64]:
    if source_indices.size < 2:
        return source_indices
    points = points_lidar[source_indices]
    squared = np.sum((points[:, None, :] - points[None, :, :]) ** 2, axis=2)
    adjacent = squared <= radius_m * radius_m
    unseen = set(range(source_indices.size))
    groups: list[list[int]] = []
    while unseen:
        seed = unseen.pop()
        group = [seed]
        pending = [seed]
        while pending:
            current = pending.pop()
            neighbors = [index for index in tuple(unseen) if adjacent[current, index]]
            for index in neighbors:
                unseen.remove(index)
                pending.append(index)
                group.append(index)
        groups.append(group)
    selected = min(
        groups,
        key=lambda group: (
            -len(group),
            float(np.median(np.linalg.norm(points[group], axis=1))),
        ),
    )
    return source_indices[np.asarray(selected, dtype=np.int64)]


def _cuboid(
    points_map: FloatArray,
    *,
    minimum_extent: float,
    maximum_span: float,
    maximum_oriented_extent: tuple[float, float, float],
) -> Cuboid | None:
    if points_map.shape[0] < 2:
        return None
    xy = points_map[:, :2]
    centered = xy - np.median(xy, axis=0)
    covariance = centered.T @ centered / max(1, centered.shape[0] - 1)
    eigenvalues, eigenvectors = np.linalg.eigh(covariance)
    axis = eigenvectors[:, int(np.argmax(eigenvalues))]
    yaw = math.atan2(float(axis[1]), float(axis[0]))
    forward = np.asarray([math.cos(yaw), math.sin(yaw)])
    side = np.asarray([-math.sin(yaw), math.cos(yaw)])
    local_xy = np.column_stack((xy @ forward, xy @ side))
    lower_xy = np.percentile(local_xy, 5.0, axis=0)
    upper_xy = np.percentile(local_xy, 95.0, axis=0)
    lower_z, upper_z = np.percentile(points_map[:, 2], [5.0, 95.0])
    spans = np.asarray(
        [upper_xy[0] - lower_xy[0], upper_xy[1] - lower_xy[1], upper_z - lower_z]
    )
    if (
        not np.isfinite(spans).all()
        or np.any(spans > maximum_span)
        or np.any(spans > np.asarray(maximum_oriented_extent, dtype=np.float64))
    ):
        return None
    sizes = np.maximum(spans, minimum_extent)
    local_center = (lower_xy + upper_xy) * 0.5
    center_xy = local_center[0] * forward + local_center[1] * side
    center_z = (float(lower_z) + float(upper_z)) * 0.5
    return Cuboid(
        center_map=(float(center_xy[0]), float(center_xy[1]), center_z),
        half_size=tuple(float(value) for value in sizes * 0.5),
        quaternion_xyzw=(0.0, 0.0, math.sin(yaw * 0.5), math.cos(yaw * 0.5)),
    )


def _track_color(track_id: int, association_group: str, *, alpha: int = 255) -> tuple[int, ...]:
    digest = hashlib.sha256(f"e6:{association_group}:{track_id}".encode()).digest()
    rgb = tuple(64 + value % 176 for value in digest[:3])
    return (*rgb, alpha) if alpha != 255 else rgb


def _fuse_tracks(
    *,
    tracks: list[dict[str, Any]],
    semantic_map: npt.NDArray[np.uint8],
    pixels_xy: FloatArray,
    depths_m: FloatArray,
    projected_source_indices: npt.NDArray[np.int64],
    points_map: FloatArray,
    points_lidar: FloatArray,
    profile: dict[str, Any],
    distance_history: dict[int, deque[float]],
) -> tuple[TrackFusion, ...]:
    association = profile["association"]
    vehicle_labels = set(str(value) for value in association["vehicle_labels"])
    tracks = _suppress_duplicate_vehicle_tracks(
        tracks,
        vehicle_labels=vehicle_labels,
        iou_threshold=float(association["group_nms_iou_threshold"]),
    )
    pixel_x = np.clip(np.rint(pixels_xy[:, 0]).astype(np.int64), 0, IMAGE_WIDTH - 1)
    pixel_y = np.clip(np.rint(pixels_xy[:, 1]).astype(np.int64), 0, IMAGE_HEIGHT - 1)
    sampled_semantic = semantic_map[pixel_y, pixel_x]
    result: list[TrackFusion] = []
    for track in tracks:
        track_id = int(track["track_id"])
        label = str(track["label"])
        group = _association_group(label, vehicle_labels)
        bbox = tuple(float(value) for value in track["bbox_xyxy"])
        candidates = _box_candidates(bbox, pixels_xy, association["box_inset"])
        semantic_allowed = np.asarray(association["semantic_ids"][group], dtype=np.uint8)
        compatible = candidates[np.isin(sampled_semantic[candidates], semantic_allowed)]
        clustered = _depth_cluster(
            compatible,
            depths_m,
            minimum_gap_m=float(association["depth_cluster_minimum_gap_m"]),
            gap_fraction=float(association["depth_cluster_gap_fraction"]),
        )
        source_indices = _spatial_cluster(
            projected_source_indices[clustered],
            points_lidar,
            radius_m=float(association["spatial_cluster_radius_m"][group]),
        )
        ranges = np.linalg.norm(points_lidar[source_indices], axis=1)
        p10 = None if ranges.size == 0 else float(np.percentile(ranges, 10.0))
        median = None if ranges.size == 0 else float(np.median(ranges))
        minimum_support = int(association["minimum_support_points"][group])
        cuboid = None
        if compatible.size == 0:
            status = "rejected-no-semantic-lidar-support"
        elif source_indices.size < minimum_support:
            status = f"rejected-fewer-than-{minimum_support}-clustered-points"
        else:
            cuboid = _cuboid(
                points_map[source_indices],
                minimum_extent=float(association["minimum_cuboid_extent_m"]),
                maximum_span=float(association["maximum_cuboid_span_m"]),
                maximum_oriented_extent=tuple(
                    float(value)
                    for value in association["maximum_oriented_extent_m"][group]
                ),
            )
            status = (
                "accepted-point-supported-oriented-p05-p95"
                if cuboid is not None
                else "rejected-implausible-cuboid"
            )
        smoothed = None
        if cuboid is not None and median is not None:
            history = distance_history[track_id]
            if history:
                reference = float(np.median(np.asarray(history, dtype=np.float64)))
                maximum_innovation = max(
                    float(association["maximum_distance_innovation_m"]),
                    reference
                    * float(association["maximum_distance_innovation_fraction"]),
                )
                if abs(median - reference) > maximum_innovation:
                    cuboid = None
                    status = "rejected-distance-innovation"
            if cuboid is not None:
                history.append(median)
                smoothed = float(np.median(np.asarray(history, dtype=np.float64)))
        result.append(
            TrackFusion(
                track_id=track_id,
                label=label,
                association_group=group,
                score=float(track["score"]),
                bbox_xyxy=bbox,
                candidate_points=int(candidates.size),
                semantic_points=int(compatible.size),
                clustered_points=int(source_indices.size),
                distance_p10_m=p10,
                distance_median_m=median,
                distance_smoothed_m=smoothed,
                status=status,
                cuboid=cuboid,
                source_indices=source_indices,
            )
        )
    return tuple(result)


def _read_raw_frame(stream: Any) -> npt.NDArray[np.uint8]:
    expected = IMAGE_WIDTH * IMAGE_HEIGHT * 3
    payload = stream.read(expected)
    if len(payload) != expected:
        raise RuntimeError("tracking video decoded fewer frames than declared")
    return np.frombuffer(payload, dtype=np.uint8).reshape((IMAGE_HEIGHT, IMAGE_WIDTH, 3)).copy()


def _overlay(
    image_rgb: npt.NDArray[np.uint8],
    projected_pixels: FloatArray,
    projected_depths: FloatArray,
    projected_source_indices: npt.NDArray[np.int64],
    fusions: tuple[TrackFusion, ...],
) -> npt.NDArray[np.uint8]:
    canvas = Image.fromarray(image_rgb).convert("RGBA")
    draw = ImageDraw.Draw(canvas, "RGBA")
    for (u, v), color in zip(projected_pixels, depth_colors(projected_depths), strict=True):
        red, green, blue = (int(value) for value in color)
        draw.ellipse((u - 1.2, v - 1.2, u + 1.2, v + 1.2), fill=(red, green, blue, 155))
    for fusion in fusions:
        x1, y1, _x2, y2 = fusion.bbox_xyxy
        color = _track_color(fusion.track_id, fusion.association_group)
        if fusion.cuboid is None:
            text = "depth —"
            alpha = 150
        else:
            text = f"{fusion.distance_smoothed_m:.1f}m · {fusion.clustered_points}pts"
            alpha = 235
            for u, v in projected_pixels[
                np.isin(projected_source_indices, fusion.source_indices)
            ]:
                draw.ellipse(
                    (u - 3.0, v - 3.0, u + 3.0, v + 3.0),
                    fill=(*color, 245),
                    outline=(0, 0, 0, 220),
                    width=1,
                )
        badge_y = min(IMAGE_HEIGHT - 17, max(0, int(y2) + 2))
        badge_x = min(IMAGE_WIDTH - 110, max(0, int(x1)))
        draw.rounded_rectangle(
            (badge_x, badge_y, badge_x + 108, badge_y + 15),
            radius=3,
            fill=(0, 0, 0, 150),
            outline=(*color, alpha),
            width=1,
        )
        draw.text(
            (badge_x + 3, badge_y + 1),
            f"#{fusion.track_id} {text}",
            font=ImageFont.load_default(),
            fill=(255, 255, 255, alpha),
        )
    return np.asarray(canvas.convert("RGB"), dtype=np.uint8)


def _object_document(item: TrackFusion) -> dict[str, Any]:
    return {
        "track_id": item.track_id,
        "label": item.label,
        "association_group": item.association_group,
        "score": round(item.score, 9),
        "bbox_xyxy": [round(value, 6) for value in item.bbox_xyxy],
        "candidate_projected_points": item.candidate_points,
        "semantic_compatible_points": item.semantic_points,
        "clustered_points": item.clustered_points,
        "distance_p10_m": item.distance_p10_m,
        "distance_median_m": item.distance_median_m,
        "distance_smoothed_m": item.distance_smoothed_m,
        "cuboid_status": item.status,
        "cuboid_center_map": None if item.cuboid is None else item.cuboid.center_map,
        "cuboid_half_size": None if item.cuboid is None else item.cuboid.half_size,
        "cuboid_quaternion_xyzw": (
            None if item.cuboid is None else item.cuboid.quaternion_xyzw
        ),
    }


def _contact_sheet(images: list[Image.Image], columns: int) -> Image.Image:
    rows = math.ceil(len(images) / columns)
    sheet = Image.new("RGB", (IMAGE_WIDTH * columns, IMAGE_HEIGHT * rows), "black")
    for index, image in enumerate(images):
        sheet.paste(image, ((index % columns) * IMAGE_WIDTH, (index // columns) * IMAGE_HEIGHT))
    return sheet


def _artifact(path: Path, kind: str, media_type: str, schema: str | None = None) -> dict[str, Any]:
    value: dict[str, Any] = {
        "kind": kind,
        "path": path.name,
        "media_type": media_type,
        "byte_length": path.stat().st_size,
        "sha256": _sha256(path),
    }
    if schema is not None:
        value["schema_version"] = schema
    return value


def main() -> int:
    args = _arguments()
    started = time.perf_counter()
    usage_before = resource.getrusage(resource.RUSAGE_SELF)
    profile, profile_sha256 = _read_profile(args.profile)
    tracking = validate_tracking_qualification_result(args.job, args.tracking)
    semantic = validate_recorded_perception_epoch_result(args.job, args.semantic_result)
    if (
        tracking.result_id != profile["inputs"]["tracking_result_id"]
        or semantic.result_id != profile["inputs"]["semantic_result_id"]
        or tracking.job.input_sha256 != semantic.job.input_sha256
        or semantic.calibration_sha256 != profile["source"]["calibration_sha256"]
        or semantic.calibration_slot != profile["source"]["calibration_slot"]
        or tracking.job.source_id != profile["source"]["source_id"]
    ):
        raise RuntimeError("LAB E6 input binding changed")
    session = args.session.resolve(strict=True)
    if session.name != tracking.job.session_id:
        raise RuntimeError("LAB E6 session does not match the tracking result")
    calibration, calibration_sha256 = _load_calibration_snapshot(
        args.calibration.resolve(strict=True)
    )
    if calibration_sha256 != semantic.calibration_sha256:
        raise RuntimeError("LAB E6 calibration generation changed")
    projection_profile = Kb4ProjectionProfile.from_factory_calibration(
        calibration, tracking.job.source_id
    )
    ffmpeg = args.ffmpeg.resolve(strict=True)
    if not ffmpeg.is_file():
        raise RuntimeError("ffmpeg is unavailable")
    tracking_frames = _read_tracking_frames(
        tracking.artifact("tracking-frame-metadata").path,
        tracking.frame_count,
        tracking.source_start_frame_index,
    )
    capture_root = session / "captures" / "mqtt_live"
    origin = read_capture_clock_origin(capture_root / "mqtt.timeline.origin.json")
    epoch_root = (
        tracking.job.job_root
        / "input"
        / "camera"
        / tracking.job.source_id
        / f"epoch-{tracking.job.codec_epoch}"
    )
    anchors = _camera_anchors(
        epoch_root / "index.jsonl",
        tracking_frames,
        origin_monotonic_ns=origin.started_monotonic_ns,
    )
    identity = {
        "schema_version": IDENTITY_SCHEMA,
        "job_id": tracking.job.job_id,
        "input_sha256": tracking.job.input_sha256,
        "tracking_result_id": tracking.result_id,
        "semantic_result_id": semantic.result_id,
        "calibration_sha256": calibration_sha256,
        "camera_slot": semantic.calibration_slot,
        "clip": {
            "source_start_frame_index": tracking.source_start_frame_index,
            "source_end_frame_index": tracking.source_end_frame_index,
            "clip_frame_count": tracking.frame_count,
            "timeline_start_seconds": tracking.timeline_start_seconds,
            "timeline_end_seconds": tracking.timeline_end_seconds,
        },
        "configuration": profile,
        "profile_sha256": profile_sha256,
        "producer_sha256": _sha256(Path(__file__).resolve(strict=True)),
        "pipeline": PIPELINE_ID,
    }
    identity_sha256 = hashlib.sha256(_canonical_json(identity)).hexdigest()
    result_id = f"e6-fusion-{identity_sha256}"
    parent = args.output_root.resolve()
    parent.mkdir(mode=0o700, parents=True, exist_ok=True)
    output = parent / result_id
    if output.exists():
        print(json.dumps({"result_id": result_id, "output": str(output), "reused": True}))
        return 0
    staging = parent / f".{result_id}.{os.getpid()}.incomplete"
    staging.mkdir(mode=0o700, exist_ok=False)
    masks_root = staging / "semantic-masks"
    masks_root.mkdir(mode=0o700)
    overlay_path = staging / "fusion-overlay.mp4"
    rrd_path = staging / "fusion.rrd"
    decoder: subprocess.Popen[bytes] | None = None
    encoder: subprocess.Popen[bytes] | None = None
    recording: rr.RecordingStream | None = None
    try:
        _extract_semantic_masks(
            semantic.artifact("panoptic-mask-archive").path,
            masks_root,
            tracking.source_start_frame_index,
            tracking.source_end_frame_index,
        )
        frame_duration = (
            tracking.timeline_end_seconds - tracking.timeline_start_seconds
        ) / (tracking.frame_count - 1)
        frame_rate = 1.0 / frame_duration
        decoder = subprocess.Popen(
            [
                str(ffmpeg), "-hide_banner", "-loglevel", "error", "-i",
                str(tracking.artifact("tracking-overlay-video").path),
                "-f", "rawvideo", "-pix_fmt", "rgb24", "pipe:1",
            ],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        encoder = subprocess.Popen(
            [
                str(ffmpeg), "-hide_banner", "-loglevel", "error", "-y",
                "-f", "rawvideo", "-pix_fmt", "rgb24", "-s",
                f"{IMAGE_WIDTH}x{IMAGE_HEIGHT}", "-framerate", f"{frame_rate:.12f}",
                "-i", "pipe:0", "-an", "-c:v", "libx264", "-preset", "medium",
                "-crf", str(profile["presentation"]["overlay_crf"]),
                "-pix_fmt", "yuv420p", "-movflags", "+faststart", str(overlay_path),
            ],
            stdin=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        if decoder.stdout is None or encoder.stdin is None:
            raise RuntimeError("ffmpeg pipes are unavailable")
        recording = rr.RecordingStream("nodedc_mission_core_e6", recording_id=result_id)
        recording.set_sinks(rr.FileSink(rrd_path, write_footer=True))
        recording.log("/world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True)
        recording.log(
            "/world/perception/contract",
            rr.TextDocument(
                "LAB E6 recorded qualification: factory KB4 projection, <=100 ms host-arrival "
                "gate, nearest-pixel depth buffer, E4 semantic support and E5 track IDs. "
                "Distances/cuboids are diagnostic, not ground truth or safety accepted."
            ),
            static=True,
        )
        frame_times_ns: list[int] = []
        cloud_offsets = [0]
        cloud_arrays: list[npt.NDArray[np.float32]] = []
        support_offsets = [0]
        support_arrays: list[npt.NDArray[np.float32]] = []
        support_color_arrays: list[npt.NDArray[np.uint8]] = []
        box_offsets = [0]
        box_centers: list[tuple[float, float, float]] = []
        box_half_sizes: list[tuple[float, float, float]] = []
        box_quaternions: list[tuple[float, float, float, float]] = []
        box_colors: list[tuple[int, int, int, int]] = []
        box_track_ids: list[int] = []
        box_distances: list[float] = []
        box_support_counts: list[int] = []
        box_labels: list[str] = []
        frame_reports: list[dict[str, Any]] = []
        rejection_counts: Counter[str] = Counter()
        fused_frames = 0
        accepted_cuboids = 0
        track_ids_with_depth: set[int] = set()
        sync_deltas: list[float] = []
        pose_deltas: list[float] = []
        history_length = int(profile["presentation"]["distance_history_frames"])
        distance_history: dict[int, deque[float]] = defaultdict(
            lambda: deque(maxlen=history_length)
        )
        sample_indices = {
            round(value)
            for value in np.linspace(
                0,
                tracking.frame_count - 1,
                int(profile["presentation"]["contact_sheet_frames"]),
            )
        }
        contact_images: list[Image.Image] = []
        maximum_lidar_delta_s = (
            float(profile["temporal"]["maximum_lidar_camera_delta_ms"]) / 1000.0
        )
        maximum_pose_delta_s = (
            float(profile["temporal"]["maximum_pose_point_delta_ms"]) / 1000.0
        )
        samples = _lidar_samples(
            capture_root / "mqtt.raw.k1mqtt",
            anchors,
            origin_monotonic_ns=origin.started_monotonic_ns,
            maximum_lidar_camera_delta_s=maximum_lidar_delta_s,
            maximum_pose_point_delta_s=maximum_pose_delta_s,
        )
        for frame_index, (anchor, sample, tracking_frame) in enumerate(
            zip(anchors, samples, tracking_frames, strict=True)
        ):
            image_rgb = _read_raw_frame(decoder.stdout)
            frame_times_ns.append(round(anchor.video_session_seconds * 1e9))
            recording.set_time(
                "session_time", duration=np.timedelta64(frame_times_ns[-1], "ns")
            )
            if sample is None:
                overlay = _overlay(
                    image_rgb,
                    np.empty((0, 2), dtype=np.float64),
                    np.empty((0,), dtype=np.float64),
                    np.empty((0,), dtype=np.int64),
                    (),
                )
                cloud_arrays.append(np.empty((0, 3), dtype=np.float32))
                cloud_offsets.append(cloud_offsets[-1])
                support_arrays.append(np.empty((0, 3), dtype=np.float32))
                support_color_arrays.append(np.empty((0, 3), dtype=np.uint8))
                support_offsets.append(support_offsets[-1])
                box_offsets.append(box_offsets[-1])
                recording.log("/world/lidar", rr.Clear(recursive=False))
                recording.log("/world/perception/support", rr.Clear(recursive=False))
                recording.log("/world/perception/boxes3d", rr.Clear(recursive=False))
                frame_reports.append(
                    {
                        "schema_version": FRAME_SCHEMA,
                        "frame_index": frame_index,
                        "source_frame_index": anchor.source_frame_index,
                        "session_seconds": anchor.video_session_seconds,
                        "state": "depth-unavailable-sync-gate",
                        "projected_points": 0,
                        "accepted_cuboids": 0,
                        "objects": [],
                    }
                )
            else:
                fused_frames += 1
                lidar_delta_ms = (sample.point_session_seconds - anchor.host_session_seconds) * 1000
                pose_delta_ms = (sample.pose_session_seconds - sample.point_session_seconds) * 1000
                sync_deltas.append(lidar_delta_ms)
                pose_deltas.append(pose_delta_ms)
                points_map = np.asarray(
                    [
                        point.scaled_xyz(sample.point_frame.header.scaler)
                        for point in sample.point_frame.points
                    ],
                    dtype=np.float64,
                )
                points_lidar = map_points_to_lidar(
                    points_map,
                    position_map_xyz=sample.pose_frame.position_xyz,
                    orientation_map_from_lidar_xyzw=sample.pose_frame.orientation_xyzw,
                )
                projected = project_map_points_kb4(
                    points_map,
                    position_map_xyz=sample.pose_frame.position_xyz,
                    orientation_map_from_lidar_xyzw=sample.pose_frame.orientation_xyzw,
                    profile=projection_profile,
                )
                visible = _visible_projection_indices(projected.pixels_xy, projected.depths_m)
                pixels = projected.pixels_xy[visible]
                depths = projected.depths_m[visible]
                source_indices = projected.source_indices[visible]
                with Image.open(
                    masks_root / f"frame-{anchor.source_frame_index + 1:06d}.png"
                ) as opened:
                    semantic_map = np.asarray(opened, dtype=np.uint8).copy()
                if semantic_map.shape != (IMAGE_HEIGHT, IMAGE_WIDTH):
                    raise RuntimeError("semantic mask dimensions changed")
                fusions = _fuse_tracks(
                    tracks=tracking_frame["tracks"],
                    semantic_map=semantic_map,
                    pixels_xy=pixels,
                    depths_m=depths,
                    projected_source_indices=source_indices,
                    points_map=points_map,
                    points_lidar=points_lidar,
                    profile=profile,
                    distance_history=distance_history,
                )
                overlay = _overlay(image_rgb, pixels, depths, source_indices, fusions)
                cloud = points_map.astype(np.float32)
                cloud_arrays.append(cloud)
                cloud_offsets.append(cloud_offsets[-1] + cloud.shape[0])
                recording.log(
                    "/world/lidar",
                    rr.Points3D(
                        cloud,
                        colors=np.tile(
                            np.asarray([[145, 145, 145]], dtype=np.uint8),
                            (cloud.shape[0], 1),
                        ),
                        radii=rr.Radius.ui_points(float(profile["presentation"]["point_radius_ui"])),
                    ),
                )
                accepted = [item for item in fusions if item.cuboid is not None]
                frame_support: list[npt.NDArray[np.float32]] = []
                frame_support_colors: list[npt.NDArray[np.uint8]] = []
                frame_centers: list[tuple[float, float, float]] = []
                frame_half_sizes: list[tuple[float, float, float]] = []
                frame_quaternions: list[tuple[float, float, float, float]] = []
                frame_colors: list[tuple[int, int, int, int]] = []
                frame_labels: list[str] = []
                for item in fusions:
                    rejection_counts[item.status] += 1
                    if item.cuboid is None:
                        continue
                    accepted_cuboids += 1
                    track_ids_with_depth.add(item.track_id)
                    color = _track_color(item.track_id, item.association_group)
                    rgba = (*color, 88)
                    support_points = points_map[item.source_indices].astype(np.float32)
                    frame_support.append(support_points)
                    frame_support_colors.append(
                        np.tile(np.asarray([color], dtype=np.uint8), (support_points.shape[0], 1))
                    )
                    frame_centers.append(item.cuboid.center_map)
                    frame_half_sizes.append(item.cuboid.half_size)
                    frame_quaternions.append(item.cuboid.quaternion_xyzw)
                    frame_colors.append(rgba)
                    label = (
                        f"{item.association_group} #{item.track_id} · "
                        f"{item.distance_smoothed_m:.1f} m · {item.clustered_points} pts"
                    )
                    frame_labels.append(label)
                    box_centers.append(item.cuboid.center_map)
                    box_half_sizes.append(item.cuboid.half_size)
                    box_quaternions.append(item.cuboid.quaternion_xyzw)
                    box_colors.append(rgba)
                    box_track_ids.append(item.track_id)
                    box_distances.append(float(item.distance_smoothed_m))
                    box_support_counts.append(item.clustered_points)
                    box_labels.append(label)
                if frame_support:
                    support = np.concatenate(frame_support)
                    support_colors = np.concatenate(frame_support_colors)
                    recording.log(
                        "/world/perception/support",
                        rr.Points3D(
                            support,
                            colors=support_colors,
                            radii=rr.Radius.ui_points(
                                float(profile["presentation"]["support_radius_ui"])
                            ),
                        ),
                    )
                else:
                    support = np.empty((0, 3), dtype=np.float32)
                    support_colors = np.empty((0, 3), dtype=np.uint8)
                    recording.log("/world/perception/support", rr.Clear(recursive=False))
                support_arrays.append(support)
                support_color_arrays.append(support_colors)
                support_offsets.append(support_offsets[-1] + support.shape[0])
                if accepted:
                    recording.log(
                        "/world/perception/boxes3d",
                        rr.Boxes3D(
                            centers=np.asarray(frame_centers, dtype=np.float32),
                            half_sizes=np.asarray(frame_half_sizes, dtype=np.float32),
                            quaternions=np.asarray(frame_quaternions, dtype=np.float32),
                            colors=np.asarray(frame_colors, dtype=np.uint8),
                            labels=frame_labels,
                            fill_mode=FillMode.Solid,
                            show_labels=True,
                        ),
                    )
                else:
                    recording.log("/world/perception/boxes3d", rr.Clear(recursive=False))
                box_offsets.append(box_offsets[-1] + len(accepted))
                frame_reports.append(
                    {
                        "schema_version": FRAME_SCHEMA,
                        "frame_index": frame_index,
                        "source_frame_index": anchor.source_frame_index,
                        "session_seconds": anchor.video_session_seconds,
                        "state": "fused",
                        "lidar_camera_delta_ms": round(lidar_delta_ms, 6),
                        "pose_point_delta_ms": round(pose_delta_ms, 6),
                        "source_points": int(points_map.shape[0]),
                        "projected_points_before_depth_buffer": projected.projected_point_count,
                        "projected_points": int(pixels.shape[0]),
                        "accepted_cuboids": len(accepted),
                        "objects": [_object_document(item) for item in fusions],
                    }
                )
            encoder.stdin.write(overlay.tobytes())
            jpeg = io.BytesIO()
            Image.fromarray(overlay).save(
                jpeg,
                format="JPEG",
                quality=int(profile["presentation"]["jpeg_quality"]),
                optimize=True,
            )
            recording.log(
                "/camera/tracking_depth",
                rr.EncodedImage(contents=jpeg.getvalue(), media_type="image/jpeg"),
            )
            if frame_index in sample_indices:
                contact_images.append(Image.fromarray(overlay).copy())
            if (frame_index + 1) % 100 == 0 or frame_index + 1 == tracking.frame_count:
                print(
                    json.dumps(
                        {
                            "phase": "e6-fusion",
                            "frames": frame_index + 1,
                            "total": tracking.frame_count,
                            "fused_frames": fused_frames,
                            "accepted_cuboids": accepted_cuboids,
                        }
                    ),
                    flush=True,
                )
        if decoder.stdout.read(1):
            raise RuntimeError("tracking video contains undeclared trailing frames")
        encoder.stdin.close()
        decoder_code = decoder.wait(timeout=60)
        encoder_code = encoder.wait(timeout=120)
        if decoder_code != 0 or encoder_code != 0:
            decoder_error = b"" if decoder.stderr is None else decoder.stderr.read()
            encoder_error = b"" if encoder.stderr is None else encoder.stderr.read()
            raise RuntimeError(
                "ffmpeg failed: "
                f"decoder={decoder_error[-2000:]!r}, encoder={encoder_error[-2000:]!r}"
            )
        recording.disconnect()
        recording = None
        arrays_path = staging / "fusion.npz"
        np.savez_compressed(
            arrays_path,
            frame_times_ns=np.asarray(frame_times_ns, dtype=np.int64),
            cloud_offsets=np.asarray(cloud_offsets, dtype=np.int64),
            cloud_points=(
                np.concatenate(cloud_arrays) if cloud_arrays else np.empty((0, 3), dtype=np.float32)
            ),
            support_offsets=np.asarray(support_offsets, dtype=np.int64),
            support_points=(
                np.concatenate(support_arrays)
                if support_arrays
                else np.empty((0, 3), dtype=np.float32)
            ),
            support_colors=(
                np.concatenate(support_color_arrays)
                if support_color_arrays
                else np.empty((0, 3), dtype=np.uint8)
            ),
            box_offsets=np.asarray(box_offsets, dtype=np.int64),
            box_centers=np.asarray(box_centers, dtype=np.float32).reshape((-1, 3)),
            box_half_sizes=np.asarray(box_half_sizes, dtype=np.float32).reshape((-1, 3)),
            box_quaternions=np.asarray(box_quaternions, dtype=np.float32).reshape((-1, 4)),
            box_colors=np.asarray(box_colors, dtype=np.uint8).reshape((-1, 4)),
            box_track_ids=np.asarray(box_track_ids, dtype=np.int64),
            box_distances_m=np.asarray(box_distances, dtype=np.float32),
            box_support_counts=np.asarray(box_support_counts, dtype=np.int64),
        )
        frames_path = staging / "fusion-frames.jsonl"
        frames_path.write_text(
            "".join(json.dumps(item, sort_keys=True) + "\n" for item in frame_reports),
            encoding="utf-8",
        )
        labels_path = staging / "box-labels.json"
        labels_path.write_text(
            json.dumps(box_labels, ensure_ascii=False, separators=(",", ":")),
            encoding="utf-8",
        )
        contact_path = staging / "contact-sheet.png"
        _contact_sheet(
            contact_images,
            int(profile["presentation"]["contact_sheet_columns"]),
        ).save(contact_path, format="PNG", optimize=True)
        shutil.rmtree(masks_root)
        sync_abs = np.abs(np.asarray(sync_deltas, dtype=np.float64))
        pose_abs = np.abs(np.asarray(pose_deltas, dtype=np.float64))
        usage_after = resource.getrusage(resource.RUSAGE_SELF)
        metrics = {
            "frames_expected": tracking.frame_count,
            "frames_processed": len(frame_reports),
            "frames_fused": fused_frames,
            "frames_depth_unavailable": tracking.frame_count - fused_frames,
            "accepted_cuboids": accepted_cuboids,
            "unique_track_ids_with_depth": len(track_ids_with_depth),
            "cloud_points": cloud_offsets[-1],
            "support_points": support_offsets[-1],
            "rejection_counts": dict(rejection_counts),
            "lidar_camera_abs_delta_ms": _summary(sync_abs),
            "pose_point_abs_delta_ms": _summary(pose_abs),
            "wall_seconds": round(time.perf_counter() - started, 6),
            "process_peak_rss_mib": round(usage_after.ru_maxrss / (1024 * 1024), 3),
            "user_cpu_seconds": round(usage_after.ru_utime - usage_before.ru_utime, 6),
            "system_cpu_seconds": round(usage_after.ru_stime - usage_before.ru_stime, 6),
        }
        report_path = staging / "run-report.json"
        report_path.write_text(
            json.dumps(
                {
                    "schema_version": "missioncore.e6-tracked-lidar-run-report/v1",
                    "result_id": result_id,
                    "created_at_utc": datetime.now(UTC)
                    .isoformat(timespec="milliseconds")
                    .replace("+00:00", "Z"),
                    "identity": identity,
                    "metrics": metrics,
                    "acceptance": {
                        "geometry": "factory-calibrated-kb4-diagnostic",
                        "timing": "host-arrival-best-effort-with-100ms-gate-not-ground-truthed",
                        "distance": "robust-lidar-range-diagnostic-not-ground-truthed",
                        "cuboids": "point-supported-oriented-p05-p95-diagnostic",
                        "tracking": "e5-iou-only-not-ground-truthed",
                        "safety": "not-accepted",
                    },
                },
                ensure_ascii=False,
                indent=2,
                sort_keys=True,
            )
            + "\n",
            encoding="utf-8",
        )
        artifacts = [
            _artifact(arrays_path, "tracked-lidar-arrays", "application/x-npz"),
            _artifact(
                frames_path,
                "tracked-lidar-frame-metadata",
                "application/x-ndjson",
                FRAME_SCHEMA,
            ),
            _artifact(labels_path, "tracked-lidar-box-labels", "application/json"),
            _artifact(overlay_path, "tracked-lidar-overlay-video", "video/mp4"),
            _artifact(rrd_path, "tracked-lidar-rerun", "application/vnd.rerun.rrd"),
            _artifact(contact_path, "tracked-lidar-contact-sheet", "image/png"),
            _artifact(
                report_path,
                "tracked-lidar-run-report",
                "application/json",
                "missioncore.e6-tracked-lidar-run-report/v1",
            ),
        ]
        result_path = staging / "result.json"
        result_path.write_text(
            json.dumps(
                {
                    "schema_version": RESULT_SCHEMA,
                    "result_id": result_id,
                    "identity_sha256": identity_sha256,
                    "identity": identity,
                    "session_id": tracking.job.session_id,
                    "source_id": tracking.job.source_id,
                    "ground_truth": False,
                    "publication_scope": "qualification-clip-only",
                    "frames_processed": tracking.frame_count,
                    "metrics": metrics,
                    "artifacts": artifacts,
                },
                ensure_ascii=False,
                indent=2,
                sort_keys=True,
            )
            + "\n",
            encoding="utf-8",
        )
        os.replace(staging, output)
    except BaseException:
        if recording is not None:
            with suppress(Exception):
                recording.disconnect()
        for process in (decoder, encoder):
            if process is not None and process.poll() is None:
                with suppress(Exception):
                    process.kill()
        shutil.rmtree(staging, ignore_errors=True)
        raise
    print(json.dumps({"result_id": result_id, "output": str(output), "reused": False}))
    return 0


def _summary(values: FloatArray) -> dict[str, float | None]:
    if values.size == 0:
        return {"mean": None, "p50": None, "p95": None, "max": None}
    return {
        "mean": round(float(np.mean(values)), 6),
        "p50": round(float(np.percentile(values, 50)), 6),
        "p95": round(float(np.percentile(values, 95)), 6),
        "max": round(float(np.max(values)), 6),
    }


if __name__ == "__main__":
    raise SystemExit(main())
