- Tests check current conditions against rule categories/severity
- Shows actual alert messages that would fire right now
- Falls back to example messages from category registry if no matches
- Preview mode shows without sending, Send Test delivers with [TEST] prefix
- Mesh delivery applies real summarization so preview matches actual output
- Added test dialog UI showing conditions matched and preview messages
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Utilization pillar now reads firmware-reported channel_utilization
instead of estimating from packet counts with hardcoded 200ms/pkt
- Uses highest infra node value (busiest node = bottleneck)
- Falls back to packet count estimate only when telemetry unavailable
- Updated thresholds: 20/25/35/45% matching real Meshtastic behavior
- Per-region utilization from region nodes, not mesh-wide
- API response includes util_method, util_max_percent, util_node_count
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Reference page now explains HOW each health pillar is calculated:
- Infrastructure: router online ratio
- Utilization: airtime estimation from packet counts
- Coverage: gateway redundancy with single-gw penalties
- Behavior: flagged node thresholds
- Power: battery warning ratio
Includes actual formulas and special cases.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace fixed overlay with useRef-based click-outside detection
- Add X close button in top-right corner of popover
- Click ? to toggle (open if closed, close if open)
- Click anywhere outside popover to dismiss
- Remove fixed inset-0 overlay that was blocking page interaction
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- SFI/Kp as prominent color-coded values with trend chart
- R/S/G scales as colored severity badges
- Tropospheric ducting condition with refractivity profile
- Environmental feeds replaced with scrolling live event timeline
- Unified activity log across all 9 feed adapters
- Source icons, severity badges, chronological order
- Real-time updates via WebSocket
- SWPC adapter stores Kp/SFI history for charting
- No wasted card space
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Self-contained rules replace abstract channels
- Inline delivery config (broadcast/DM/email/webhook or none)
- quiet_hours_enabled master toggle separate from start/end times
- delivery_type="" valid: rule matches but does not deliver
- Severity dropdown with plain-English descriptions
- Example messages per alert category
- Default baseline rules: Emergency Broadcast, Infrastructure Down, Fire Alert, Severe Weather
- Condition vs Schedule trigger types
- Test and preview buttons per rule
- stream_flood_warning renamed from flood_warning (distinct from packet_flood)
- Categories display with descriptions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Each notification rule contains its own delivery config inline
- No more separate channels with abstract IDs to cross-reference
- Delivery type selector (Mesh Broadcast/DM/Email/Webhook) with
inline config fields per type
- Follows MeshMonitor trigger-action UX pattern
- Channel picker from radio for mesh broadcast
- Node picker for mesh DM
- Collapsed rule cards show readable one-line summary
- Trigger type: condition (alerts) or schedule (daily reports)
- Schedule triggers support daily, weekly, custom cron
- Message types: mesh health, RF propagation, alerts digest, custom
- Migrates old channels+rules config to new flat format on load
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add GET /api/channels endpoint for live radio channel data
- Create ChannelPicker component (single/multi-select from live channels)
- Create NodePicker component (searchable multi-select from mesh nodes)
- Replace manual inputs in Config with data-driven pickers
- Update Notifications to use pickers for mesh broadcast/DM
- Resolve node names in Alerts subscriptions display
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create standalone Notifications.tsx page with full notification config UI
- Add /notifications route in App.tsx
- Add Notifications nav item in Layout.tsx sidebar (below Alerts, BellRing icon)
- Remove notifications section from Config.tsx (keep settings sections only)
- Channels, rules, quiet hours, and dedup all configurable on dedicated page
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Notifications tab in Config sidebar with Bell icon
- Channels section: add/edit/delete channels (mesh broadcast, DM, email, webhook)
- Test button sends test alert to channel
- Rules section: create rules with category checkboxes fetched from API
- Quiet hours configurable with start/end times
- Dedup window to prevent alert spam
- Full helper text and info buttons on every field
- Category list fetched from /api/notifications/categories, not hardcoded
- Added notifications and environmental to VALID_SECTIONS in config_routes.py
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add InfoButton component with click-to-toggle popover for field help
- Add SectionDescription component for section intro paragraphs
- Add AlertRuleToggle component with grouped threshold controls
- Add detailed info and helper text for every field in all sections
- Convert Commands section to toggleable command list with descriptions
- Add dropdowns for severity_min, fire state, connection type, LLM backend
- Add region management: Add/Delete buttons with confirmation
- Group alert rules by category: Infrastructure, Power, Utilization, Health
- Remove hardcoded placeholders and Idaho-specific text
- Fix config.py DashboardConfig dataclass decorator
- Fix main.py MessageRouter initialization
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Full Alerts page with active alerts, history table, subscriptions
- Active alert cards with severity styling and acknowledge button
- Alert history table with type/severity filtering and pagination
- Subscription viewer showing mesh subscriptions
- ToastProvider for app-wide toast notifications
- Toast notifications triggered on WebSocket alert_fired messages
- Auto-dismiss toasts after 8 seconds, click to navigate
- Page titles on all pages (Dashboard/Mesh/Environment/Config/Alerts)
- Improved alert_routes.py with proper pending alert handling
- Added AlertHistoryItem, Subscription types to api.ts
- Added fetchAlertHistory, fetchSubscriptions functions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Implement FIRMSAdapter polling NASA FIRMS area API for satellite hotspots
- Cross-reference hotspots against NIFC perimeters to identify new ignitions
- Add !hotspots command with --new flag for filtering new ignitions only
- Add FIRMSConfig dataclass with map_key, source, bbox, day_range options
- Add /api/env/hotspots endpoint for dashboard integration
- Add Satellite Hotspots section to Environment.tsx with NEW badges
- Add FIRMS configuration section to Config.tsx with source/confidence options
- Update config.example.yaml with FIRMS configuration template
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Timezone now configurable (default America/Boise)
- Router prompt generates region name instructions from config
- Any operator can run MeshAI for their region without code changes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- WFIGS ArcGIS fire perimeter polling with proximity alerts
- Avalanche.org advisory polling (seasonal, SNFAC)
- !fire and !avy commands
- Distance-based severity for fires near mesh infrastructure
- Dashboard environment page integration
- Alert engine fires on fires within 50km of mesh area
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove band_assessment and band_detail from SWPC adapter
- Remove all frequency-specific conclusions (906 MHz, 10m-20m, etc.)
- Store only raw indices: SFI, Kp, R/S/G scales, dM/dz gradients
- Let LLM interpret propagation data based on user's band of interest
- Add full Environment page with feed status, solar indices, and ducting data
- Update Dashboard RF Propagation card to show raw values only
- Update alert messages to be frequency-agnostic
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add catch-all route that serves index.html for any non-API path
- Mount /assets separately for static JS/CSS files
- Enables browser refresh on React Router paths (/mesh, /config, etc.)
- API routes (/api/*) continue to work normally
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
NOAA changed the planetary k-index endpoint from array of arrays
to array of objects. Updated parser to handle both formats.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- FastAPI runs in MeshAI asyncio loop (no separate process)
- REST API: /api/status, /api/health, /api/nodes, /api/edges,
/api/regions, /api/sources, /api/config, /api/alerts
- WebSocket at /ws/live pushes health updates and alerts
- Config CRUD: GET/PUT per section with validation and save
- DashboardConfig with port/host in config.yaml
Packet dedup: track seen packet IDs across all sources. Same packet from
Meshview + MeshMonitor counted once, not twice. Fixes inflated counts.
Portnum: numeric values (3, 4, 71) mapped to names (Position, NodeInfo, Neighbors).
LLM prompt: guidance on normal vs abnormal packet rates per type.
Delays 1.5-2.5s (was 3-5s, only for broadcasts now).
DMs: send → ACK → next immediately. No ACK → retry once → abort.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Alert conditions across all 5 pillars:
Infrastructure: offline, recovery, new router
Power: battery 50/25/10%, 7-day trend, USB→battery, solar not charging
Utilization: sustained >20% for 6h, packet flood >500/24h
Coverage: infra single gateway, feeder offline, region blackout
Scores: mesh <70, region <60
Scaling cooldown: immediate → 12h → 24h → 48h → stop
Recovery notifications when conditions resolve
Per-condition on/off toggles in TUI
Battery trend queries SQLite node_snapshots for 7-day history
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- build_lora_compact returns list[str] instead of str
- Each line is a separate LoRa message (no chunking needed)
- main.py handles list responses from commands
- _try_compute_distance supports partial names (TVM Pearl → TVM Pearl Relay)
- Ambiguous names detected (TVM → asks which node)
- Max message size: 54 bytes (well under 228 byte limit)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
!health: 🔵 perfect, 🟢 healthy, 🟠 warning, 🔴 critical — no /100 scores.
Each line ends with period for separate LoRa messages.
Uses long_name to avoid emoji shortnames (📡 → TVM Tablerock Relay).
Distance from AIDA shown on every infra node in Tier 1.
Router detects how far questions and injects computed distance.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Commands now chunk output same as LLM responses
- split_sentences splits on newlines first for !health output
- chunk_response uses byte counting instead of character counting
- Emojis and UTF-8 properly counted for 228-byte LoRa limit
- !health 274 bytes now splits into 2 messages (195 + 74 bytes)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace build_lora_compact with personality version using emojis
- Add _region_lora_compact helper for region-specific display
- Skip empty regions in 3 loops (build_tier1_summary, utilization, list_regions_compact)
- Update AIDA identity: she IS a physical node (!27780c47 AIDA-N2)
- AIDA now knows she has real GPS coordinates and radio connections
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add build_distance() method to MeshReporter
- Uses _haversine_km() for GPS distance calculation
- Formats output with both km and miles
- Handles missing nodes or GPS positions gracefully
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add max_response_tokens config (8192) to LLMConfig
- Use config value in router.py instead of hardcoded 500
- Update base.py default from 300 to 8192
- Lets LLM generate full responses; chunker handles size limits
Fixes truncated responses like Here are three nodes in the freq
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
These methods were called by commands/health.py and main.py but missing
from mesh_reporter.py, causing crashes on !health and !region commands.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added hops_away to Connectivity section in node detail
- Added nearest infra distance after Position in node detail
- Added distance from reference infra to single-gw client listings
- Added _haversine_km and _format_distance helper functions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>