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.
7.6 KiB
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.182–24.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 (48–49% 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.