correlator: shrink the same-talkgroup escape hatch from 2h to a few minutes (#115) #126

Merged
logan merged 3 commits from fix/115-escape-hatch-window into main 2026-09-12 04:47:50 -04:00
2 changed files with 15 additions and 5 deletions
Showing only changes of commit 83beb2bf35 - Show all commits
+9
View File
@@ -135,6 +135,12 @@ async def debug_correlation(
"corr_llm_reasoning": call.get("corr_llm_reasoning"),
"corr_llm_action": call.get("corr_llm_action"),
"corr_rules_action": call.get("corr_rules_action"),
# server-26#115 — why an llm=orphan/rules=new disagreement escalated
# to tiebreak instead of being gated (see upload.py's
# _call_is_substanceless). Present only on that disagreement shape;
# written here specifically so a live measurement window can read
# the reason instead of reconstructing it by hand from the dump.
"corr_gate_veto": call.get("corr_gate_veto"),
}
# ── Determine which systems have AI active ────────────────────────────────
@@ -293,6 +299,9 @@ async def debug_correlation(
"corr_fit_signal": _tally(c.get("corr_fit_signal") for c in linked),
"corr_consensus": _tally(c.get("corr_consensus") for c in linked),
"corr_llm_action": _tally(c.get("corr_llm_action") for c in linked),
# server-26#115 — this IS the number the escape-hatch fix exists to
# produce: why each llm=orphan/rules=new call escaped the gate.
"corr_gate_veto": _tally(c.get("corr_gate_veto") for c in linked),
# STT coverage: correlation quality is capped by this, so it belongs in
# the same view rather than a separate investigation.
"linked_calls_with_transcript": with_transcript,
+6 -5
View File
@@ -150,11 +150,12 @@ def _recent_incident_on_same_talkgroup(ctx: dict) -> bool:
fix needs a dedicated Firestore query that is not status/capacity
filtered — a new read, out of scope for this pass.
This does NOT explain the 2/24 unexplained gate misses in the window #3
measurement — re-review found a code-level explanation for both instead
(see `_call_is_substanceless`'s `incident_type`/`reassignment` branch and
the scene-level severity/tags fields the call-doc alone doesn't show), so
this limitation is believed inactive so far, not a live loose end.
Whether this limitation explains the 2/24 unexplained gate misses in the
window #3 measurement is UNANSWERED, not confirmed either way — a prior
pass here claimed a "confirmed explanation" for both that turned out to
be self-contradictory. Read `corr_gate_veto` (written to corr_debug on
every escalation of this exact disagreement shape — see the caller) in
the next measurement window instead of guessing from the raw dump again.
# TODO(server-26#115): add a talkgroup-scoped incident lookup (any
# status, no capacity filter) if a future measurement window pins a real
# gate miss on a resolved/capped same-talkgroup incident.