mirror of
https://github.com/zvx-echo6/meshai.git
synced 2026-08-26 17:31:34 +00:00
* chore: excise the dead Central NATS consumer path
Central was retired and its database dropped 2026-07-15; its NATS broker no
longer exists. Verified against the live CT108 deployment: all 12 adapters
run feed_source=native, zero on central, and central.enabled is False
(default, never overridden). The consumer and its handlers were unreachable.
Removed:
- central/consumer.py and 6 dead handlers (nws, quake, swpc, nwis, avy,
incident) -- their handle_* entrypoints were reachable only from the
consumer's dispatch
- the Central wiring in main.py (init, guarded start, retry loop, stop path)
- the dead config surface: CentralConsumerConfig, EnvironmentalConfig.central,
adapter_config ("central","severity_thresholds") and its display block
- the nats-py dependency (consumer.py was its only importer)
- 19 test files that exercised only the dead path
KEPT -- these live under central/ but are imported directly by native
adapters, and deleting them would break production:
- wfigs_handler.py: firms_handler._handle_pass_boundary() calls its _render()
on the live FIRMS growth-fire path (env/firms.py -> ingest_hotspot_pixel)
- firms_handler, satpass_handler, tle_handler: split files whose handle_*
entrypoints are dead but whose engines are live. Left intact; splitting
them is separate work.
- pass_predictor, budget, idaho_gauge_sites: fully live.
The usgs_quake keys global_mag_floor / regional_mag_floor / regional_centroid
/ regional_radius_mi / broadcast_pager_alerts are NOT removed despite comments
labelling them "CENTRAL-PATH ONLY" -- notifications/gating/quake.py reads them
unconditionally in the native path. Those comments are corrected separately.
Test-count note: the suite drops ~425 tests. Most were migration PARITY tests
whose sole purpose was proving the native rewrite byte-matched the Central
handler (golden byte-parity, cross-source identity, gate-sequence replay).
With the handler deleted there is nothing left to compare against, so they
cannot exist. Native-only tests were kept and reworked where a test reached
for a central symbol incidentally. This is a real coverage loss, accepted
deliberately: the parity harness proved the refactor faithful, and git
history preserves the originals.
Suite: 1984 passed, 6 failed -- the same 6 pre-existing failures as main
(stale SCHEMA_VERSION x3, expired TLE fixtures x2, one order-dependent),
all being fixed on fix/green-test-suite. No new failures.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(nws): restore native-only golden coverage for the wire formatter
Commit ca751fb5 deleted the Central nws_handler parity harness along with
the handler itself, which took the ONLY tests that pinned formatters.nws
.format()'s literal wire output. Gate-sequence and schema-conformance
tests already survived natively; the formatter's actual rendered text did
not have any native-only regression net.
Add TestFormatterGolden to test_nws_refactor.py: 3 real-fixture cases plus
6 hand-built pathological cases mined from the deleted test_nws_handler.py
(SVR path-sampling, the "no dangling separator" regression, TOR on-ground
vs radar-indicated, FFW flood-cause detection). Every literal was verified
by temporarily restoring the pre-excision central.nws_handler._render()
from git history (ca751fb5^) in a throwaway, uncommitted script, confirming
byte-identical output against the current native format() for all 37 real
fixtures (nws/ + nws_last/) and all 9 pathological cases, then pinning the
confirmed-matching string as the literal -- not a blind snapshot of
current behavior.
quake/swpc/avalanche/hydro/incident/fire were checked and already carry
equivalent native-only golden coverage (added directly in ca751fb5), so no
changes were needed there.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Matt Johnson <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
192 lines
6.4 KiB
Python
192 lines
6.4 KiB
Python
"""Tests for satpass event path — wire adapter names route correctly.
|
|
|
|
Verifies:
|
|
- celestrak_tle envelope routes to tle_handler and inserts sat_tles row
|
|
- n2yo_visualpasses envelope routes to satpass_handler
|
|
- satpass_predict envelope routes to satpass_handler
|
|
- adapter_config reads min_elevation (not min_elevation_deg)
|
|
- CENTRAL_ADAPTER_TO_SOURCE maps wire names to 'satpass'
|
|
- stale adapter names removed from dispatch
|
|
"""
|
|
|
|
import json
|
|
import time
|
|
|
|
import pytest
|
|
|
|
|
|
# ── Realistic wire envelopes ────────────────────────────────────────
|
|
|
|
CELESTRAK_TLE_ENVELOPE = {
|
|
"specversion": "1.0",
|
|
"id": "tle-25544-1718200000",
|
|
"source": "central",
|
|
"type": "central.sat.tle",
|
|
"data": {
|
|
"id": "tle-25544-1718200000",
|
|
"adapter": "celestrak_tle",
|
|
"category": "sat.tle",
|
|
"data": {
|
|
"norad_id": 25544,
|
|
"satellite_name": "ISS (ZARYA)",
|
|
"tle_line1": "1 25544U 98067A 26163.51782528 .00020000 00000-0 35000-3 0 9999",
|
|
"tle_line2": "2 25544 51.6416 247.4627 0006703 130.5360 325.0288 15.49815002 17",
|
|
"epoch": "2026-06-12T12:25:40Z",
|
|
},
|
|
},
|
|
}
|
|
|
|
N2YO_PASS_ENVELOPE = {
|
|
"specversion": "1.0",
|
|
"id": "pass-25544-twinfalls-1718300000",
|
|
"source": "central",
|
|
"type": "central.sat.pass",
|
|
"data": {
|
|
"id": "pass-25544-twinfalls-1718300000",
|
|
"adapter": "n2yo_visualpasses",
|
|
"category": "sat.pass",
|
|
"data": {
|
|
"norad_id": 25544,
|
|
"sat_name": "ISS (ZARYA)",
|
|
"observer": "Twin Falls",
|
|
"max_elevation": 72.5,
|
|
"aos": "2026-06-13T04:15:00Z",
|
|
"los": "2026-06-13T04:21:30Z",
|
|
"direction": "visible",
|
|
},
|
|
},
|
|
}
|
|
|
|
SATPASS_PREDICT_ENVELOPE = {
|
|
"specversion": "1.0",
|
|
"id": "pass-25544-boise-1718300500",
|
|
"source": "central",
|
|
"type": "central.sat.pass",
|
|
"data": {
|
|
"id": "pass-25544-boise-1718300500",
|
|
"adapter": "satpass_predict",
|
|
"category": "sat.pass",
|
|
"data": {
|
|
"norad_id": 25544,
|
|
"sat_name": "ISS (ZARYA)",
|
|
"observer": "Boise",
|
|
"max_elevation": 45.0,
|
|
"aos": "2026-06-13T04:20:00Z",
|
|
"los": "2026-06-13T04:26:00Z",
|
|
"direction": "visible",
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
def _enable_satpass():
|
|
"""Set satpass.enabled=true in the test DB."""
|
|
from meshai.persistence import get_db
|
|
from meshai.adapter_config import invalidate_cache
|
|
conn = get_db()
|
|
conn.execute(
|
|
"UPDATE adapter_config SET value_json='true' "
|
|
"WHERE adapter='satpass' AND key='enabled'"
|
|
)
|
|
invalidate_cache()
|
|
|
|
|
|
# ── TLE handler route ──────────────────────────────────────────────
|
|
|
|
def test_tle_handler_inserts_sat_tles_row():
|
|
"""A celestrak_tle envelope must land a row in sat_tles."""
|
|
from meshai.central.tle_handler import handle_tle
|
|
from meshai.persistence import get_db
|
|
|
|
_enable_satpass()
|
|
|
|
# Reset the disabled-logged flag if set
|
|
if hasattr(handle_tle, "_disabled_logged"):
|
|
del handle_tle._disabled_logged
|
|
|
|
result = handle_tle(
|
|
CELESTRAK_TLE_ENVELOPE,
|
|
"central.sat.tle.25544",
|
|
now=int(time.time()),
|
|
)
|
|
|
|
# TLE handler always returns None (storage-only)
|
|
assert result is None
|
|
|
|
conn = get_db()
|
|
row = conn.execute(
|
|
"SELECT norad_id, name, line1, line2, epoch FROM sat_tles WHERE norad_id=25544"
|
|
).fetchone()
|
|
assert row is not None, "TLE row not inserted into sat_tles"
|
|
assert row["name"] == "ISS (ZARYA)"
|
|
assert row["line1"].startswith("1 25544U")
|
|
assert row["line2"].startswith("2 25544")
|
|
assert row["epoch"] == "2026-06-12T12:25:40Z"
|
|
|
|
|
|
def test_tle_handler_drops_when_disabled():
|
|
"""When satpass.enabled=false, TLE handler drops and returns None."""
|
|
from meshai.central.tle_handler import handle_tle
|
|
from meshai.persistence import get_db
|
|
|
|
# enabled=false is the default from conftest seed
|
|
if hasattr(handle_tle, "_disabled_logged"):
|
|
del handle_tle._disabled_logged
|
|
|
|
result = handle_tle(
|
|
CELESTRAK_TLE_ENVELOPE,
|
|
"central.sat.tle.25544",
|
|
now=int(time.time()),
|
|
)
|
|
assert result is None
|
|
|
|
conn = get_db()
|
|
row = conn.execute(
|
|
"SELECT norad_id FROM sat_tles WHERE norad_id=25544"
|
|
).fetchone()
|
|
assert row is None, "TLE row should NOT be inserted when disabled"
|
|
|
|
|
|
# ── Pass handler route ──────────────────────────────────────────────
|
|
|
|
def test_satpass_handler_accepts_n2yo_envelope():
|
|
"""n2yo_visualpasses must not be rejected by the adapter guard."""
|
|
inner = N2YO_PASS_ENVELOPE["data"]
|
|
adapter = inner.get("adapter")
|
|
assert adapter == "n2yo_visualpasses"
|
|
assert adapter in ("n2yo_visualpasses", "satpass_predict")
|
|
|
|
|
|
def test_satpass_handler_accepts_satpass_predict_envelope():
|
|
"""satpass_predict must not be rejected by the adapter guard."""
|
|
inner = SATPASS_PREDICT_ENVELOPE["data"]
|
|
adapter = inner.get("adapter")
|
|
assert adapter == "satpass_predict"
|
|
assert adapter in ("n2yo_visualpasses", "satpass_predict")
|
|
|
|
|
|
def test_satpass_handler_rejects_wrong_adapter():
|
|
"""An envelope with adapter='celestrak_tle' must be rejected."""
|
|
from meshai.central.satpass_handler import handle_satpass
|
|
if hasattr(handle_satpass, "_disabled_logged"):
|
|
del handle_satpass._disabled_logged
|
|
result = handle_satpass(CELESTRAK_TLE_ENVELOPE, "central.sat.tle.25544")
|
|
assert result is None
|
|
|
|
|
|
# ── Config key consistency ──────────────────────────────────────────
|
|
|
|
def test_registry_has_min_elevation_not_deg():
|
|
"""The REGISTRY key must be 'min_elevation', not 'min_elevation_deg'."""
|
|
from meshai.adapter_config.defaults import REGISTRY
|
|
assert ("satpass", "min_elevation") in REGISTRY
|
|
assert ("satpass", "min_elevation_deg") not in REGISTRY
|
|
|
|
|
|
def test_handler_reads_min_elevation():
|
|
"""satpass_handler must read cfg.min_elevation (matching REGISTRY key)."""
|
|
import inspect
|
|
from meshai.central import satpass_handler
|
|
src = inspect.getsource(satpass_handler)
|
|
assert "min_elevation" in src
|
|
assert "min_elevation_deg" not in src
|