correlator: address drb-correlation-review notes on #139

- Document call_severity's routine-coercion asymmetry with incident_type
  (extraction-said-routine vs extraction-said-nothing look identical).
- Test docstring no longer overclaims the ctx-linkage it doesn't cover;
  points to the tests that do (test_consensus_gate.py, test_incident_identity.py).
- scene1 now uses a distinct severity so the test actually exercises both
  fields symmetrically; the 'no flat top-level clobber' claim is now
  asserted, not just commented.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tbknwttzou4s46PAykmtix
This commit is contained in:
Logan Cusano
2026-09-14 00:14:32 -04:00
co-authored by Claude Sonnet 5
parent 7717fcccdd
commit f23026b9ab
2 changed files with 21 additions and 8 deletions
@@ -1467,6 +1467,13 @@ async def _apply_and_log(decision: dict, ctx: dict) -> Optional[str]:
# which is last-scene-wins (server-26#96) and was the reason # which is last-scene-wins (server-26#96) and was the reason
# #138's "type" veto couldn't be told apart from cross-scene # #138's "type" veto couldn't be told apart from cross-scene
# contamination without re-guessing from a live dump. # contamination without re-guessing from a live dump.
# NOTE: unlike incident_type, call_severity is already
# coerced to "routine" when extraction emitted nothing
# (ctx build: `severity or "routine"`) — a scene reading
# "routine" here doesn't distinguish "extraction said
# routine" from "extraction said nothing". Don't split a
# severity veto the way #138 splits the type veto without
# accounting for that.
"incident_type": ctx.get("incident_type"), "incident_type": ctx.get("incident_type"),
"severity": ctx.get("call_severity"), "severity": ctx.get("call_severity"),
} }
+14 -8
View File
@@ -135,9 +135,12 @@ async def test_scene_entry_captures_its_own_incident_type_not_a_sibling_scenes()
server-26#139: _call_is_substanceless's "type" veto reads ctx["incident_type"] server-26#139: _call_is_substanceless's "type" veto reads ctx["incident_type"]
at decision time, but that value was never persisted per-scene — only the at decision time, but that value was never persisted per-scene — only the
last-scene-wins flat field, which #138's dump analysis couldn't last-scene-wins flat field, which #138's dump analysis couldn't
distinguish from cross-scene contamination. Each scene's own scenes.<n> distinguish from cross-scene contamination. Pins _apply_and_log's write
entry must carry its own incident_type/severity, distinct from any other side: each scene's own scenes.<n> entry carries its own incident_type/
scene on the same call. severity, distinct from any other scene on the same call. Does NOT cover
whether the ctx handed to _call_is_substanceless is the same object that
reaches here — that linkage is pinned by test_consensus_gate.py and
test_incident_identity.py, not this file.
""" """
docs: dict[tuple, dict] = {} docs: dict[tuple, dict] = {}
@@ -160,7 +163,7 @@ async def test_scene_entry_captures_its_own_incident_type_not_a_sibling_scenes()
} }
ctx1 = { ctx1 = {
"call_id": "call-5", "scene_index": 1, "scene_transcript": "roll call", "call_id": "call-5", "scene_index": 1, "scene_transcript": "roll call",
"incident_type": None, "call_severity": "routine", "incident_type": None, "call_severity": "moderate",
} }
with patch.object(incident_correlator, "fstore") as mock_fstore: with patch.object(incident_correlator, "fstore") as mock_fstore:
@@ -168,13 +171,16 @@ async def test_scene_entry_captures_its_own_incident_type_not_a_sibling_scenes()
await incident_correlator._apply_and_log(decision0, ctx0) await incident_correlator._apply_and_log(decision0, ctx0)
await incident_correlator._apply_and_log(decision1, ctx1) await incident_correlator._apply_and_log(decision1, ctx1)
scenes = docs[("calls", "call-5")]["scenes"] doc = docs[("calls", "call-5")]
scenes = doc["scenes"]
assert scenes["0"]["incident_type"] == "traffic-stop" assert scenes["0"]["incident_type"] == "traffic-stop"
assert scenes["0"]["severity"] == "routine" assert scenes["0"]["severity"] == "routine"
assert scenes["1"]["incident_type"] is None assert scenes["1"]["incident_type"] is None
# _apply_and_log never writes incident_type/severity to the flat assert scenes["1"]["severity"] == "moderate"
# top-level fields at all (only corr_debug's own keys go flat) — the # _apply_and_log only ever flat-merges corr_debug's own keys (:1460) — a
# per-scene entry is the only place either value is ever persisted. # future corr_debug["incident_type"] would silently clobber
# intelligence.py's flat field, so this is asserted, not just commented.
assert "incident_type" not in doc
@pytest.mark.asyncio @pytest.mark.asyncio