wip(k1): checkpoint connection recovery rewrite

Capture the current unreleased K1 connection, recovery, lifecycle, viewer, and test work as a single known-bad baseline for subsequent fixes.
This commit is contained in:
DCCONSTRUCTIONS
2026-08-14 14:57:50 +03:00
parent aff331082f
commit 0ca7316a24
157 changed files with 152962 additions and 4036 deletions
@@ -142,7 +142,10 @@ def build_l34a_assisted_yolox_error_audit(
},
"limitations": [
"the review was seeded from the same frozen candidate and is not independent truth",
"precision, recall and F1 are assisted diagnostic alignment metrics, not acceptance metrics",
(
"precision, recall and F1 are assisted diagnostic alignment metrics, "
"not acceptance metrics"
),
"custom labels are retained as proposed ontology terms and were not adjudicated",
"the result is source-scoped to 32 RAVNOVES00 right-camera frames",
],
+61 -4
View File
@@ -10,7 +10,7 @@ import threading
import time
import zlib
from collections import deque
from collections.abc import Mapping, Sequence
from collections.abc import Callable, Mapping, Sequence
from dataclasses import dataclass
from hashlib import sha256
from typing import Any, Final, Literal
@@ -33,7 +33,7 @@ LiveIngressModality = Literal[
LIVE_INGRESS_SCHEMA: Final = "missioncore.live-perception-ingress/v1"
LIVE_INGRESS_WIRE_SCHEMA: Final = "missioncore.live-perception-wire/v1"
LIVE_RESULT_WIRE_SCHEMA: Final = "missioncore.live-perception-result-wire/v1"
LIVE_RESULT_WIRE_SCHEMA: Final = "missioncore.live-perception-result-wire/v2"
LIVE_RESULT_MAGIC: Final = b"MCPR"
LIVE_RESULT_MAX_HEADER_BYTES: Final = 256 * 1024
LIVE_RESULT_MAX_PAYLOAD_BYTES: Final = 2 * 1024 * 1024
@@ -41,6 +41,8 @@ LIVE_RESULT_MAX_PAYLOAD_BYTES: Final = 2 * 1024 * 1024
@dataclass(frozen=True, slots=True)
class LivePerceptionResultFrame:
session_id: str
session_generation: int
frame_index: int
source_frame_index: int
session_seconds: float
@@ -53,6 +55,8 @@ class LivePerceptionResultFrame:
def encode_live_perception_result(
*,
session_id: str,
session_generation: int,
frame_index: int,
source_frame_index: int,
session_seconds: float,
@@ -65,7 +69,11 @@ def encode_live_perception_result(
"""Encode one bounded, non-authoritative worker-to-viewer result frame."""
if (
frame_index < 0
not session_id
or len(session_id) > 160
or isinstance(session_generation, bool)
or session_generation < 1
or frame_index < 0
or source_frame_index < 0
or captured_at_epoch_ns < 0
or not math.isfinite(session_seconds)
@@ -91,6 +99,8 @@ def encode_live_perception_result(
raise ValueError("live perception result payload exceeds the bound")
header = {
"schema_version": LIVE_RESULT_WIRE_SCHEMA,
"session_id": session_id,
"session_generation": session_generation,
"frame_index": frame_index,
"source_frame_index": source_frame_index,
"session_seconds": session_seconds,
@@ -192,11 +202,19 @@ def decode_live_perception_result(encoded: bytes) -> LivePerceptionResultFrame:
mask = np.frombuffer(raw_mask, dtype=np.uint8).reshape((600, 800)).copy()
normalized_objects = tuple(_normalize_live_result_object(value) for value in objects)
frame_index = header.get("frame_index")
session_id = header.get("session_id")
session_generation = header.get("session_generation")
source_frame_index = header.get("source_frame_index")
session_seconds = header.get("session_seconds")
captured_at_epoch_ns = header.get("captured_at_epoch_ns")
if (
not isinstance(frame_index, int)
not isinstance(session_id, str)
or not session_id
or len(session_id) > 160
or not isinstance(session_generation, int)
or isinstance(session_generation, bool)
or session_generation < 1
or not isinstance(frame_index, int)
or isinstance(frame_index, bool)
or frame_index < 0
or not isinstance(source_frame_index, int)
@@ -212,6 +230,8 @@ def decode_live_perception_result(encoded: bytes) -> LivePerceptionResultFrame:
):
raise ValueError("live perception result time identity is invalid")
return LivePerceptionResultFrame(
session_id=session_id,
session_generation=session_generation,
frame_index=frame_index,
source_frame_index=source_frame_index,
session_seconds=float(session_seconds),
@@ -297,6 +317,7 @@ class LiveIngressEvent:
ingress_sequence: int
session_id: str
session_generation: int
modality: LiveIngressModality
source_id: str
source_sequence: int
@@ -310,6 +331,7 @@ class LiveIngressEvent:
"schema_version": LIVE_INGRESS_WIRE_SCHEMA,
"ingress_sequence": self.ingress_sequence,
"session_id": self.session_id,
"session_generation": self.session_generation,
"modality": self.modality,
"source_id": self.source_id,
"source_sequence": self.source_sequence,
@@ -382,9 +404,13 @@ class LivePerceptionIngress:
}
self._ingress_sequence = 0
self._session_id: str | None = None
self._session_generation = 0
self._active = False
self._closed = False
self._consumer_id: str | None = None
self._results_accepted = 0
self._results_rejected_stale = 0
self._results_rejected_receiver = 0
def begin_session(self, session_id: str) -> None:
if not session_id or len(session_id) > 160:
@@ -402,6 +428,7 @@ class LivePerceptionIngress:
for queue in self._queues.values():
queue.items.clear()
self._session_id = session_id
self._session_generation += 1
self._active = True
self._publish_locked(
modality="control",
@@ -470,6 +497,31 @@ class LivePerceptionIngress:
self._consumer_id = None
self._condition.notify_all()
def admit_result(
self,
*,
session_id: str,
session_generation: int,
receiver: Callable[[], bool],
) -> bool:
"""Atomically reject a late worker result before viewer admission."""
with self._condition:
if (
self._closed
or not self._active
or self._session_id != session_id
or self._session_generation != session_generation
):
self._results_rejected_stale += 1
return False
accepted = receiver()
if accepted:
self._results_accepted += 1
else:
self._results_rejected_receiver += 1
return accepted
def take_next(
self,
consumer_id: str,
@@ -509,7 +561,11 @@ class LivePerceptionIngress:
"mode": "shadow-diagnostic-only",
"active": self._active,
"session_id": self._session_id,
"session_generation": self._session_generation,
"consumer_connected": self._consumer_id is not None,
"results_accepted": self._results_accepted,
"results_rejected_stale": self._results_rejected_stale,
"results_rejected_receiver": self._results_rejected_receiver,
"commands_enabled": False,
"navigation_or_safety_accepted": False,
"closed": self._closed,
@@ -548,6 +604,7 @@ class LivePerceptionIngress:
event = LiveIngressEvent(
ingress_sequence=self._ingress_sequence,
session_id=session_id,
session_generation=self._session_generation,
modality=modality,
source_id=source_id,
source_sequence=source_sequence,