2026-06-16 03:40:31 +00:00
|
|
|
"""v0.7-fire-tracker-4 tests."""
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import asyncio
|
|
|
|
|
import time
|
|
|
|
|
import uuid
|
|
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
|
|
|
def _isolate_db(tmp_path, monkeypatch):
|
|
|
|
|
db_path = str(tmp_path / f"meshai-{uuid.uuid4().hex}.sqlite")
|
|
|
|
|
monkeypatch.setenv("MESHAI_DB_PATH", db_path)
|
|
|
|
|
from meshai.persistence import db as pdb
|
|
|
|
|
pdb.close_thread_connection()
|
|
|
|
|
pdb._initialised.discard(db_path)
|
|
|
|
|
from meshai.persistence import init_db
|
|
|
|
|
init_db(db_path)
|
|
|
|
|
yield db_path
|
|
|
|
|
pdb.close_thread_connection()
|
|
|
|
|
pdb._initialised.discard(db_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _seed_fire(*, irwin_id, name, lat, lon, acres=None,
|
|
|
|
|
contained=None, county="Test", state="ID"):
|
|
|
|
|
from meshai.persistence import get_db
|
|
|
|
|
get_db().execute(
|
|
|
|
|
"INSERT INTO fires(irwin_id, incident_name, current_acres, "
|
|
|
|
|
"current_contained_pct, lat, lon, county, state, last_event_at) "
|
|
|
|
|
"VALUES (?,?,?,?,?,?,?,?,?)",
|
|
|
|
|
(irwin_id, name, acres, contained, lat, lon, county, state,
|
|
|
|
|
int(time.time())),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===========================================================================
|
|
|
|
|
# Bug A regression: scope_type defined before use
|
|
|
|
|
# ===========================================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_router_scope_type_defined_before_env_check():
|
|
|
|
|
"""The env_reporter check at the top of generate_llm_response reads
|
|
|
|
|
scope_type. Pre-fix it was UnboundLocalError on every env query."""
|
|
|
|
|
import re
|
test: fix 13 stale tests in the red suite, leave 6 real-bug failures (#124) (#129)
Triaged all 20 known-red tests. 13 were stale tests asserting rotted
expectations against deliberate, documented behavior changes; fixed by
deriving expected values instead of hard-coding, or updating the
expectation to match a documented policy change:
- test_adapter_config_foundation.py / test_adapter_config_api.py:
REGISTRY/API key-count and key-set guards hard-coded magic numbers
(59/94/17) that rotted repeatedly. Now derive expectations from
REGISTRY itself and, for the schema version, from the migrations
directory, so they can't rot the same way again.
- test_fire_tracker_phase4.py: two tests hardcoded a nonexistent
deployment path (/opt/meshai/meshai/router.py) that matches no
Dockerfile WORKDIR in this repo; resolve the module path via
importlib.util.find_spec instead.
- test_tombstone_broadcast.py: asserted fire severity == "immediate",
which commit 2f677e85 deliberately downgraded to "priority" (to stop
fire broadcasts bypassing the Grouper/cooldown during NATS backlog
replay) without updating this test.
- test_pipeline_grouper.py: test_immediate_severity_bypasses_grouper
asserted an immediate-severity bypass that commit 85d48ce3
("fix(fire): remove immediate-severity exemption from grouper +
cooldown") DELETED on purpose -- fire events carry
_severity_override="immediate", and the exemption left fire with no
rate control at all in normal live operation. Re-adding the bypass
would re-open that fire-spam hole on a public-safety mesh, so the test
moves, not the source. Renamed + inverted to assert the real contract
(all severities coalesce; only a missing group_key passes through).
- test_tail_followups.py: dispatcher mock was missing
dispatch_scheduled_fire_broadcast (a method added alongside the
generic dispatch_scheduled_broadcast; test_reminders.py already
mocks both).
- test_tracking_v057.py: guard required an empty tracking-family
adapter list in Environment.tsx, but the frontend has long grouped
the pre-existing native satpass adapter under the "Tracking" display
section (its own "satpass" backend toggle, unrelated to the Phase-7
tracking family every other guard in this file confirms is still
unimplemented). Narrowed the guard to allow only that known entry.
- test_v052_dispatcher.py: two tests used category="wildfire_incident",
which the phase3b fire migration (#33) forced onto a dedicated
formatter via NATIVE_ALWAYS_DECIDE; swapped to wildfire_hotspot
(same emoji/label, not in NATIVE_ALWAYS_DECIDE) to keep exercising
the generic composer logic under test.
Also fixes one stale COMMENT (comment-only, no logic change) in
meshai/notifications/pipeline/__init__.py's start_pipeline(): it still
claimed "Immediate events bypass the grouper and don't need this
[periodic flush]", which has been false since 85d48ce3 and is precisely
what makes the deleted bypass look like a missing feature. The comment
now records that the removal was deliberate and must not be reverted.
The remaining 6 failures are left untouched -- 2 confirmed real bugs, to
be fixed deliberately in their own changes:
- meshcore_transport.py defines `_resolve_contact` TWICE on
MeshCoreTransport (line 171 from PR #56, line 1227 from PR #92). The
second silently shadows the first, so the DM contact-resolution
refetch-on-miss that #56 added is dead code in production. (3 tests)
- SCHEMA_VERSION (persistence/db.py:33) is stale at 26 vs. the actual
highest migration v28; v27 and v28 shipped without bumping it.
(3 tests)
Plus 1 environment gap, not a code defect:
test_natural_language_fire_question_routes_to_llm needs the `openai`
package, which is declared in requirements.txt but not installed here.
Suite: 20 failed, 2240 passed, 72 skipped -> 7 failed, 2254 passed, 72
skipped. All 7 remaining failures are ones classified above; no new
failures introduced elsewhere in the suite.
Co-authored-by: Matt Johnson <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 10:36:19 -06:00
|
|
|
import importlib.util
|
2026-06-16 03:40:31 +00:00
|
|
|
from pathlib import Path
|
test: fix 13 stale tests in the red suite, leave 6 real-bug failures (#124) (#129)
Triaged all 20 known-red tests. 13 were stale tests asserting rotted
expectations against deliberate, documented behavior changes; fixed by
deriving expected values instead of hard-coding, or updating the
expectation to match a documented policy change:
- test_adapter_config_foundation.py / test_adapter_config_api.py:
REGISTRY/API key-count and key-set guards hard-coded magic numbers
(59/94/17) that rotted repeatedly. Now derive expectations from
REGISTRY itself and, for the schema version, from the migrations
directory, so they can't rot the same way again.
- test_fire_tracker_phase4.py: two tests hardcoded a nonexistent
deployment path (/opt/meshai/meshai/router.py) that matches no
Dockerfile WORKDIR in this repo; resolve the module path via
importlib.util.find_spec instead.
- test_tombstone_broadcast.py: asserted fire severity == "immediate",
which commit 2f677e85 deliberately downgraded to "priority" (to stop
fire broadcasts bypassing the Grouper/cooldown during NATS backlog
replay) without updating this test.
- test_pipeline_grouper.py: test_immediate_severity_bypasses_grouper
asserted an immediate-severity bypass that commit 85d48ce3
("fix(fire): remove immediate-severity exemption from grouper +
cooldown") DELETED on purpose -- fire events carry
_severity_override="immediate", and the exemption left fire with no
rate control at all in normal live operation. Re-adding the bypass
would re-open that fire-spam hole on a public-safety mesh, so the test
moves, not the source. Renamed + inverted to assert the real contract
(all severities coalesce; only a missing group_key passes through).
- test_tail_followups.py: dispatcher mock was missing
dispatch_scheduled_fire_broadcast (a method added alongside the
generic dispatch_scheduled_broadcast; test_reminders.py already
mocks both).
- test_tracking_v057.py: guard required an empty tracking-family
adapter list in Environment.tsx, but the frontend has long grouped
the pre-existing native satpass adapter under the "Tracking" display
section (its own "satpass" backend toggle, unrelated to the Phase-7
tracking family every other guard in this file confirms is still
unimplemented). Narrowed the guard to allow only that known entry.
- test_v052_dispatcher.py: two tests used category="wildfire_incident",
which the phase3b fire migration (#33) forced onto a dedicated
formatter via NATIVE_ALWAYS_DECIDE; swapped to wildfire_hotspot
(same emoji/label, not in NATIVE_ALWAYS_DECIDE) to keep exercising
the generic composer logic under test.
Also fixes one stale COMMENT (comment-only, no logic change) in
meshai/notifications/pipeline/__init__.py's start_pipeline(): it still
claimed "Immediate events bypass the grouper and don't need this
[periodic flush]", which has been false since 85d48ce3 and is precisely
what makes the deleted bypass look like a missing feature. The comment
now records that the removal was deliberate and must not be reverted.
The remaining 6 failures are left untouched -- 2 confirmed real bugs, to
be fixed deliberately in their own changes:
- meshcore_transport.py defines `_resolve_contact` TWICE on
MeshCoreTransport (line 171 from PR #56, line 1227 from PR #92). The
second silently shadows the first, so the DM contact-resolution
refetch-on-miss that #56 added is dead code in production. (3 tests)
- SCHEMA_VERSION (persistence/db.py:33) is stale at 26 vs. the actual
highest migration v28; v27 and v28 shipped without bumping it.
(3 tests)
Plus 1 environment gap, not a code defect:
test_natural_language_fire_question_routes_to_llm needs the `openai`
package, which is declared in requirements.txt but not installed here.
Suite: 20 failed, 2240 passed, 72 skipped -> 7 failed, 2254 passed, 72
skipped. All 7 remaining failures are ones classified above; no new
failures introduced elsewhere in the suite.
Co-authored-by: Matt Johnson <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 10:36:19 -06:00
|
|
|
# Resolve the module's file path without importing it -- router.py
|
|
|
|
|
# transitively imports optional LLM backend deps (openai/anthropic)
|
|
|
|
|
# that may not be installed in every test environment, and this test
|
|
|
|
|
# only needs the source text, not a working import.
|
|
|
|
|
spec = importlib.util.find_spec("meshai.router")
|
|
|
|
|
src = Path(spec.origin).read_text()
|
2026-06-16 03:40:31 +00:00
|
|
|
# Find the "if should_inject_mesh and scope_type" line + the
|
|
|
|
|
# nearest preceding `scope_type, scope_value = ` assignment.
|
|
|
|
|
env_use_line = None
|
|
|
|
|
for i, line in enumerate(src.splitlines(), start=1):
|
|
|
|
|
if "should_inject_mesh and scope_type" in line:
|
|
|
|
|
env_use_line = i
|
|
|
|
|
break
|
|
|
|
|
assert env_use_line is not None
|
|
|
|
|
# There must be an assignment on or before this line.
|
|
|
|
|
preceding = "\n".join(src.splitlines()[: env_use_line - 1])
|
|
|
|
|
assert re.search(r"scope_type[, ]+scope_value\s*=", preceding) \
|
|
|
|
|
or "scope_type:" in preceding
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===========================================================================
|
|
|
|
|
# Natural-language fire DMs route to the LLM (no ?status fallback)
|
|
|
|
|
# ===========================================================================
|
|
|
|
|
|
|
|
|
|
|
fix(persistence): derive SCHEMA_VERSION from migrations; unbreak the red suite (#140)
* fix(persistence): derive SCHEMA_VERSION from the migrations directory
db.py hardcoded SCHEMA_VERSION = 26 while migrations/ had already reached
v29 (v27 dispatcher floor-drop counter, v28 mesh_observations, v29 IPAWS).
The migration runner globs the directory and applies every vN.sql it finds
regardless of the constant, so a fresh DB actually landed at 29 while the
constant claimed 26 -- a three-version drift that three tests were
correctly catching.
Derive it from the highest vN.sql present instead of bumping the literal,
so it cannot drift again the next time someone adds a migration. Falls back
to 0 if the directory is missing so import never fails; the migrations dir
sits alongside db.py and ships with the package (Dockerfile COPYs meshai/).
Adds a regression guard asserting the constant matches the highest
migration file, and updates three tests that hardcoded 26 as a literal.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(tle): make TLE fixtures time-relative so they cannot expire
The ISS fixtures hardcoded epochs of 2026-06-30/07-01/07-02. tle_handler
sets STALE_DAYS = 14 and get_tle_by_norad() filters on epoch >= now - 14d,
so the fixtures silently aged out on 2026-07-02 and the tests began
failing -- a time bomb, not a regression.
Compute epochs relative to wall-clock now (base = now - 2d, +/-1d for
newer/older) with correct TLE epoch-field encoding and mod-10 checksum.
STALE_DAYS is untouched -- widening it in product code would have changed
production behavior to paper over a test bug.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(fire-tracker): pin config + history db to tmp_path
load_config() defaults HistoryConfig.database to the relative path
"conversations.db", resolved against the process CWD, so every test calling
load_config() with no override shares one file for the whole session. The
conftest DB-isolation fixture only covers MESHAI_DB_PATH, not this.
Point both the config dir and the history database at the test's tmp_path.
NOTE: this does NOT resolve the order-dependent failure -- the test still
passes standalone and fails in a full run, so the polluting state lives
somewhere other than config/history. Left failing rather than weakened;
root cause still unidentified.
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>
2026-07-17 13:03:40 -06:00
|
|
|
def test_natural_language_fire_question_routes_to_llm(tmp_path):
|
2026-06-16 03:40:31 +00:00
|
|
|
"""The LLM DM path is the sole interface for natural-language fire
|
|
|
|
|
questions. Pre-revised commit there was a `?status` intent that
|
|
|
|
|
rewrote the query in-router; this test confirms the rewrite is gone
|
|
|
|
|
and that a plain English question is forwarded verbatim."""
|
|
|
|
|
import asyncio
|
|
|
|
|
from meshai.router import MessageRouter, RouteType
|
|
|
|
|
from meshai.config_loader import load_config
|
|
|
|
|
from meshai.history import ConversationHistory
|
|
|
|
|
from meshai.commands.dispatcher import create_dispatcher
|
|
|
|
|
|
fix(persistence): derive SCHEMA_VERSION from migrations; unbreak the red suite (#140)
* fix(persistence): derive SCHEMA_VERSION from the migrations directory
db.py hardcoded SCHEMA_VERSION = 26 while migrations/ had already reached
v29 (v27 dispatcher floor-drop counter, v28 mesh_observations, v29 IPAWS).
The migration runner globs the directory and applies every vN.sql it finds
regardless of the constant, so a fresh DB actually landed at 29 while the
constant claimed 26 -- a three-version drift that three tests were
correctly catching.
Derive it from the highest vN.sql present instead of bumping the literal,
so it cannot drift again the next time someone adds a migration. Falls back
to 0 if the directory is missing so import never fails; the migrations dir
sits alongside db.py and ships with the package (Dockerfile COPYs meshai/).
Adds a regression guard asserting the constant matches the highest
migration file, and updates three tests that hardcoded 26 as a literal.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(tle): make TLE fixtures time-relative so they cannot expire
The ISS fixtures hardcoded epochs of 2026-06-30/07-01/07-02. tle_handler
sets STALE_DAYS = 14 and get_tle_by_norad() filters on epoch >= now - 14d,
so the fixtures silently aged out on 2026-07-02 and the tests began
failing -- a time bomb, not a regression.
Compute epochs relative to wall-clock now (base = now - 2d, +/-1d for
newer/older) with correct TLE epoch-field encoding and mod-10 checksum.
STALE_DAYS is untouched -- widening it in product code would have changed
production behavior to paper over a test bug.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(fire-tracker): pin config + history db to tmp_path
load_config() defaults HistoryConfig.database to the relative path
"conversations.db", resolved against the process CWD, so every test calling
load_config() with no override shares one file for the whole session. The
conftest DB-isolation fixture only covers MESHAI_DB_PATH, not this.
Point both the config dir and the history database at the test's tmp_path.
NOTE: this does NOT resolve the order-dependent failure -- the test still
passes standalone and fails in a full run, so the polluting state lives
somewhere other than config/history. Left failing rather than weakened;
root cause still unidentified.
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>
2026-07-17 13:03:40 -06:00
|
|
|
# load_config() defaults HistoryConfig.database to the relative path
|
|
|
|
|
# "conversations.db", resolved against the process CWD. Left alone,
|
|
|
|
|
# every test in the suite that calls load_config() with no override
|
|
|
|
|
# shares that one file for the whole pytest session, so conversation
|
|
|
|
|
# rows written by an unrelated, earlier-running test file can leak
|
|
|
|
|
# into this test's routing decision. Point both the config dir and
|
|
|
|
|
# the history database at this test's own tmp_path to make it
|
|
|
|
|
# hermetic regardless of run order.
|
|
|
|
|
cfg = load_config(tmp_path / "config")
|
|
|
|
|
cfg.history.database = str(tmp_path / "conversations.db")
|
2026-06-16 03:40:31 +00:00
|
|
|
history = ConversationHistory(cfg.history)
|
|
|
|
|
|
|
|
|
|
async def _run():
|
|
|
|
|
await history.initialize()
|
|
|
|
|
dispatcher = create_dispatcher(
|
|
|
|
|
prefix=cfg.commands.prefix,
|
|
|
|
|
disabled_commands=cfg.commands.disabled_commands,
|
|
|
|
|
custom_commands=cfg.commands.custom_commands,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
class FakeConnector:
|
|
|
|
|
my_node_id = "!THIS_BOT"
|
|
|
|
|
|
|
|
|
|
class FakeMessage:
|
|
|
|
|
text = "how's the cache peak fire?"
|
|
|
|
|
sender_id = "!T"
|
|
|
|
|
sender_name = "t"
|
|
|
|
|
is_dm = True
|
|
|
|
|
channel = 0
|
|
|
|
|
|
|
|
|
|
router = MessageRouter(
|
|
|
|
|
config=cfg, connector=FakeConnector(),
|
|
|
|
|
history=history, dispatcher=dispatcher,
|
|
|
|
|
llm_backend=None, # we only inspect the route() decision
|
|
|
|
|
)
|
|
|
|
|
result = await router.route(FakeMessage())
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
result = asyncio.run(_run())
|
|
|
|
|
assert result.route_type == RouteType.LLM
|
|
|
|
|
# Critical: the query must be the verbatim user text, not a rewrite
|
|
|
|
|
# synthesized by an in-router intent helper.
|
|
|
|
|
assert result.query == "how's the cache peak fire?"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_status_helpers_removed_from_router():
|
|
|
|
|
"""Hard guard against ?status helpers sneaking back in. If anyone
|
|
|
|
|
adds a structured-command path to router.py for fires, this test
|
|
|
|
|
fails and the author has to talk to Matt first."""
|
test: fix 13 stale tests in the red suite, leave 6 real-bug failures (#124) (#129)
Triaged all 20 known-red tests. 13 were stale tests asserting rotted
expectations against deliberate, documented behavior changes; fixed by
deriving expected values instead of hard-coding, or updating the
expectation to match a documented policy change:
- test_adapter_config_foundation.py / test_adapter_config_api.py:
REGISTRY/API key-count and key-set guards hard-coded magic numbers
(59/94/17) that rotted repeatedly. Now derive expectations from
REGISTRY itself and, for the schema version, from the migrations
directory, so they can't rot the same way again.
- test_fire_tracker_phase4.py: two tests hardcoded a nonexistent
deployment path (/opt/meshai/meshai/router.py) that matches no
Dockerfile WORKDIR in this repo; resolve the module path via
importlib.util.find_spec instead.
- test_tombstone_broadcast.py: asserted fire severity == "immediate",
which commit 2f677e85 deliberately downgraded to "priority" (to stop
fire broadcasts bypassing the Grouper/cooldown during NATS backlog
replay) without updating this test.
- test_pipeline_grouper.py: test_immediate_severity_bypasses_grouper
asserted an immediate-severity bypass that commit 85d48ce3
("fix(fire): remove immediate-severity exemption from grouper +
cooldown") DELETED on purpose -- fire events carry
_severity_override="immediate", and the exemption left fire with no
rate control at all in normal live operation. Re-adding the bypass
would re-open that fire-spam hole on a public-safety mesh, so the test
moves, not the source. Renamed + inverted to assert the real contract
(all severities coalesce; only a missing group_key passes through).
- test_tail_followups.py: dispatcher mock was missing
dispatch_scheduled_fire_broadcast (a method added alongside the
generic dispatch_scheduled_broadcast; test_reminders.py already
mocks both).
- test_tracking_v057.py: guard required an empty tracking-family
adapter list in Environment.tsx, but the frontend has long grouped
the pre-existing native satpass adapter under the "Tracking" display
section (its own "satpass" backend toggle, unrelated to the Phase-7
tracking family every other guard in this file confirms is still
unimplemented). Narrowed the guard to allow only that known entry.
- test_v052_dispatcher.py: two tests used category="wildfire_incident",
which the phase3b fire migration (#33) forced onto a dedicated
formatter via NATIVE_ALWAYS_DECIDE; swapped to wildfire_hotspot
(same emoji/label, not in NATIVE_ALWAYS_DECIDE) to keep exercising
the generic composer logic under test.
Also fixes one stale COMMENT (comment-only, no logic change) in
meshai/notifications/pipeline/__init__.py's start_pipeline(): it still
claimed "Immediate events bypass the grouper and don't need this
[periodic flush]", which has been false since 85d48ce3 and is precisely
what makes the deleted bypass look like a missing feature. The comment
now records that the removal was deliberate and must not be reverted.
The remaining 6 failures are left untouched -- 2 confirmed real bugs, to
be fixed deliberately in their own changes:
- meshcore_transport.py defines `_resolve_contact` TWICE on
MeshCoreTransport (line 171 from PR #56, line 1227 from PR #92). The
second silently shadows the first, so the DM contact-resolution
refetch-on-miss that #56 added is dead code in production. (3 tests)
- SCHEMA_VERSION (persistence/db.py:33) is stale at 26 vs. the actual
highest migration v28; v27 and v28 shipped without bumping it.
(3 tests)
Plus 1 environment gap, not a code defect:
test_natural_language_fire_question_routes_to_llm needs the `openai`
package, which is declared in requirements.txt but not installed here.
Suite: 20 failed, 2240 passed, 72 skipped -> 7 failed, 2254 passed, 72
skipped. All 7 remaining failures are ones classified above; no new
failures introduced elsewhere in the suite.
Co-authored-by: Matt Johnson <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 10:36:19 -06:00
|
|
|
import importlib.util
|
2026-06-16 03:40:31 +00:00
|
|
|
from pathlib import Path
|
test: fix 13 stale tests in the red suite, leave 6 real-bug failures (#124) (#129)
Triaged all 20 known-red tests. 13 were stale tests asserting rotted
expectations against deliberate, documented behavior changes; fixed by
deriving expected values instead of hard-coding, or updating the
expectation to match a documented policy change:
- test_adapter_config_foundation.py / test_adapter_config_api.py:
REGISTRY/API key-count and key-set guards hard-coded magic numbers
(59/94/17) that rotted repeatedly. Now derive expectations from
REGISTRY itself and, for the schema version, from the migrations
directory, so they can't rot the same way again.
- test_fire_tracker_phase4.py: two tests hardcoded a nonexistent
deployment path (/opt/meshai/meshai/router.py) that matches no
Dockerfile WORKDIR in this repo; resolve the module path via
importlib.util.find_spec instead.
- test_tombstone_broadcast.py: asserted fire severity == "immediate",
which commit 2f677e85 deliberately downgraded to "priority" (to stop
fire broadcasts bypassing the Grouper/cooldown during NATS backlog
replay) without updating this test.
- test_pipeline_grouper.py: test_immediate_severity_bypasses_grouper
asserted an immediate-severity bypass that commit 85d48ce3
("fix(fire): remove immediate-severity exemption from grouper +
cooldown") DELETED on purpose -- fire events carry
_severity_override="immediate", and the exemption left fire with no
rate control at all in normal live operation. Re-adding the bypass
would re-open that fire-spam hole on a public-safety mesh, so the test
moves, not the source. Renamed + inverted to assert the real contract
(all severities coalesce; only a missing group_key passes through).
- test_tail_followups.py: dispatcher mock was missing
dispatch_scheduled_fire_broadcast (a method added alongside the
generic dispatch_scheduled_broadcast; test_reminders.py already
mocks both).
- test_tracking_v057.py: guard required an empty tracking-family
adapter list in Environment.tsx, but the frontend has long grouped
the pre-existing native satpass adapter under the "Tracking" display
section (its own "satpass" backend toggle, unrelated to the Phase-7
tracking family every other guard in this file confirms is still
unimplemented). Narrowed the guard to allow only that known entry.
- test_v052_dispatcher.py: two tests used category="wildfire_incident",
which the phase3b fire migration (#33) forced onto a dedicated
formatter via NATIVE_ALWAYS_DECIDE; swapped to wildfire_hotspot
(same emoji/label, not in NATIVE_ALWAYS_DECIDE) to keep exercising
the generic composer logic under test.
Also fixes one stale COMMENT (comment-only, no logic change) in
meshai/notifications/pipeline/__init__.py's start_pipeline(): it still
claimed "Immediate events bypass the grouper and don't need this
[periodic flush]", which has been false since 85d48ce3 and is precisely
what makes the deleted bypass look like a missing feature. The comment
now records that the removal was deliberate and must not be reverted.
The remaining 6 failures are left untouched -- 2 confirmed real bugs, to
be fixed deliberately in their own changes:
- meshcore_transport.py defines `_resolve_contact` TWICE on
MeshCoreTransport (line 171 from PR #56, line 1227 from PR #92). The
second silently shadows the first, so the DM contact-resolution
refetch-on-miss that #56 added is dead code in production. (3 tests)
- SCHEMA_VERSION (persistence/db.py:33) is stale at 26 vs. the actual
highest migration v28; v27 and v28 shipped without bumping it.
(3 tests)
Plus 1 environment gap, not a code defect:
test_natural_language_fire_question_routes_to_llm needs the `openai`
package, which is declared in requirements.txt but not installed here.
Suite: 20 failed, 2240 passed, 72 skipped -> 7 failed, 2254 passed, 72
skipped. All 7 remaining failures are ones classified above; no new
failures introduced elsewhere in the suite.
Co-authored-by: Matt Johnson <mj@k7zvx.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 10:36:19 -06:00
|
|
|
# See test_router_scope_type_defined_before_env_check above for why
|
|
|
|
|
# this resolves the path via find_spec rather than importing router.py
|
|
|
|
|
# or hardcoding a deployment-container path.
|
|
|
|
|
spec = importlib.util.find_spec("meshai.router")
|
|
|
|
|
src = Path(spec.origin).read_text()
|
2026-06-16 03:40:31 +00:00
|
|
|
assert "_maybe_rewrite_status_query" not in src
|
|
|
|
|
assert "_lookup_fire_fuzzy" not in src
|
|
|
|
|
assert "?status" not in src
|