mirror of
https://github.com/zvx-echo6/meshai.git
synced 2026-05-21 15:14:45 +02:00
fix(notifications): complete severity cleanup to 3-level system
- Replace 11 info fallbacks with routine in router.py + channels.py - Replace 2 warning min_severity defaults with priority - Update config.example.yaml rules to use routine/priority/immediate - Annotate config.example.yaml notifications section as transitional pending v0.3 8-toggle rewrite Phase 1.2 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
95ec7d5351
commit
344ca0677d
4 changed files with 24 additions and 22 deletions
|
|
@ -217,11 +217,13 @@ environmental:
|
|||
proximity_km: 10.0 # km to match known fire perimeters
|
||||
|
||||
|
||||
# === NOTIFICATION DELIVERY ===
|
||||
# === NOTIFICATION DELIVERY (TRANSITIONAL) ===
|
||||
# NOTE: This notifications schema will be replaced in v0.3 by the 8-toggle model.
|
||||
# These rule examples are transitional until Phase 1.2 lands. Do not extend.
|
||||
# Severity levels: routine (informational), priority (needs attention), immediate (act now)
|
||||
#
|
||||
# Route alerts to channels (mesh, email, webhook) based on rules.
|
||||
# Categories match alert types from alert_engine.py.
|
||||
# Severity levels: info, advisory, watch, warning, critical, emergency
|
||||
#
|
||||
notifications:
|
||||
enabled: false
|
||||
quiet_hours_enabled: true # Master toggle for quiet hours feature
|
||||
|
|
@ -236,7 +238,7 @@ notifications:
|
|||
enabled: true
|
||||
trigger_type: condition
|
||||
categories: [] # Empty = all categories
|
||||
min_severity: "emergency"
|
||||
min_severity: "immediate"
|
||||
delivery_type: mesh_broadcast
|
||||
broadcast_channel: 0
|
||||
cooldown_minutes: 5
|
||||
|
|
@ -247,7 +249,7 @@ notifications:
|
|||
enabled: true
|
||||
trigger_type: condition
|
||||
categories: ["infra_offline", "critical_node_down"]
|
||||
min_severity: "warning"
|
||||
min_severity: "priority"
|
||||
delivery_type: mesh_broadcast
|
||||
broadcast_channel: 0
|
||||
cooldown_minutes: 30
|
||||
|
|
@ -258,7 +260,7 @@ notifications:
|
|||
enabled: true
|
||||
trigger_type: condition
|
||||
categories: ["wildfire_proximity", "new_ignition"]
|
||||
min_severity: "advisory"
|
||||
min_severity: "routine"
|
||||
delivery_type: mesh_broadcast
|
||||
broadcast_channel: 0
|
||||
cooldown_minutes: 60
|
||||
|
|
@ -269,7 +271,7 @@ notifications:
|
|||
enabled: true
|
||||
trigger_type: condition
|
||||
categories: ["weather_warning"]
|
||||
min_severity: "warning"
|
||||
min_severity: "priority"
|
||||
delivery_type: mesh_broadcast
|
||||
broadcast_channel: 0
|
||||
cooldown_minutes: 30
|
||||
|
|
@ -280,7 +282,7 @@ notifications:
|
|||
# enabled: true
|
||||
# trigger_type: condition
|
||||
# categories: ["wildfire_proximity", "new_ignition"]
|
||||
# min_severity: "advisory"
|
||||
# min_severity: "routine"
|
||||
# delivery_type: email
|
||||
# smtp_host: "smtp.gmail.com"
|
||||
# smtp_port: 587
|
||||
|
|
@ -296,7 +298,7 @@ notifications:
|
|||
# enabled: true
|
||||
# trigger_type: condition
|
||||
# categories: []
|
||||
# min_severity: "warning"
|
||||
# min_severity: "priority"
|
||||
# delivery_type: webhook
|
||||
# webhook_url: "https://discord.com/api/webhooks/..."
|
||||
# cooldown_minutes: 10
|
||||
|
|
@ -316,7 +318,7 @@ notifications:
|
|||
# enabled: true
|
||||
# trigger_type: condition
|
||||
# categories: ["battery_warning"]
|
||||
# min_severity: "warning"
|
||||
# min_severity: "priority"
|
||||
# delivery_type: "" # Empty = no delivery, just tracks matches
|
||||
|
||||
# === WEB DASHBOARD ===
|
||||
|
|
|
|||
|
|
@ -578,7 +578,7 @@ def _migrate_legacy_channels(notifications, data: dict):
|
|||
enabled=ch.get("enabled", True),
|
||||
trigger_type="condition",
|
||||
categories=old_rule.get("categories", []),
|
||||
min_severity=old_rule.get("min_severity", "warning"),
|
||||
min_severity=old_rule.get("min_severity", "priority"),
|
||||
delivery_type=ch.get("type", "mesh_broadcast"),
|
||||
broadcast_channel=ch.get("channel_index", 0),
|
||||
node_ids=ch.get("node_ids", []),
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ class EmailChannel(NotificationChannel):
|
|||
return False
|
||||
|
||||
alert_type = alert.get("type", "alert")
|
||||
severity = alert.get("severity", "info").upper()
|
||||
severity = alert.get("severity", "routine").upper()
|
||||
message = alert.get("message", "")
|
||||
subject = "[MeshAI %s] %s" % (severity, alert_type.replace("_", " ").title())
|
||||
body = "MeshAI Alert\n\nType: %s\nSeverity: %s\nTime: %s\n\n%s\n\n---\nAutomated message from MeshAI." % (
|
||||
|
|
@ -518,7 +518,7 @@ class WebhookChannel(NotificationChannel):
|
|||
"""POST alert to webhook URL."""
|
||||
payload = {
|
||||
"type": alert.get("type"),
|
||||
"severity": alert.get("severity", "info"),
|
||||
"severity": alert.get("severity", "routine"),
|
||||
"message": alert.get("message", ""),
|
||||
"timestamp": time.time(),
|
||||
"node_name": alert.get("node_name"),
|
||||
|
|
@ -527,7 +527,7 @@ class WebhookChannel(NotificationChannel):
|
|||
|
||||
# Discord/Slack format
|
||||
if "discord.com" in self._url or "slack.com" in self._url:
|
||||
severity = alert.get("severity", "info")
|
||||
severity = alert.get("severity", "routine")
|
||||
color = {
|
||||
"immediate": 0xFF0000,
|
||||
"priority": 0xFFAA00,
|
||||
|
|
@ -669,7 +669,7 @@ class WebhookChannel(NotificationChannel):
|
|||
else:
|
||||
payload = {
|
||||
"type": "test",
|
||||
"severity": "info",
|
||||
"severity": "routine",
|
||||
"message": "MeshAI channel connectivity test",
|
||||
"timestamp": time.time(),
|
||||
}
|
||||
|
|
@ -730,7 +730,7 @@ class WebhookChannel(NotificationChannel):
|
|||
async def deliver_test(self, message: str) -> tuple[bool, str]:
|
||||
"""Deliver a specific test message via webhook."""
|
||||
try:
|
||||
test_alert = {"type": "test", "severity": "info", "message": message}
|
||||
test_alert = {"type": "test", "severity": "routine", "message": message}
|
||||
success = await self.deliver(test_alert, {})
|
||||
if success:
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ class NotificationRouter:
|
|||
async def process_alert(self, alert: dict) -> bool:
|
||||
"""Route an alert through matching rules."""
|
||||
category = alert.get("type", "")
|
||||
severity = alert.get("severity", "info")
|
||||
severity = alert.get("severity", "routine")
|
||||
delivered = False
|
||||
|
||||
for rule in self._rules:
|
||||
|
|
@ -160,7 +160,7 @@ class NotificationRouter:
|
|||
if rule_categories and category not in rule_categories:
|
||||
continue
|
||||
|
||||
min_severity = rule.get("min_severity", "info")
|
||||
min_severity = rule.get("min_severity", "routine")
|
||||
if not self._severity_meets(severity, min_severity):
|
||||
continue
|
||||
|
||||
|
|
@ -392,7 +392,7 @@ class NotificationRouter:
|
|||
|
||||
rule_name = rule_dict.get("name", f"Rule {rule_index}")
|
||||
rule_categories = rule_dict.get("categories", [])
|
||||
min_severity = rule_dict.get("min_severity", "info")
|
||||
min_severity = rule_dict.get("min_severity", "routine")
|
||||
delivery_type = rule_dict.get("delivery_type", "")
|
||||
|
||||
# Legacy support
|
||||
|
|
@ -536,7 +536,7 @@ class NotificationRouter:
|
|||
for alert in alert_engine.get_pending_alerts():
|
||||
all_events.append({
|
||||
"type": alert.get("type", ""),
|
||||
"severity": alert.get("severity", "info"),
|
||||
"severity": alert.get("severity", "routine"),
|
||||
"message": alert.get("message", ""),
|
||||
"headline": alert.get("message", "")[:80],
|
||||
})
|
||||
|
|
@ -548,7 +548,7 @@ class NotificationRouter:
|
|||
for event in env_store.get_active():
|
||||
all_events.append({
|
||||
"type": event.get("type", event.get("category", "")),
|
||||
"severity": event.get("severity", "info"),
|
||||
"severity": event.get("severity", "routine"),
|
||||
"message": event.get("message", event.get("headline", str(event))),
|
||||
"headline": event.get("headline", event.get("message", "Event"))[:80],
|
||||
})
|
||||
|
|
@ -761,7 +761,7 @@ class NotificationRouter:
|
|||
"enabled": True,
|
||||
"trigger_type": "condition",
|
||||
"categories": categories if categories else [],
|
||||
"min_severity": "warning",
|
||||
"min_severity": "priority",
|
||||
"delivery_type": "mesh_dm",
|
||||
"node_ids": [node_id],
|
||||
"cooldown_minutes": 10,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue