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

163 lines
9.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.