From 90943ff96688d6d2e32ede034bcd4f5c5c98506a Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 2 Aug 2026 19:53:54 +0000 Subject: [PATCH] feat(host): expose ConstellationFrameState as a StateFlow for the mesh-health UI Surfaces the engine's new frame-lock lifecycle (constellationFrameState) so the diagnostics UI can advertise frame stability and its degradation/recovery: CONVERGING -> LOCKED (stable) with RESOLVING_MOTION (an anchor was bumped or moved) and RESOLVING (an anchor dropped, healing) as the degraded states. Wired exactly like the existing antennaDelays / anchorLinks flows: a MutableStateFlow refreshed on the 2 s engine-maintenance tick, read on the engine thread. Default CONVERGING until the first tick. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01WppuiKZt4CuQxX4N7k6SVR --- .../java/com/aether/mofe/platform/MofeEngineHost.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/androidApp/src/main/java/com/aether/mofe/platform/MofeEngineHost.kt b/androidApp/src/main/java/com/aether/mofe/platform/MofeEngineHost.kt index c6f58a6..e59875a 100644 --- a/androidApp/src/main/java/com/aether/mofe/platform/MofeEngineHost.kt +++ b/androidApp/src/main/java/com/aether/mofe/platform/MofeEngineHost.kt @@ -8,6 +8,7 @@ import com.aether.mofe.engine.MofeListener import com.aether.mofe.engine.MultiObserverFusionEngine import com.aether.mofe.engine.MultilaterationSolver import com.aether.mofe.model.AnchorHealth +import com.aether.mofe.model.ConstellationFrameState import com.aether.mofe.model.DeviceId import com.aether.mofe.model.FusedState import com.aether.mofe.model.InterAnchorLinkReport @@ -122,6 +123,12 @@ class MofeEngineHost( * the mesh-health UI, refreshed on the maintenance tick. null until a calibration exists. */ val antennaDelays: StateFlow = _antennaDelays.asStateFlow() + private val _constellationFrame = MutableStateFlow(ConstellationFrameState.CONVERGING) + /** Frame-lock lifecycle for the mesh-health UI, refreshed on the maintenance tick: + * CONVERGING → LOCKED (stable) ⇄ RESOLVING_MOTION (an anchor was bumped/moved) / RESOLVING + * (an anchor dropped, healing). Advertises frame-stability degradation and its recovery. */ + val constellationFrame: StateFlow = _constellationFrame.asStateFlow() + /** Instrumentation + state capture — the engine's multi-observer fusion output, * surfaced to logcat AND to the flows above for the HUD/health pane to consume. */ private val logListener = object : MofeListener { @@ -230,6 +237,9 @@ class MofeEngineHost( .getOrDefault(InterAnchorLinkReport.EMPTY) // Latest antenna-delay calibration for the mesh-health UI. _antennaDelays.value = runCatching { eng.antennaDelayCalibration() }.getOrNull() + // Frame-lock lifecycle (LOCKED / RESOLVING_MOTION / …) for the mesh-health UI. + _constellationFrame.value = runCatching { eng.constellationFrameState() } + .getOrDefault(ConstellationFrameState.CONVERGING) } } } -- 2.43.0