Files
NODEDC_MISSION_CORE/docs/audits/2026-09-19-runtime-scheduling-fix.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

7.6 KiB
Raw Blame History

K1 stationary start: runtime scheduling correction

Date: 2026-09-19. Mission Core Ops: MISSIONCOR-81; camera baseline: MISSIONCOR-3. Follow-up to 2026-09-19-physical-start-005.md. The owner confirmed K1 was off before the canonical local service was restarted. No scanner command was issued.

Finding and correction

The canonical8000 LaunchAgent declared ProcessType=Background; launchctl also reported spawn type = background (5) and the Python service had priority4. The localization child inherits this resource class. Apple's launchd manual describes Background as applying CPU and I/O resource limits. This is unsuitable for the application's operator-requested camera ingestion and bounded initial localization. An HTTP request does not provide the XPC activity needed to promote an Adaptive job. Source: installed launchd.plist(5) and Apple's launchd manual.

Reproducing the same frozen005 input under /usr/sbin/taskpolicy -b, with no camera or generated load, again exhausted the unchanged deadline. This identifies an independently reproducible scheduling cause of the slowdown. It does not prove the origin of the corrupt H.264 already present in the physical005 archive.

The versioned src/k1link/local_service_launchd.py now declares Interactive, the ordinary app resource class. It does not set realtime priority, alter system resource limits, or change algorithms. The pre-apply plist comparison found exactly one changed key, ProcessType; environment, arguments, repository, watchdog, process-group ownership, data and camera/map configuration are identical.

scripts/manage_mission_core_launch_agent.py applied the hash-gated plan, made a private backup, reloaded the exact label and accepted /api/health. Its automatic rollback remained available. Previous plist SHA-256: 6b651aedb54236f76bf062a2319d9223f0b00f7d264451b3bbaccbee0896e065; new SHA-256: 5d7a58122c016f8021fede27d1b21891ee20238fc38c281e5b33574ff8204e3f. Post-apply launchctl: spawn type = interactive (4); one Python listener on8000, none on8765; health operational. UI entry asset: /assets/app-DKxsidxk.js.

Evidence and bounded combined replay

Private evidence root, outside Git: NODEDC_MISSION_CORE/.runtime/mission-core/missions/diagnostics/20260919-runtime-scheduling-fix. It retains the background reproduction, applied plan, runtime acceptance, test/build logs, UI fixture acceptance and combined-replay-02. The prior005 sealed capture is unchanged. Input identity: b72e1f202a04c5455aa10d2907a3912bfb3fbf76b84a079746b23aaa0cc0f9eb.

Execution Entry seeds Search wall time Decision
Physical005, before correction 54/108 25.4795 s reject incomplete search
Exact saved input, Background, no camera 38/108 25.8272 s reject incomplete search
Prior ordinary isolated child 108/108 16.0428 s complete candidate search
Ordinary combined archive replay 108/108 14.1715 s complete candidate search

The combined run replays the first65seconds of physical005 MQTT at original receipt intervals through LivePerceptionIngress, the production K1 planning decoder, PlanningLiveTests, bounded entry child, three disjoint fresh validation windows and Rerun scene generation every2seconds. Search process CPU time was 14.1691seconds, close to wall time. Full108-seed coverage, five supporting seeds, ambiguity rejection, original25second search/30second child deadlines and fresh validation thresholds remain unchanged. Overlap96.3758% and inlier RMSE0.151095m match the previously observed candidate; these are not measured position accuracy.

In parallel, the helper scripts/planning_archive_camera.py feeds the clean canonical camera baseline A, session 20260822T105904Z_viewer_live, through the real fMP4 parser, per-segment durable archive, bounded preview queue and a local FFmpeg decoder. The helper has no RTSP or hardware producer. All70 retained media fragments keep their recorded intervals and exact bytes; no generated load or accelerated playback is used. The baseline's legacy index does not contain an init receipt timestamp: init is delivered with the first media receipt, so no initialization-latency claim is made.

Camera commits span0.18224.601seconds and overlap the entry search. All70 media fragments and init were archived and delivered byte-for-byte;70 frames decoded; decoder warning/error log empty; no slow-reader retirement. Producer/decoder children, parser/preview threads and planning leases were released. The helper adds a camera acceptance report to the existing replay manifest and source seal.

Fresh validation reached tracking at37.591seconds after archive playback started. Further fresh results stayed tracking until the65second retained prefix ended; the service then correctly revoked live authority. No prior, stale sample or completed run was promoted to live tracking. All combined acceptance checks passed.

This is stronger than the earlier cloud-only replay, but is not full physical acceptance: the ordinary acquisition authority/publisher, K1 RTSP encoder/network and browser MSE are not exercised by the replay. Clean baseline video cannot retroactively repair or certify physical005's corrupt archive.

Operator presentation

Initial unsuccessful binding now says «Поиск остановлен» and explicitly instructs the operator to stop the device/recording and start a new study for another attempt. It has no continuing busy indicator. The production K1 status component wraps the instruction, uses the canonical11px token and keeps it visible below960px. Device authority, stop precedence, lost-after-established tracking, stale-data rejection and session identity fences remain unchanged.

Changed owners: stationary_live.py, planningPresentation.ts, K1SpatialSession.tsx/.css, the duplicate responsive rule in plugin styles.css. Entry diagnostics now also retain process CPU time in entry_acquisition.py; the decision still uses wall time.

Validation and limitations

  • 48 focused backend tests passed: LaunchAgent plan/apply, entry acquisition, stationary bootstrap and live planning.
  • 55 existing camera gateway/archive regression tests passed.
  • Architecture4/4, full TypeScript check, frontend853/853 and production build passed sequentially. Build retains the existing large-chunk warning.
  • Ruff passed for changed Python owners and replay helpers.
  • Actual8000 UI opened a retained aligned project and its inspector; ordinary and expanded window states work. Close-button behavior works. The existing floating inspector did not close on Escape; that unrelated behavior is retained as a follow-up, not represented as a passed check.
  • The terminal status was rendered from the production React component and built stylesheet in an explicitly labelled offline fixture at1280px and800px. Full instruction visible; no ellipsis or overflow; desktop scroll height equals client height45px. This is presentation QA, not a fabricated live session. The temporary fixture route/tab was removed and viewport override reset.
  • No Docker VM or stress test was started. Memory pressure remained healthy (4849% reported free), swap did not grow during qualification. Temporary children exited. The canonical8000 service remains running.

Next gate: qualify the remaining acquisition/MSE boundaries without changing scanner state, then perform a short physical stationary start with continuous camera and fresh tracking. A long field walk and autonomous vehicle authority are not accepted by this result. Preserve physical005's unresolved STOP evidence; the owner's report that the scanner is off is not a fabricated READY receipt.