drb-correlation-review: ship, with two bounds the low-bar link rule needs.
1. _call_block emitted only the talkgroup NAME while _inc_summary emits
numeric tg ids, so the "same talkgroup" precondition in _RULES was
unevaluable and the low link bar applied unconditionally. _call_block now
prints "Talkgroup: <name> (id <n>)".
2. ctx["recent"] is an unordered Firestore slice with no order_by; a busy 2h
window (~40 active incidents) showed the model an arbitrary half of the
candidates. _prompt_incidents() sorts by updated_at desc before the [:20]
cap — also makes each row's idle: field monotonic.
+2 tests. Full c2-core suite green (sandboxed venv).
Review follow-ups (not blockers): _parse_response demotes an unresolvable
link to orphan (drops the call) rather than falling back to rules — now on
rising link volume; the 45% tiebreak escalation rate / smart-model cost is
untouched; _ROAD_RE swallows leading tokens so "10 Parker Street" still
won't road-overlap "Parker St".
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The 2026-09-07 measurement window (CORRELATION_REVIEW_0907.md) showed the
consensus tiebreaker was the dominant over-split driver: it ran on 45% of
calls and resolved link/orphan disagreements as "new" ~24/25 of the time,
shattering one Mohegan Park car-alarm job into 9 incidents and opening ~7
incidents from radio checks / roll calls.
Two causes, two fixes:
1. `_inc_summary` gave the model `id|type|loc|units|tags|idle` — no title,
no talkgroup. It literally could not see that two "car alarms, Mohegan
Park Ave/Avenue" incidents on TG 9560 were the same. Now includes the
incident title (the strongest same-event signal) and talkgroup.
2. `_RULES` told the model "orphan when in doubt — conservative is always
correct". For a system that over-splits, that is backwards: a wrong link
is cheap, a duplicate incident is the failure. Rewritten to: prefer link
for a plausible same-talkgroup continuation (low bar), reserve "new" for a
genuinely different event, and explicitly "orphan" non-incidents (radio
checks, roll call, 10-8/10-98, mileage logs).
Plus `_extract_road_ids` now canonicalises street-type synonyms
(Avenue→ave, Street→st, Road→rd, ...), so "Mohegan Park Avenue" and
"Mohegan Park Ave" share a road id — that one difference was splitting the
car-alarm incident.
+tests/test_correlator_115.py. Full c2-core suite green (sandboxed venv).
Bigger levers deferred to follow-ups: the consensus escalation itself (should
a cheap-LLM "orphan" ever reach a tiebreak?), a first-class road-overlap fit
signal in _call_fits_incident, geocode coverage.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>