fix(k1): restore low-latency live recovery path
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
# ADR 0042 — K1 run ledger and regression telemetry
|
||||
|
||||
Status: proposed for acceptance
|
||||
Date: 2026-08-22
|
||||
|
||||
Named physical references and redacted evidence hashes are retained in
|
||||
[`docs/lab/010_K1_MISSION_CORE_INTERNAL_LIVE_BASELINE_20260822.redacted.md`](../lab/010_K1_MISSION_CORE_INTERNAL_LIVE_BASELINE_20260822.redacted.md).
|
||||
That report deliberately distinguishes the fast Mission Core internal
|
||||
ideal-path reference from the accepted recovery-capable checkpoint and from
|
||||
manufacturer/LixelGO evidence.
|
||||
|
||||
## Context
|
||||
|
||||
The K1 integration has repeatedly returned to the same visible failures after
|
||||
otherwise successful recovery work: delayed first point cloud, a camera that
|
||||
repeatedly disappears and reopens, browser decoder failures, slow START/STOP,
|
||||
and connection-mode transitions that disturb an already accepted Bridge path.
|
||||
|
||||
The current evidence is individually strong but operationally fragmented. Raw
|
||||
MQTT capture, camera fMP4 epochs, acquisition checkpoints, browser diagnostics,
|
||||
redacted manifests and operator timing notes use different identities and must
|
||||
be correlated manually. A successful run is described in Ops, but is not yet an
|
||||
executable baseline that can reject a later regression.
|
||||
|
||||
The repository already owns an accepted telemetry plane under ADR 0031:
|
||||
Telegraf and a bounded native JSONL outbox publish through authenticated MQTT to
|
||||
the Mission Core normalizer and TimescaleDB. Introducing another broker or
|
||||
database solely for K1 would create a second lifecycle, credential boundary and
|
||||
recovery problem without improving the local K1-to-Mission-Core evidence path.
|
||||
|
||||
## Decision
|
||||
|
||||
Every physical or replayed K1 acquisition is one explicit **K1 run**. The run is
|
||||
identified by the acquisition id and its evidence-session lineage. All derived
|
||||
events carry the same redacted identity, code revision, UI build id, connection
|
||||
mode and monotonic clock origin.
|
||||
|
||||
The authoritative write path is:
|
||||
|
||||
```text
|
||||
K1 control, MQTT receiver, camera gateway and browser diagnostics
|
||||
-> local append-only K1 run journal
|
||||
-> bounded durable outbox
|
||||
-> authenticated telemetry MQTT topic
|
||||
-> existing Mission Core telemetry normalizer
|
||||
-> existing TimescaleDB
|
||||
-> run comparison and acceptance report
|
||||
```
|
||||
|
||||
The local journal remains the source of truth during network loss. Database
|
||||
availability never gates START, STOP, raw evidence capture, camera archival or
|
||||
local recovery. Delivery resumes from the outbox when the telemetry contour is
|
||||
available.
|
||||
|
||||
The initial event contract is `missioncore.k1-run-event/v1`. Each event contains:
|
||||
|
||||
- `run_id`, `acquisition_id`, redacted `evidence_session_id` lineage;
|
||||
- UTC and monotonic timestamps plus a per-run sequence number;
|
||||
- Mission Core commit, UI build id and K1 compatibility-profile id;
|
||||
- connection mode, host-path epoch and producer generations without addresses,
|
||||
credentials, project names or raw device identifiers;
|
||||
- event code, stage, outcome and bounded numeric facts;
|
||||
- source component and source schema version.
|
||||
|
||||
The required timeline includes at least:
|
||||
|
||||
- operator START intent, physical command publication and confirmed SCANNING;
|
||||
- calibration start/end when the device exposes those facts;
|
||||
- first authoritative PCL received and first PCL published to Rerun;
|
||||
- browser Rerun store admitted and first visible point-cloud frame;
|
||||
- camera producer init, first media, browser first frame and sustained playing;
|
||||
- camera decoder errors, preview-reader retirements, IDR admission, queue age,
|
||||
bytes and fragment counts;
|
||||
- connection gap start, recovery attempts, recovered binding and gap end;
|
||||
- operator STOP intent, confirmed READY and archive finalization;
|
||||
- terminal run result and automatically evaluated acceptance checks.
|
||||
|
||||
An acceptance report is generated from the journal after each run. It compares
|
||||
the run with a named accepted baseline and reports exact deltas. The following
|
||||
conditions are hard failures rather than performance warnings:
|
||||
|
||||
- any browser `MEDIA_ERR_DECODE`;
|
||||
- any decode error in the archived camera stream;
|
||||
- a missing first point-cloud admission or missing terminal archive;
|
||||
- loss of acquisition/control lineage;
|
||||
- a device state asserted by the UI without authoritative device evidence.
|
||||
|
||||
Latency and FPS thresholds are versioned baseline checks. They are never
|
||||
implemented by silently reducing point count, image quality, bitrate or source
|
||||
FPS. A threshold change requires its own reviewed acceptance run.
|
||||
|
||||
The engineering work format changes accordingly:
|
||||
|
||||
1. Name the accepted baseline and the single invariant targeted by the change.
|
||||
2. Make one bounded implementation increment.
|
||||
3. Run focused synthetic tests before a physical test.
|
||||
4. Perform one canonical UI run; do not substitute direct device commands.
|
||||
5. Generate and retain the run comparison automatically.
|
||||
6. Do not merge a change that improves its target while regressing an already
|
||||
accepted invariant.
|
||||
|
||||
## Rejected alternatives
|
||||
|
||||
### Redis
|
||||
|
||||
Redis is useful for disposable cache and coordination. It is not the evidence
|
||||
system of record for offline physical runs and does not replace a durable local
|
||||
journal or analytical store.
|
||||
|
||||
### Kafka
|
||||
|
||||
Kafka is not admitted for this local single-producer contour. The existing MQTT
|
||||
plane already supplies authenticated fan-out and reconnect delivery, while the
|
||||
local outbox supplies offline durability. Kafka would add a second broker and
|
||||
operational quorum without repairing the K1, RTSP, browser or local-network
|
||||
boundaries. It can be reconsidered only when independent high-volume consumers,
|
||||
cross-site retention or replay requirements exceed the accepted MQTT contour.
|
||||
|
||||
### ClickHouse
|
||||
|
||||
ClickHouse is not admitted as a second telemetry database. Existing TimescaleDB
|
||||
already stores run identity, timestamps and JSON payloads and is sufficient for
|
||||
the current event volume and comparisons. The event schema remains storage
|
||||
neutral, so a later measured analytical-volume limit can justify a reviewed
|
||||
ClickHouse migration without changing producers.
|
||||
|
||||
## Implementation increments
|
||||
|
||||
1. Generate a local K1 run report from the evidence and diagnostic artifacts
|
||||
already produced today; no runtime transport change.
|
||||
2. Emit the versioned append-only event contract directly during a run and seal
|
||||
it with the evidence session.
|
||||
3. Tail the bounded outbox through the accepted ADR 0031 telemetry plane and
|
||||
extend the normalizer with K1 run series.
|
||||
4. Add baseline comparison and a CI/replay gate. Physical acceptance remains a
|
||||
separate operator-controlled UI test.
|
||||
|
||||
No product window, status family or K1 control command is introduced by this
|
||||
decision.
|
||||
|
||||
## Consequences
|
||||
|
||||
- A stable K1 run becomes executable regression evidence rather than a prose
|
||||
memory.
|
||||
- Camera, point-cloud, control and recovery events can be compared on one clock
|
||||
and one run identity.
|
||||
- Wi-Fi or telemetry-plane loss cannot erase the local run or block the device.
|
||||
- The existing telemetry stack is extended instead of duplicated.
|
||||
- The first implementation work is an evidence/reporting increment; it does not
|
||||
authorize broad recomposition of the fragile K1 communication path.
|
||||
Reference in New Issue
Block a user