correlator: remove is_dispatch and the tactical fit path entirely (#134)
Full removal, not a hardcoded flag: _is_dispatch_channel, _DISPATCH_TG_RE, the is_dispatch parameter, and _call_fits_incident's tactical branch are gone. One evaluation path for every channel. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tbknwttzou4s46PAykmtix
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
0473e6a583
commit
014f5e071f
@@ -31,8 +31,10 @@ from app.internal.incident_correlator import (
|
||||
|
||||
NOW = datetime(2026, 8, 20, 7, 0, 0, tzinfo=timezone.utc)
|
||||
|
||||
# TG 383 from the dump: "Ch 1 (Patched with 155.310)". _DISPATCH_TG_RE matches
|
||||
# "patched", so this is a shared dispatch backbone carrying the whole department.
|
||||
# TG 383 from the dump: "Ch 1 (Patched with 155.310)", a shared dispatch
|
||||
# backbone carrying the whole department. Kept as two distinct fixture names
|
||||
# for readability even though the channel's name no longer affects behavior
|
||||
# (server-26#134).
|
||||
DISPATCH_TG = "Ch 1 (Patched with 155.310)"
|
||||
TACTICAL_TG = "Fireground 2"
|
||||
|
||||
@@ -140,12 +142,9 @@ def test_thin_call_with_no_overlap_does_not_attach_on_a_dispatch_channel():
|
||||
assert _run_decision(_ctx(all_active=[inc], recent=[inc]))["action"] == "orphan"
|
||||
|
||||
|
||||
def test_thin_call_with_no_overlap_does_not_attach_on_a_tactical_channel():
|
||||
"""
|
||||
The widest version of the bug: non-dispatch talkgroups skipped the tiering
|
||||
entirely and used the whole 90-minute fast-path window with no
|
||||
single-candidate requirement, so ANY thin call joined whatever was newest.
|
||||
"""
|
||||
def test_thin_call_with_no_overlap_does_not_attach_on_a_tactical_named_channel():
|
||||
"""A channel's name no longer changes anything (server-26#134) — same
|
||||
assertion as the dispatch-named case above, different fixture name."""
|
||||
inc = _incident(idle_minutes=40)
|
||||
decision = _run_decision(_ctx(
|
||||
all_active=[inc], recent=[inc], talkgroup_name=TACTICAL_TG,
|
||||
@@ -154,10 +153,9 @@ def test_thin_call_with_no_overlap_does_not_attach_on_a_tactical_channel():
|
||||
|
||||
|
||||
def test_tactical_named_channel_uses_the_dispatch_window_now():
|
||||
"""server-26#134: is_dispatch is hardcoded True — a channel's name no
|
||||
longer changes the thin window. 14 min (the old tactical bound minus 1,
|
||||
inside the old 15-min window) is now past the 5-min dispatch window."""
|
||||
inc = _incident(idle_minutes=settings.tg_thin_idle_minutes - 1)
|
||||
"""server-26#134: 14 min was inside the old 15-min tactical window; now
|
||||
every channel uses the 5-min window regardless of name."""
|
||||
inc = _incident(idle_minutes=14)
|
||||
decision = _run_decision(_ctx(
|
||||
all_active=[inc], recent=[inc], talkgroup_name=TACTICAL_TG,
|
||||
))
|
||||
@@ -234,47 +232,27 @@ def test_back_dated_thin_call_does_not_sail_through_the_recency_gate():
|
||||
|
||||
def test_back_dated_call_does_not_bypass_the_content_divergence_veto(monkeypatch):
|
||||
"""
|
||||
Same `9d376ffe` failure mode, but exercised directly against
|
||||
`_call_fits_incident` on a dispatch channel: unit overlap plus a
|
||||
back-dated call (incident updated 45 minutes AFTER the call's own
|
||||
`started_at`, which the sweep passes as `now`) used to make the signed
|
||||
idle -45, so `idle_min >= 15` read False and the content-divergence
|
||||
veto never ran — unit overlap alone forced the merge regardless of
|
||||
what the call was actually about. With the gate fixed to compare
|
||||
distance, idle_min is 45 (>= 15), the veto runs, and a divergent
|
||||
embedding (patched below so the assertion doesn't depend on numpy
|
||||
being installed in this environment) fails it.
|
||||
Same `9d376ffe` failure mode, exercised directly against
|
||||
`_call_fits_incident`: unit overlap plus a back-dated call (incident
|
||||
updated 45 minutes AFTER the call's own `started_at`, which the sweep
|
||||
passes as `now`) used to make the signed idle -45, so `idle_min >= 15`
|
||||
read False and the content-divergence veto never ran — unit overlap
|
||||
alone forced the merge regardless of what the call was actually about.
|
||||
With the gate fixed to compare distance, idle_min is 45 (>= 15), the
|
||||
veto runs, and a divergent embedding (patched below so the assertion
|
||||
doesn't depend on numpy being installed in this environment) fails it.
|
||||
"""
|
||||
monkeypatch.setattr(correlator_mod, "_cosine_similarity", lambda a, b: 0.0)
|
||||
inc = _incident(idle_minutes=-45, units=["6-Adam"])
|
||||
inc["embedding"] = [1.0, 0.0]
|
||||
fits, signal = _call_fits_incident(
|
||||
inc, call_units=["6-Adam"], call_vehicles=[], call_coords=None,
|
||||
proximity_km=settings.location_proximity_km, is_dispatch=True,
|
||||
proximity_km=settings.location_proximity_km,
|
||||
call_embedding=[0.0, 1.0], now=NOW,
|
||||
)
|
||||
assert (fits, signal) == (False, "content_divergence")
|
||||
|
||||
|
||||
def test_back_dated_call_on_tactical_channel_does_not_get_the_default():
|
||||
"""
|
||||
Tactical-channel counterpart: no unit/vehicle/location signal, so the
|
||||
function falls through to step 4's `idle_min < 20.0` default. A
|
||||
back-dated call (incident updated 45 minutes after the call's own
|
||||
started_at) used to read idle_min as -45, which is always < 20.0, so
|
||||
`tactical_default` fired unconditionally no matter how stale the
|
||||
incident actually was relative to this call. Fixed, idle_min is the
|
||||
45-minute distance, which is not < 20.0.
|
||||
"""
|
||||
inc = _incident(idle_minutes=-45)
|
||||
fits, signal = _call_fits_incident(
|
||||
inc, call_units=[], call_vehicles=[], call_coords=None,
|
||||
proximity_km=settings.location_proximity_km, is_dispatch=False,
|
||||
call_embedding=None, now=NOW,
|
||||
)
|
||||
assert (fits, signal) == (False, "tactical_idle")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 4. Hard caps — path-independent, because pairwise fit tests can't see shape
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user