The backend stereo service was enabled by a single watcher on the
combined stereo toggle state with { immediate: true }. That immediate
run fires during setup(), before the dataset/viewer has finished
loading, so the load-time auto-enable of a remembered setting (e.g.
"update lengths on modify" on by default) could hit not-yet-ready
multicam metadata, fail, and degrade silently with nothing to retry.
The service then stayed off -- and lengths were not auto-recomputed --
until the user flipped a stereo toggle off and on again.
Split the watcher: runtime toggle changes still enable/disable
immediately (always user-initiated), while the load-time auto-enable is
deferred to a one-shot watcher on the viewer's progress.loaded, so it
runs once the dataset is actually loaded and the metadata/calibration
the enable needs are available.
Problem
In the desktop interactive stereo feature, if the "update lengths on modify" option (or "auto-compute location on other camera") is on at program boot, the backend stereo service was not initialized and lengths were not auto-recomputed — until the user flipped a stereo toggle off and on again (or turned on the other stereo option).
Root cause
The stereo service was enabled by a single watch(stereoServiceWanted, …, { immediate: true }) in ViewerLoader.vue. The immediate run fires during setup() — before the dataset/viewer has finished loading. On that boot run (treated as non-user-initiated), if loadStereoMetadata() / stereoEnable() doesn't succeed at that instant (multicam metadata / calibration or backend not ready yet), the catch block degrades silently and nothing retries. The frame watcher only pushes frames and bails on !stereoEnabled, so the only re-entry points were a user toggle or a calibration import.
Fix
Split the single watcher into two responsibilities:
The enable/disable logic is extracted into a shared applyStereoServiceState(enabled, userInitiated) helper (with an idempotency guard so a user toggle racing the load-time enable can't start the service twice). Benign-failure silent-degrade and launch-failure dialog behavior are preserved.
Verification
eslint passes on the changed file.