_call_fits_incident now returns (bool, signal_str) so each correlation
decision records exactly what evidence fired: unit_overlap, vehicle_overlap,
location_proximity, time_fallback, tactical_default, or the corresponding
false-return variants (unit_loc_conflict, content_divergence, etc.).
- corr_fit_signal and corr_matched_units written to call docs for
fast/single and fast/disambig paths
- Admin debug endpoint exposes the new fields in calls_detail
- Orphan section adds orphans_by_talkgroup summary (count, no-type count,
sweep-exhausted count per TGID) and raises orphan limit 100 → 250
- Admin page shows corr_path and fit_signal distribution panels above raw
JSON; time_fallback highlighted in yellow as a diagnostic marker
No correlation logic changed — diagnostic data only.
- Move incident panel to left side (was topright, conflicting with LayersControl)
- Move legend to bottom-right, raise auto-fit button to clear it
- Tighten fan card step 7→5px for closer grouping
- Geocoding: remove bounded=1 hard clip, widen bias radius 0.1°→0.5° (~55km)
so addresses like "34 Carlton Drive" resolve outside the node's immediate area
Map (MapView.tsx):
- Fan/hand-of-cards marker clustering: groups nearby markers by pixel
proximity (union-find), renders as rotated color cards showing all types
- Pulsing ring CSS animation on recording nodes (pulse-ring keyframe)
- Live incident overlay panel — right sidebar (desktop) / bottom drawer (mobile),
clickable to flyTo incident location
- Auto-fit button (⤢) fits all markers in view with fitBounds
- "Live · Xs ago" timestamp badge (refreshes every 10s)
- Weather Radar layer (NEXRAD via Iowa Env Mesonet, no API key)
- ADS-B + Meshtastic placeholder layers (off by default)
Map page (map/page.tsx):
- Fullscreen / kiosk toggle: fixed z-50 overlay covers nav, map fills viewport
- lastUpdated tracking passed to MapView for Live timestamp
Systems page (systems/page.tsx):
- Duplicate System button: opens form pre-filled with Copy of <name>
- RadioReference HTML import: file upload → DOMParser validates .rrlblue
structure, parses talkgroup categories, modal lets user select which
categories to import, auto-maps RR tags to local tags (law→police, etc.)
incident_correlator.py — full rewrite: always runs on every call, fetches all active incidents cross-type, fast path collects all talkgroup matches and disambiguates by unit/vehicle overlap → location proximity → embedding, new location proximity path, slow path requires location corroboration, "Auto:" stripped from titles, "auto-generated" tag added, units/vehicles now accumulated on update
intelligence.py — resolved field in GPT schema, returned as 5th value
upload.py — both pipelines unpack 5-tuple, always call correlate, auto-resolve on resolved=True
summarizer.py — stale sweep runs each tick, resolves incidents idle for 90+ minutes
config.py — correlation_window_hours=2, embedding_similarity_threshold=0.93, location_proximity_km=0.5, incident_auto_resolve_minutes=90