mirror of
https://github.com/zvx-echo6/meshai.git
synced 2026-06-10 17:04:45 +02:00
Phase 3 of FIRMS+WFIGS fusion. v15.sql adds perimeter_geojson to fire_passes + last_spotting_broadcast_at to fires. FIRMS handler computes convex hull of each pass on pass-boundary close; attributed pixels >= 1.5 mi (configurable) from previous-pass perimeter emit wildfire_spotting broadcast. Cooldown 1h between spotting broadcasts per fire so rapid embers do not spam. wildfire_spotting category at immediate severity -- spotting is the highest-actionable fire signal (spread beyond perimeter). All thresholds GUI-editable. Phase 4 (LLM summaries + on-demand queries) deferred. Schema (v15.sql): - fire_passes gains perimeter_geojson TEXT (nullable; populated by _close_prev_perimeter at boundary). GeoJSON Polygon, single outer ring in (lon, lat) order per RFC 7946, closed (first == last). - fires gains last_spotting_broadcast_at REAL (per-fire cooldown latch). Index (irwin_id, last_spotting_broadcast_at) for the cooldown probe. adapter_config (defaults.py REGISTRY): - fires.spotting_distance_threshold_mi = 1.5 (float). Matches design doc Phase 3 spec; design doc open question #6 lists this as TBD pending real spotting observation data. - fires.spotting_cooldown_seconds = 3600 (int, 1h). Suppresses rapid-ember spam from a single satellite pass. ALERT_CATEGORIES (notifications/categories.py): - wildfire_spotting: immediate / fire. Highest fire severity -- spotting represents fire spread BEYOND the existing perimeter, the most actionable detection signal. FIRMS handler (central/firms_handler.py): - _handle_pass_boundary now closes the prior pass's perimeter (convex hull of fire_pixels via Andrew's monotone chain) on the first boundary; subsequent in-pass pixels reuse the stored hull. - _check_spotting runs for every attributed pixel: looks up the most recent CLOSED pass (perimeter_geojson NOT NULL AND pass_id != current), point-in-polygon test, vertex-distance approximation per design doc Q (sparse pixels make edge projection overkill at VIIRS 375 m resolution), per-fire cooldown gate. - Priority order: spotting (immediate) > growth (priority) > cluster (priority) > halt (routine). Spotting preempts growth at the same pixel because immediate > priority. - Helpers: _convex_hull (Andrew's monotone chain), _hull_to_geojson (RFC 7946 Polygon), _point_in_polygon (ray casting), _close_prev_perimeter, _check_spotting, _prev_has_perimeter. Wire string: - wildfire_spotting: "🔥 Possible spotting <dist:.1f> mi <dir> of <incident_name> perimeter" -- direction is 8-way bearing from the previous pass's centroid to the spotting pixel. Tests (tests/test_fire_tracker_phase3.py, 11 cases all green): - Pass close stamps perimeter_geojson as a closed Polygon (6 hex vertices -> 7-entry closed ring). - Pixel 2 mi NE of perimeter fires spotting with distance in the 1.0..2.5 mi band (vertex-distance approximation) and direction NE. - Pixel inside perimeter -> NO spotting wire. - Second spotting candidate within 1h cooldown -> suppressed. - Past-cooldown spotting fires again. - Convex hull / point-in-polygon / GeoJSON round-trip helper tests. - adapter_config seed for both new fires.* keys. - wildfire_spotting category registered with immediate severity. - 49 tests green across phase1/phase2/phase3/or-arch/include-roundtrip. Live verification on CT108 after rebuild: - v15 migration applied (schema_meta=15, no Traceback in 3 min). - Container healthy. Synthetic 25-pixel probe (PROBE-V07P3-*, cleaned up after): - Pass A: 20 pixels in a ~0.3 mi circle. Perimeter stored on boundary. - Pass B: 5 pixels at distances 0.5/1.0/2.0/5.0/7.0 mi from center. Observed wires: "🔥 Possible spotting 1.7 mi NE of Probe Spotting Fire perimeter" "🔥 Possible spotting 4.7 mi NW of Probe Spotting Fire perimeter" (Plus a Phase 2 growth wire on the first pass B pixel -- documented side effect: single-pixel pass B centroid shows 0.5 mi drift from pass A.) - 7.0 mi E pixel: outside 5 mi spread, no broadcast (cluster check found no co-located unattributed pixels). Cleanup confirmed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| fixtures/central_envelopes | ||
| conftest.py | ||
| test_adapter_avalanche.py | ||
| test_adapter_config_api.py | ||
| test_adapter_config_foundation.py | ||
| test_adapter_ducting.py | ||
| test_adapter_fires.py | ||
| test_adapter_firms.py | ||
| test_adapter_nws.py | ||
| test_adapter_roads511.py | ||
| test_adapter_swpc.py | ||
| test_adapter_traffic.py | ||
| test_adapter_usgs.py | ||
| test_adapter_usgs_quake.py | ||
| test_avalanche_v057.py | ||
| test_band_conditions.py | ||
| test_central_consumer.py | ||
| test_central_envelope_to_wire_v057.py | ||
| test_central_normalizer.py | ||
| test_central_region_routing.py | ||
| test_central_sub_adapter_routing.py | ||
| test_channel_rendering.py | ||
| test_cold_start_grace.py | ||
| test_config_loader.py | ||
| test_config_source_field.py | ||
| test_consumer_default_deny.py | ||
| test_curation.py | ||
| test_dashboard_config_save.py | ||
| test_dispatcher_persistence.py | ||
| test_env_reporter.py | ||
| test_fire_tracker_phase1.py | ||
| test_fire_tracker_phase2.py | ||
| test_fire_tracker_phase3.py | ||
| test_fire_v057.py | ||
| test_firms_handler.py | ||
| test_incident_handler.py | ||
| test_include_roundtrip.py | ||
| test_itd_511_work_zone.py | ||
| test_notification_toggles.py | ||
| test_nwis_handler.py | ||
| test_nws_dedup_relaxation.py | ||
| test_nws_handler.py | ||
| test_or_arch_continuous.py | ||
| test_persistence.py | ||
| test_pipeline_digest.py | ||
| test_pipeline_grouper.py | ||
| test_pipeline_inhibitor_grouper.py | ||
| test_pipeline_persistence.py | ||
| test_pipeline_scheduler.py | ||
| test_pipeline_skeleton.py | ||
| test_pipeline_toggle_filter.py | ||
| test_quake_handler.py | ||
| test_reminders.py | ||
| test_renderers.py | ||
| test_rf_v057.py | ||
| test_router_env_scope.py | ||
| test_save_section_secret_preserve.py | ||
| test_seismic_v057.py | ||
| test_swpc_handler.py | ||
| test_tail_followups.py | ||
| test_tracking_v057.py | ||
| test_traffic_v057.py | ||
| test_v052_dispatcher.py | ||
| test_water_v057.py | ||
| test_weather_v057.py | ||
| test_wfigs_handler.py | ||
| test_work_zone_renderer.py | ||