mirror of
https://github.com/zvx-echo6/meshai.git
synced 2026-08-26 17:31:34 +00:00
fix(firms): repair the FIRMS fire-fusion Event contract (issues #117-#119) (#120)
Three independent bugs kept firms_handler's growth/spotting/halt/cluster fusion decisions from reaching a correct mesh Event: - #117: consumer._normalize() computed `category` from the raw Central category BEFORE the per-adapter handler ran and never re-read data["category"] afterward, so every firms_handler category stamp was a silent no-op. Now re-read post-dispatch, validated against the known category registry (unrecognized overrides are logged and ignored). - #118: consumer.py only ever honors data["_severity_override"], but firms_handler's halt/spotting/cluster sites stamped the plain data["severity"] key instead (only growth used the right key). Switched all three sites to `_severity_override` for one consistent contract. This is severity plumbing only -- it does not change which events fire. - #119: FirePacer's gate only matched source in ("fires","wfigs") at severity=="priority", so FIRMS fusion broadcasts (source="firms", growth/spotting at "immediate") never reached the pacer. Broadened the gate to cover "firms" + {"priority","immediate"}, and gave FirePacer head-of-line insertion so an "immediate" event is never stuck behind already-queued "priority" events. Still unbounded/never-drops. Cluster detection is left exactly as main ships it: live, always on, no toggle (PR #73's curated new-fire cluster broadcasts with cold-start silent-seeding). Only its severity-override key changes, under #118. Updated existing tests that asserted the old (buggy) data["severity"] contract, and added tests/test_firms_fusion_event_contract.py covering all three fixes end-to-end through consumer._normalize()/_handle() and FirePacer directly. Co-authored-by: Matt Johnson <mj@k7zvx.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f50c2e54d8
commit
5dd8266abe
10 changed files with 479 additions and 32 deletions
|
|
@ -402,7 +402,7 @@ class TestNotCutoverLegacyVerbatim:
|
|||
wire, data = _drive_spotting("ID-SN", 43.0, -115.0, now=1780768800)
|
||||
assert wire is not None and "spotting" in wire
|
||||
assert data["category"] == "wildfire_spotting"
|
||||
assert data["severity"] == "immediate"
|
||||
assert data["_severity_override"] == "immediate"
|
||||
# Legacy path stamps the latch EAGERLY with the handler `now`.
|
||||
latch = get_db().execute(
|
||||
"SELECT last_spotting_broadcast_at FROM fires WHERE irwin_id=?",
|
||||
|
|
@ -419,7 +419,7 @@ class TestNotCutoverLegacyVerbatim:
|
|||
wire = _maybe_emit_halt(get_db(), data=data, now=now)
|
||||
assert wire == "🔥 Cold Fire no growth in 14h"
|
||||
assert data["category"] == "wildfire_halted"
|
||||
assert data["severity"] == "routine"
|
||||
assert data["_severity_override"] == "routine"
|
||||
latch = get_db().execute(
|
||||
"SELECT halt_broadcast_at FROM fires WHERE irwin_id=?",
|
||||
("ID-HN",)).fetchone()[0]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue