Files
NODEDC_MISSION_CORE/docs/audits/2026-09-20-planning-stop-and-delivery.md
T
DCCONSTRUCTIONS e515ab1b8c feat(planning): consolidate recorded-route localization and spatial scene
Preserve the completed teach-and-repeat laboratory stage: reference preparation, cascaded acquisition, local tracking and recovery, recording lifecycle, replay qualification, and persistent Rerun scene controls. Document the open grid-picking regression and Rerun upgrade contract. No autonomous driving or loop-closure optimization is claimed.
2026-09-21 08:47:19 +03:00

9.1 KiB
Raw Blame History

Planning STOP lifecycle and burst delivery

Scope and decision

Owner-authorized follow-up to the physical 017/018 review. Preserve the v6 dense-start / route-search cascade and all geometric, causal, identity and freshness gates. This increment addresses intentional STOP and bounded derived delivery, not K1 SLAM, vegetation robustness, vehicle control or a new retrieval algorithm. Original captures and comparison reports remain immutable.

Commanded stop is not unexpected loss

Both physical runs stopped supplying clouds after operator STOP but retained their raw-recording owners for approximately 51 seconds. The eight-second localisation freshness check correctly expired; the planning owner incorrectly treated intentional cessation as a reason to recover localisation.

The K1 lifecycle facade now signals spatial-stop-requested after its existing canonical request_stop has admitted the command. It supplies the exact evidence session and ingress generation. This is an admitted intent, not proof of physical STOP success or READY. A synchronous admission rejection does not emit it; an asynchronous device failure remains owned and reported by the existing physical-command lifecycle. Localisation does not automatically resume after a failed STOP or replay a command.

The ingress latches that signal independently of queue consumption. It cannot stop another generation, survives a slow consumer and resets on a new session. It neither closes raw capture nor rejects its subsequent publications. The planning owner checks it before freshness/recovery work, clears live authority and completes the study with termination_reason=spatial-stop-requested. An already-running fit retains its compute lease until cleanup; its late output is recorded as unaccepted evidence and cannot publish a new candidate/green state or overwrite the last accepted historical alignment. End-of-input also no longer publishes an intermediate synthetic lost phase.

The existing UI already renders completed studies as the neutral “Исследование завершено”. No frontend, visual components, clipping range or operator-copy changes are part of this increment. Real stale data, rejected geometry, receipt gaps and pose jumps still revoke localisation and initiate the existing recovery flow.

Delivery findings and changes

Physical evidence from the preceding audit: 017 discarded 9/1125 derived lidar receipts, 018 discarded 34/1439 lidar and 1/1439 pose receipts. These are queue overflows, not missing raw recording packets. Both physical walks passed all fresh fits despite those losses.

The retained receipt indexes show bursty delivery:

Recorded burst 017 018
Maximum lidar receipts in 100 ms 12 12
Maximum lidar receipts in 200 ms 14 17
Maximum lidar receipts in 500 ms 17 19
Previous lidar queue capacity 8 8

Both spatial modality queues now retain 32 receipts (previously lidar 8, pose 16). This is bounded burst/scheduling headroom, not a route-length or geometric acceptance limit. The existing 2 MiB packet bound makes the worst case 64 MiB per spatial queue. Overflow counters, source order, original receipt timestamps and all freshness limits remain unchanged. No unbounded queue, new decoder thread, synthetic timestamp or interpolation was added.

PlanningLiveTests also caches height bounds for each immutable reference array. Summary and scene polling previously rescanned/copied the route-wide point array while holding the planning lock. Replacing the reference invalidates the cache; finite-point handling and the existing 80 m ceiling are unchanged. This removes unnecessary work but does not prove that UI polling was the sole cause of the physical packet losses.

Validation and evidence boundaries

Focused suites r2/r3 plus acquisition-control regressions covered 170 distinct tests: exact-generation stop, rejected admission, active raw capture after stop, stop before first cloud, blocked initial/fresh workers, late worker error, 51-second virtual finalisation, real loss/recovery, queue overflow/order, fresh-window separation, registration cascade and cached scene bounds. Evidence: .runtime/qualification-20260920-stop-tests-r2.xml, qualification-20260920-stop-tests-r3.xml, and qualification-20260920-stop-control-tests.xml.

An exploratory cProfile replay is retained at .runtime/qualification-20260920-stop-delivery-018-baseline. It is not an acceptance pass or a timing baseline: instrumentation caused the route search to exceed its budget, expected-tracking/complete-search failed, and a test-file edit during that diagnostic run invalidated its code-unchanged check. Original input hashes remained unchanged. No result was promoted into the planner.

The unprofiled final replay is independently sealed under .runtime/qualification-20260920-stop-delivery-018-final. It uses raw 018 receipts at their original 1x intervals, the real ingress, decoder, planner, numerical child and 10 Hz in-process scene-delta endpoint. An explicitly declared archived last-cloud boundary models admitted STOP while the private capture source remains active; this is not a replay of the K1 command protocol. The separate fake-device tests cover the actual facade admission edge. No socket, scanner command, production comparison mutation or extra app server is used by the archive probe.

Final unprofiled result: 13/13 acceptance checks passed, all input/code hashes unchanged, full route search and tracking at 52.40 s, 20/20 disjoint fresh fits accepted, 85.023 m accumulated travel. Maximum fresh-fit worker wall time was 0.524 s; no recovery was initiated. STOP ended the study while capture ownership remained active, with no green after completion and all temporary leases released. The probe exercised 1,267 scene-delta requests.

Each spatial queue published 1,439 receipts, consumed 1,436, reached a maximum depth of 11/32, and recorded zero overflow or oversize rejections. Three receipts per modality remained queued at intentional STOP; they were not reported as processed or lost from raw capture. Maximum publisher scheduling lag was 0.049 s. No camera/video producer or second browser was included, so this is not proof of zero overflow under all field workloads. A new physical pass must confirm the integrated host/device/browser workload.

Final focused lifecycle/ingress rerun is retained separately in .runtime/qualification-20260920-stop-tests-r4-final.xml. Ruff passed for all changed production modules and qualification helpers; existing Starlette/httpx deprecation warnings were not treated as new product failures.

Local runtime handoff

After the final 37-test lifecycle/ingress rerun passed, the canonical LaunchAgent was reloaded through manage_mission_core_launch_agent.py plan/apply, using the unchanged current/desired declaration SHA 5d7a58122c016f8021fede27d1b21891ee20238fc38c281e5b33574ff8204e3f. Its normal backup and health-acceptance path succeeded. Post-reload /api/health reported operational readiness; /api/state reported idle acquisition, inactive ingress, the new 32/32 capacities and spatial_stop_requested=false. The original 018 comparison remained selected/completed/historical with an 80 m ceiling. Only the canonical backend listened on 8000 (PID 4146); no backend on 8765, temporary replay, numerical child, pytest process or Docker backend remained. Memory-pressure free percentage was 49%; swap did not grow during final qualification/reload. No K1 command or Ops write was issued by this task.

Kilometre-scale next stage

The selected-route policy has no fixed maximum walking distance or duration. Tracking fits a local reference region and recovery starts at the last confirmed place. That supports testing a longer taught route from its known start; it is not evidence that the current system is qualified at kilometre scale.

Cold route-wide retrieval still checks eligible regions at 5 m spacing, with three precise yaw seeds per region and a 35-second combined search budget. A 2 km polyline has 401 anchors rather than the 26 in physical 018. An incomplete search must remain incomplete, not be accepted merely because one good result was found before checking alternatives. The next scaling work is reusable reference preparation and an indexed, ambiguity-aware retrieval strategy—not lowering overlap thresholds or deleting freshness protection.

Other implementation bounds still need qualification on the longer recording: 40 m preparation tiles, repeated source verification/staging and extraction, 90-second extraction/export budgets, a 100,000-pose / 30 MiB trajectory cache, and route-wide map storage/scans. These are not claims of a physical 40 m or 100 m route limit; their cost grows with the reference. This increment does not silently rewrite that architecture.

Recommended field sequence: record a 12 km reference; qualify its preparation and existing saved-pass localisation offline; then repeat from the known start. Cold restart in the middle of the long route is a separate acceptance gate. Foliage/grass changes and handheld motion are relevant nuisance geometry; these two same-day passes show encouraging tolerance, not seasonal acceptance or an absolute scanner-position error certificate.