move_detect/edge/detectors
유창욱 f7266f5980 fix(edge): identity-aware GHOST dedup keyed on track_id (FIX 4)
edge/engine.py keyed the ghost cooldown as
(GHOST, round(x), round(y)) — purely spatial, ignoring track identity.
Two distinct workers collapsing at ~the same pixel within the cooldown
window would suppress each other's ghost event, potentially masking a
second CRITICAL incident.

edge/detectors/ghost.py GhostIncidentDetector.update now includes the
candidate's track_id in each emitted dict. edge/engine.py keys the
cooldown as (EventType.GHOST, track_id) and sets the emitted Event's
track_id accordingly, matching how FALL/NO_MOTION/IMMOBILITY/zone events
are already keyed per-track.

Tests: tests/test_ghost.py asserts ghosts[0]["track_id"] == 1 on the
existing reappear-timeout test.
2026-07-11 22:17:48 +09:00
..
__init__.py feat(edge): FallDetector state machine (OR-logic, baseline freeze, post-fall no-motion) 2026-07-11 20:41:11 +09:00
fall.py fix(edge): require sustained non-prone before FallDetector recover (FIX 2) 2026-07-11 22:15:47 +09:00
ghost.py fix(edge): identity-aware GHOST dedup keyed on track_id (FIX 4) 2026-07-11 22:17:48 +09:00
immobility.py feat(edge): ImmobilityWatchdog (posture-independent prolonged immobility) 2026-07-11 20:51:33 +09:00
zone.py feat(edge): ZoneIntrusionDetector (foot-anchor point-in-polygon, debounce) 2026-07-11 21:05:42 +09:00