meshai/tests
matt+claude c2d5bcfbd1 feat(central): v0.5.4 -- region-aware subscriptions using Central v0.9.20 regional subjects
Pre-v0.5.4 every Central subscription used a bare wildcard (central.wx.>,
central.fire.>, central.traffic.>, central.quake.>, central.hydro.>,
central.space.>), so a Magic Valley operator flipping nws -> central was
in fact subscribing to the all-US firehose and discarding 95% of events
locally. Central v0.9.20 (2026-05-28) added per-region subject suffixes
so the firehose can be filtered server-side. This wires meshai to use them.

Backend (meshai/central/consumer.py):
- New _subjects_for(adapter, region) replaces the static ADAPTER_SUBJECTS
  dict. ADAPTER_SUBJECTS is retained as an alias to _SUBJECTS_BARE for any
  legacy importers; the dispatcher path is unchanged.
- Per-adapter subject patterns (region='us.id' default):
    nws        -> central.wx.alert.us.id.>     (region BEFORE wildcard)
    usgs_quake -> central.quake.event.>.us.id  (region AFTER wildcard)
    firms      -> central.fire.hotspot.>.us.id
    fires      -> central.fire.incident.id.>   (state token at fixed depth)
                  central.fire.perimeter.id.>
    traffic    -> central.traffic.>.id          (bare state, no us. prefix)
    roads511   -> central.traffic.>.id          (shared with traffic, sub-adapter routing)
    usgs       -> central.hydro.>.us.id
                  central.hydro.>.unknown      (workaround until v0.9.20.1)
    swpc       -> central.space.>               (planetary; region ignored)
- Empty/None region falls back to bare wildcards (pre-v0.9.20 behaviour).
- _subject_owned() pulls region from env.central.region and routes through
  _subjects_for; v0.5.3 sub-adapter routing (owned-sources set) still
  applies on shared subjects like central.traffic.>.id.
- start() logs the active region at connect-time for ops visibility.

Config (meshai/config.py):
- CentralConsumerConfig.region: str = "us.id". One region per consumer
  applies to every central-flipped adapter; per-adapter overrides can
  land in v0.6 when there is a real use case.

Frontend (dashboard-frontend/src/pages/Environment.tsx):
- Central Connection panel gets a Region text input next to URL/Durable.
- EnvConfig.central type extended with region: string.
- Static bundle rebuilt; index-DCFmSeOM.js -> index-B24tHcYj.js.

Tests:
- tests/test_central_region_routing.py (new, 9 cases): asserts the exact
  v0.9.20 subject string for each adapter at region='us.id', the SWPC
  global-stays-global rule, the USGS .unknown workaround, the empty-region
  backward-compat fallback for all 8 adapters, and integration through
  CentralConsumer._subject_owned() with the default region.
- tests/test_central_consumer.py + tests/test_central_sub_adapter_routing.py:
  the two tests that asserted bare-wildcard subjects now set
  env.central.region = "" explicitly to preserve their original concern
  (no region semantics — backward-compat path only).

Why swpc stays global: space weather is planetary -- a CME is detected on
the sun, the geomagnetic response is hemispheric. There is no Idaho-only
solar event; subscribing per-region would only drop events we want.

Why hydro has the .unknown workaround: Central v0.9.20 leaves gauges
whose USGS state can't be inferred on central.hydro.>.unknown. Until
v0.9.20.1 backfills the state tag we subscribe to both filters to
avoid silently losing those rows. Idaho downstream-filtering on
data['_enriched']['usgs_site']['state'] is future v0.6 work.

Orthogonal to v0.5.2 dispatcher guards (staleness / cooldown / dedup)
and v0.5.3 sub-adapter routing: the region filter operates at the NATS
subscription layer (server-side), upstream of everything else.

Verified: pytest 327 passed (318 prior + 9 new region-routing tests);
py_compile clean; frontend build clean. Safe-mode preserved -- no toggle
enabled, no master enabled, no central enabled.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-04 02:30:33 +00:00
..
test_adapter_avalanche.py feat(notifications): Phase 2.10 avalanche adapter pipeline integration 2026-05-27 23:08:24 +00:00
test_adapter_ducting.py feat(notifications): Phase 2.13 ducting adapter threshold-crossing emission (severity-tiered, Option C) 2026-05-28 00:01:40 +00:00
test_adapter_fires.py feat(notifications): Phase 2.11 NIFC fires adapter pipeline integration 2026-05-27 23:33:48 +00:00
test_adapter_firms.py feat(env): Phase 2.6 FIRMS adapter emits Events to pipeline bus 2026-05-15 05:23:00 +00:00
test_adapter_nws.py feat(notifications): Phase 2.6 NWS adapter pipeline integration 2026-05-15 04:47:31 +00:00
test_adapter_roads511.py feat(notifications): Phase 2.8 roads511 adapter pipeline integration 2026-05-27 21:18:21 +00:00
test_adapter_swpc.py feat(notifications): Phase 2.12 SWPC space weather adapter + dedup fix 2026-05-27 23:41:30 +00:00
test_adapter_traffic.py feat(notifications): Phase 2.7 traffic adapter pipeline integration 2026-05-27 19:17:27 +00:00
test_adapter_usgs.py feat(notifications): Phase 2.9 usgs water adapter pipeline integration 2026-05-27 21:58:13 +00:00
test_adapter_usgs_quake.py feat(notifications): Phase 2.14 USGS earthquake adapter (new) -- closes Rule 16 Seismic standalone path 2026-05-28 00:10:39 +00:00
test_central_consumer.py feat(central): v0.5.4 -- region-aware subscriptions using Central v0.9.20 regional subjects 2026-06-04 02:30:33 +00:00
test_central_region_routing.py feat(central): v0.5.4 -- region-aware subscriptions using Central v0.9.20 regional subjects 2026-06-04 02:30:33 +00:00
test_central_sub_adapter_routing.py feat(central): v0.5.4 -- region-aware subscriptions using Central v0.9.20 regional subjects 2026-06-04 02:30:33 +00:00
test_channel_rendering.py feat(notifications): Phase 2.5b per-channel-type renderers 2026-05-15 04:25:44 +00:00
test_config_loader.py fix(notifications): Phase 2.16.1 unblock pipeline -- grouper flush + rules coercion + toggle warning 2026-05-28 00:36:13 +00:00
test_config_source_field.py feat(central): v0.4 C.1 Central connector backend (no-op until adapter source flipped) 2026-05-28 02:28:19 +00:00
test_dashboard_config_save.py fix(dashboard): v0.4 C.2.1 -- route PUT /config to multi-file save_section (Rule 17 persistence unblocked) 2026-05-28 03:17:30 +00:00
test_notification_toggles.py feat(notifications): v0.5.0 -- Master Toggles UX redesign + Central Connection GUI + grouped categories + region scoping 2026-05-28 07:00:10 +00:00
test_pipeline_digest.py fix(notifications): inject llm_backend into build_pipeline 2026-05-15 03:08:31 +00:00
test_pipeline_grouper.py fix(notifications): Phase 2.16.1 unblock pipeline -- grouper flush + rules coercion + toggle warning 2026-05-28 00:36:13 +00:00
test_pipeline_inhibitor_grouper.py fix(notifications): Phase 2.16.1 unblock pipeline -- grouper flush + rules coercion + toggle warning 2026-05-28 00:36:13 +00:00
test_pipeline_scheduler.py feat(notifications): Phase 2.5a channel interface unification 2026-05-15 03:45:27 +00:00
test_pipeline_skeleton.py feat(notifications): Phase 2.5a channel interface unification 2026-05-15 03:45:27 +00:00
test_pipeline_toggle_filter.py fix(notifications): inject llm_backend into build_pipeline 2026-05-15 03:08:31 +00:00
test_renderers.py feat(notifications): Phase 2.5b per-channel-type renderers 2026-05-15 04:25:44 +00:00
test_save_section_secret_preserve.py fix(central): v0.4 C.3.1 -- preserve secret refs in save_section + deliver_policy=NEW (no backlog flood) 2026-05-28 04:55:20 +00:00
test_v052_dispatcher.py fix(notifications): v0.5.2 -- staleness filter, cooldown, dedup, renderer wiring, hydro family 2026-06-04 00:40:28 +00:00