W-MLP claimed 90.4% training accuracy in ADR-120 but live UI kept
showing only the 4 baseline classes (absent/still/moving/active).
Root cause: 3 amp_presence_override / amp_classify_from_latest call
sites ALWAYS overwrite classification.motion_level after
adaptive_override runs, regardless of what the model decided. The
rule-based path only knows 4 classes; the 2 new ones (waving,
transition) emitted by the adaptive W-MLP were silently clobbered
every tick.
Hybrid priority:
rule-based wins → absent / present_still / present_moving / active
(ESPectre-style F1>96%, battle-tested)
adaptive wins → waving / transition (exclusive to ADR-120 W-MLP)
Implementation: new helper adaptive_owns_class() + ADAPTIVE_EXCLUSIVE_CLASSES
constant. Each of the 3 rule-based override blocks (multi-BSSID tick,
feature_state path, per-node loop) now guards on `if !adaptive_owns_class(
classification.motion_level)`. Skips the overwrite when the adaptive
model has just emitted a new class.
Live verification (30s sample):
transition: 14/30 (47%) — visible in live UI for the first time
present_still: 10/30 (33%)
present_moving: 1/30
absent: 1/30
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>