feat: fire halt broadcast + tombstone all-clear (wildfire_halted / wildfire_closed)

Enable _maybe_emit_halt in firms_handler (remove return None stub) so
fires with no FIRMS hotspot activity beyond halt_minimum_seconds emit a
routine wildfire_halted broadcast.

Add tombstone all-clear in wfigs_handler: when a fire is tombstoned and
has last_broadcast_at set (i.e. previously made it to mesh), broadcast a
wildfire_closed message with acres, containment, and location. Fires that
were never broadcast are silently consumed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matt Johnson (via Claude) 2026-06-09 17:45:41 +00:00
commit f4930a388f
2 changed files with 34 additions and 1 deletions

View file

@ -774,7 +774,6 @@ def _maybe_emit_halt(conn, *, data, now):
eligible because we filter on `halt_broadcast_at IS NULL OR
halt_broadcast_at < last_pass_at`.
"""
return None
minimum_s = int(adapter_config.fires.halt_minimum_seconds)
cutoff = float(now) - float(minimum_s)
row = conn.execute(

View file

@ -116,6 +116,40 @@ def handle_wfigs(normalized: dict, envelope: dict, subject: str,
)
except Exception:
logger.exception("wfigs: tombstoned_at stamp failed irwin=%s", irwin_id)
# All-clear broadcast: only fires that previously made it to mesh
# get a closure message. Silent for fires that were never broadcast.
if kind == "wfigs_tombstone" and irwin_id:
fire_row = conn.execute(
"SELECT incident_name, current_acres, current_contained_pct, "
"last_broadcast_at, county, state, lat, lon "
"FROM fires WHERE irwin_id = ?", (irwin_id,)
).fetchone()
if fire_row is not None and fire_row["last_broadcast_at"] is not None:
name = fire_row["incident_name"] or "(unnamed fire)"
# Build line 2 parts
parts = []
if fire_row["current_acres"] is not None:
parts.append(f"{int(fire_row['current_acres']):,} ac")
if fire_row["current_contained_pct"] is not None:
parts.append(f"{int(fire_row['current_contained_pct'])}% contained")
# Location via _location_anchor with a minimal normalized dict
loc_dict = {
"lat": fire_row["lat"], "lon": fire_row["lon"],
"county": fire_row["county"], "state": fire_row["state"],
}
anchor = _location_anchor(loc_dict)
if anchor and anchor != "(location unknown)":
parts.append(anchor)
lines = [f"{name} — contained & closed"]
if parts:
lines.append(" | ".join(parts))
wire = "\n".join(lines)
if isinstance(data, dict):
data["category"] = "wildfire_closed"
data["_severity_override"] = "routine"
return wire
return None
# ---- active incident ----