docs(perception): record cross-host canary failure and joint startup gate

This commit is contained in:
DCCONSTRUCTIONS
2026-09-02 20:44:08 +03:00
parent 093df8b38f
commit 93ae1edbb4
3 changed files with 193 additions and 3 deletions
@@ -0,0 +1,163 @@
# Stage 2 increment 15 — full graph with acknowledged cross-host clocks
2026-09-02, 20:37 MSK. **Implementation/regressions accepted; real-time canary FAIL.**
Stage 2 remains open. No stage 3 cutover, standalone release or actuation is claimed.
Code commit: `35b6cd9`.
## Objective and retained architecture
Connect the existing Mac recording source and real result receiver to the single
Worker006 full graph: DDRNet-39 GOOSE, RF-DETR, online LiDAR geometry/distance,
temporal/motion, TRAVEL TGS/costmap and advisory policy. The source supplies original
camera fragments, normalized point increments and poses incrementally at 1x.
No whole recording upload, predecode, precomputed perception layers or per-recording
application is introduced. Original source timestamps never change during a run.
The Worker model container has no recording/index/camera/sensor-archive mount. This
is still a diagnostic dependency image with explicit code/model mounts, **not** the
portable standalone profile. Mac only reads/releases raw events and validates replies.
Masks and full scene/grid payloads return over gRPC/TLS through the existing authenticated
SSH/Tailscale route. This is not the prospective rover radio or an onboard deployment.
## Implemented contracts
- `StreamControl/ReportClock` echoes the last issued Poll challenge once, including the
source receipt timestamp. The Worker checks nonce, both clock identities and its own
receive/send timestamps; an acknowledgement must arrive within 500ms. The control
capability cannot renew a GPU lease, restart models, select epochs or actuate.
- `ClockReceipt` derives the responder-side offset interval from the original causal
exchange, not a reversed/symmetric-delay shortcut. The source anchor is immutable.
The explicit conditional envelope remains 500ppm relative drift, 50us per timestamp,
2s expiry and uncertainty <=5ms. These assumptions are not hardware clock certification.
- The Worker checks current clock validity at ingress, GPU/CPU work, publication and
while idle. The source checks it during sending and receipt. Unavailable mapping means
WAIT, bounded discard, a new controller-owned input epoch and fresh keyframe/sensors.
Lease renewal/model ownership remains local and independent of the network.
- Source cutoff uses the upper mapped age bound. Scene and per-cell expiry include
uncertainty; the Mac receiver measures elapsed source-to-consumer time entirely on its
own monotonic clock. Worker-local mapped timing is diagnostic, not the acceptance clock.
- One clock snapshot is used throughout each publication/receipt assessment. A concurrent
clock update cannot change the timestamp midway through cell/policy assessment.
- Source completion is acknowledged before data EOF can retire the control endpoint.
Clock warmup precedes initial source-anchor assignment; once assigned, it is never
shifted to recover skipped observations.
- An admitted transport disconnect before the application OPEN now enters WAIT too.
Previously the one-use grant could be consumed while the runtime remained active with
no input, preventing a replacement epoch. An unbound malformed packet still cannot
stop the owner; obsolete peers cannot pause a replacement epoch.
## Method and sequential results
Each model attempt used one profile and the same serialized GPU schedule. Dedicated
RTX4090, 8 CPU/8GiB limit, pids256, shm256MiB; temporary stock-clock reference
2610/10251MHz and unchanged 450W power limit. No EoMT, Frigate or Ollama inference.
Four pre-existing Mission Core services were quiesced and restored per attempt.
All attempts remain separately identified; none is overwritten or omitted:
| Attempt | Outcome | Accepted interpretation |
| --- | --- | --- |
| canary32a | Missing candidate manifest before model startup | Packaging failure, no measurement |
| canary32b | Missing pinned DDRNet runner | Packaging failure, no source processed |
| canary32c, code-v1 | 30 results, 2 compute discards; source EOF acknowledgement timed out | Full graph/receipt evidence, not accepted real-time |
| canary32d, code-v2 | 0 results, clean bounded completion | 3 source WAIT skips +29 synchronization skips |
| canary32e, code-v3 | Source command incorrectly named the index directory, not index.jsonl | Operator-command failure, no source data; explicitly ended via the pilot watchdog handler |
| canary32f, code-v4 | 2 results, clean bounded completion | Final canary FAIL:13 source WAIT skips +17 synchronization skips |
The launcher now checks the manifest, pinned runner hash and all bind sources before
quiescing services. Source command generation checks exact input files before activation.
The pinned runner is unchanged (`b18ad60f277eea69a240a28f290611b94627fb9707faf1bb3e6e22102dad67c1`).
The rejected early source command was stopped by signalling the confirmed diagnostic
main PID7 through its existing SIGALRM handler, allowing ordinary cleanup/lease release.
### First full cross-host observation: canary32c
32 source frames ->32 accepted inputs ->30 byte-exact scene receipts +2 explicit
`input-gap` compute discards (sequences17,27). No reply drops or unaccounted frames.
The discarded calculations coincided with the old repeated-clock-read assessment path;
the run did not retain enough fine-grained tracing to prove that as their sole cause.
All30 received raw model/geometry/temporal/costmap reference comparisons match;28 replies
arrived before source EOF. Twelve scenes are fully fresh; missing/aged source geometry
does not become permissive policy.
Measured source-to-consumer-ready p95/p99:208.197/211.873ms, range90.877211.873ms.
The125ms latency gate fails even apart from discards/EOF error. Published clock
uncertainty:3.4874.543ms. Peak reply440373B; tracked input14640679B, below16MiB.
These figures belong to the rejected code-v1 attempt, not the final candidate.
### Final candidate: canary32f
Source released all32 frames at1x. Sequences012 were omitted while waiting for
admission. Sequences1329 were skipped for fresh sensor/keyframe synchronization.
The full graph resumed at30; frames30 and31 returned, byte/hash validated. Both arrived
after the bounded source window ended. Therefore neither complete delivery nor the
result-before-EOF gate passed. This was startup WAIT followed by synchronization,
**not** two successful initial frames followed by a late outage.
The two source-to-consumer-ready delays were143.881 and155.743ms. Two observations
do not establish meaningful p95/p99 or sustainable FPS. Both receipts are fresh under
the explicit250ms freshness envelope; this does not make2/32 availability acceptable.
Segmentation/detector output matches the reference for both frames. History-dependent
geometry/motion/costmap differs after the omitted prefix and reset; full-scene reference
parity is not claimed.
Clock loop:78 observations,28 marked ready; uncertainty min/median/max
3.915/5.312/30.808ms. Published uncertainty4.5174.562ms. The gate was never widened.
One input epoch, one lease generation and four resident children; no model reload
while awaiting admission. Peak reply403572B, tracked input10479771B, final buffers0.
Final run sampled VRAM peak2365MiB and cgroup peak3313.4MiB; Mac source RSS59.9MB.
This is not evidence of a24GiB capacity limit. Sensor archive rows are read incrementally,
not fully loaded or transferred.
## Validation and retained limitations
- Final local:297PASS,2 intentionally Worker-only skips. Worker:173PASS including
the native large-result/slow-reader tests. Early-open cancellation: six additional
sequential repeats, two cases each,12/12PASS. No timeout was increased.
- The previous intermittent reconnect test was reproduced three times. Diagnostics
found `opened=false`, drained transport and still-active continuity; the correction
covers cancellation both before and after OPEN. An initial overly broad failure
handler was rejected by four existing unbound-peer tests and corrected before GPU use.
- Ruff, format, six-file strict mypy and diff checks pass.128 staged Python files match
measured commit35b6cd9, including the pinned runner mapping and final test-only overlays.
Subsequent formatting in two files is independently AST-identical; no new model result
is attributed to a changed algorithm.
- `verify.py` independently reconciles source/compute/synchronization/receipt counts,
raw scene bytes, mask/layer hashes, Mac receipt ages and clock-bound widening arithmetic.
This campaign retained aggregate clock bounds, not every raw five-timestamp exchange;
raw clock reconstruction remains a next diagnostic, not a claimed proof here.
- No full-session, controlled cross-host full-graph outage or full-graph slow-consumer
acceptance was performed after the negative canary. The earlier same-Worker results
retain their original narrower scope. Product UI/registry was not changed.
## Decision and next Stage 2 gate
The graph works over this real route, but its current start/readiness protocol does
not provide stable availability. The source can first pass its clock bound before
the Worker has accumulated equivalent responder-side evidence; its fixed2s lead does
not prove joint readiness. Missing the initial keyframe/sensor prefix then magnifies
a short admission delay. This is a protocol/startup finding, not a GPU sizing result.
Next: separate two-sided clock warmup from immutable source-anchor activation. Confirm
both peers' current readiness before starting the1x source, then keep the source clock
running unchanged through real faults. Retain raw exchange/ack timing and state-change
ledgers to distinguish route latency, scheduling and protocol overhead. Repeat one short
normal canary; only after that pass, run controlled outage/slow-consumer and longer windows.
Do not weaken the5ms gate, replay backlog or infer an onboard/radio result from SSH.
Standalone packaging remains later within Stage2; Stage34 remain unopened.
## Cleanup and evidence
All temporary containers, lease volumes, host collectors and port18561/tunnel are gone.
Owner records released; four service container IDs restored, Triton200, Telegraf Running.
GPU automatic210/405MHz,980MiB,0%,450W at final sample. Existing legacy service defects
are not declared fixed. Ollama/Frigate remain exited/restart=no. Canonical Mac8000 PID33360
and identity-matched agent-MQTT telemetry remain available;8765 absent. No physical K1,
motor/autopilot, recording, Synology or external deployment mutation.
Private TLS keys/bootstrap capabilities were removed on both hosts; public certificates
and raw non-secret diagnostics retained. Session:
`.runtime/perception-stage2-crosshost-20260902T1705Z/`,198 artifacts,
manifest SHA-256 `7b435cac111b3e0e789aa137ba064651e6d344a5f8fb8fa35b0abbd0e7cb1d74`.
Final code-v4 archive SHA-256:
`866d709baa785101d10b32b31a17a1b97b15e6de4de932bfd2e79c00825911ab`.