- Wrap each adapter registration in try/except via _register_adapter()
- Track failed adapters in _failed_adapters dict with error message
- Add get_status() method for /api/env/status to report failed adapters
- No single adapter failure can abort loading of remaining adapters
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace bg-slate-800/60 and bg-slate-800 with bg-bg-card/bg-bg
- Replace border-slate-700 with border-border
- Replace divide-slate-700/60 with divide-border
- Replace hover:bg-slate-800/50 and hover:bg-slate-700 with hover:bg-bg-hover
- Remove all rounded classes for sharp Carbon edges
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
text-[#333] → text-[#666] (63 hits), text-[#444] → text-[#777] (38 hits)
across all tsx/css. Scrollbar thumb #1e1e1e → #2a2a2a.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Global: removed all rounded-lg/md/sm classes, replaced blue-500 with
sky-400 informational, cyan accents with amber across all tsx files.
Environment.tsx + AdapterConfig.tsx: full Carbon color sweep — slate
hierarchy replaced with #333/#444/white tokens, border-border tokens,
font-sans labels, font-mono values. Layout.tsx logo text-[15px].
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Carbon palette: #111111/#0d0d0d backgrounds, #1e1e1e borders, traffic-light
data colors (green/red/sky/amber), 10px uppercase card headers, StatCard
colored border-tops, Layout sidebar amber bar + right nav indicator.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Tailwind config: semantic color tokens (amber/blue/danger), borderRadius all zero except full, Inter + JetBrains Mono font families
- index.css: Google Fonts imports, sharp scrollbar, scanline card texture, amber-glow utility
- Dashboard.tsx: three-color accent system (amber primary, blue informational, danger alerts), Inter for labels/prose, JetBrains Mono strictly for data values, all rounded corners removed, tighter spacing (p-4 cards, gap-4 grids, space-y-2 lists), underline-style tabs with amber active indicator, band condition dot indicators, source status dots remapped to semantic colors, StatCard supports per-instance value coloring, 36px minimum touch targets on interactive elements
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Active Alerts panel now has pill-style tab switcher (Active Alerts | Event Feed)
- LiveEventFeed supports embedded mode (no card wrapper) for tab use
- HepburnTropoCard moved from bottom row to middle row (replaces LiveEventFeed)
- Bottom row removed (empty after tropo card move)
- Fixed broken unicode escapes in BandConditionsCard (satellite, circle, moon emoji)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds HepburnTropoCard to the dashboard with a 23-region dropdown
selector. Selected region is persisted to adapter_config via
(dashboard, tropo_region) key, defaulting to wam (Western North
America). Image loads from dxinfocentre.com/tr_map/fcst/{code}006.png
with date-based cache busting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The periodic health_update in main.py only sent score/tier/totals but
no pillars dict. Dashboard setHealth() replaced the full REST response
with this incomplete object, causing all pillar bars to drop to 0.0.
Now sends the complete payload matching mesh_routes.py and ws.py
(pillars, util_percent, flagged_nodes, battery_warnings, recommendations)
and gates on composite > 0 + infra_total > 0 to skip partial state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Coverage pillar was added to mesh_routes.py in 15f2b6c but missed in
the WebSocket serializer, sending undefined for coverage on every WS
push. Also gates the initial health_update broadcast on composite > 0
and infra_total > 0 to prevent partially-initialized HealthScore from
overwriting good REST-fetched data on the frontend.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- /api/env/active: direct DB queries for fires, nws_alerts, quake_events
instead of env_store.get_active() (which depends on live NATS data)
- /api/env/swpc: reads band_conditions_broadcasts table, returns ratings
with slot label (Day/Night Propagation) derived from Mountain Time
- Frontend: replace RFPropagationCard (SFI/Kp/R/S/G charts) with
BandConditionsCard showing 4-band Good/Fair/Poor ratings
- Remove unused recharts dependency from Dashboard.tsx
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
100.100.100.100 resolves .echo6.mesh hostnames (including
central.echo6.mesh for the NATS bus). 1.1.1.1 provides fallback
for public DNS when MagicDNS is unavailable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Without this branch, the environmental config dict falls through to the
bare else clause, storing a raw dict instead of an EnvironmentalConfig
dataclass. This causes AttributeError when accessing env_cfg.enabled or
any nested feed config attributes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add coverage pillar to /api/health response and _serialize_health_score
- Add coverage to MeshHealth.pillars TypeScript interface
- Add Coverage PillarBar between Utilization and Behavior
- Active Alerts panel: show high-severity env events (immediate/priority)
as fallback when mesh alerts are empty, with ENV badge
Issues 3 (Live Event Feed) and 4 (RF Propagation): diagnosed as
env feed configuration — SWPC adapter disabled, only ducting feed
loaded, /api/env/active returns 0 events. Not a code bug.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add _is_update() helper that checks CAP references field against
nws_alerts table. When any referenced CAP id has last_broadcast_at
set, the wire gets an Update: prefix via _render(prefix=). Applied
in both the new-alert and cold-start-race branches.
References field shape: list of dicts with identifier key containing
the superseded CAP id (urn:oid:...).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace hardcoded 50-char area cap with adapter_config key
nws.area_max_chars (default 80). Truncation now appends ellipsis when
cut, matching the locations_max_chars pattern from the prior commit.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace hardcoded 40-char locations cap with adapter_config key
nws.locations_max_chars (default 120). Truncation now uses word-boundary
split with ellipsis, matching the swpc _trunc pattern.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Stamp last_spotting_broadcast_at on all 23 active fires before enabling
the detector, preventing false positives on first pixel after deploy.
Remove the return None stub from _check_spotting so the convex-hull
perimeter + cooldown logic runs on every attributed FIRMS pixel.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
In-memory dict keyed on scale_code (G1-G5) with 600s suppression window.
Only geomag events are deduplicated — flare and proton sub-types have no
cross-adapter overlap. Suppressed events still persist to swpc_events and
event_log (handled=0) for audit trail.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds _trunc() helper that cuts at last space before 120 chars and appends
ellipsis. Applied at extraction site and all four _render line2 branches.
Line 3 (SWPC · timestamp) is a formatted fixed string — left unchanged.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
swpc_handler.py: rewrite _render() to multi-line format (emoji + New:
prefix + scale/type — detail line — SWPC · time tag). Extract message
and time fields from envelope for line 2/3.
Environment.tsx: replace empty SWPC panel with broadcast threshold
controls — geomag Kp floor (G1-G5), flare class floor (M1-X10),
proton pfu floor (S1-S4). Full adapter_config save/load/discard wiring.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Query now filters out 100% contained and >7d stale fires. Line format
uses county-only anchor (no Photon geocoder). Greedy 220-byte packing
ensures the digest fits in a single Meshtastic frame.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds (reminders_wfigs, enabled) to REGISTRY (default=False) and
gates _tick_adapter() on the flag — when false, wfigs fire reminders
are skipped entirely. Use the digest instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>