fix: exempt persist-disabled review forks from the session-scoped tripwire

Background-review forks share the live parent's session_id for prompt-cache
warmth but are _persist_disabled — they can never write to the transcript.
Without this, every review fork on an active session would (a) trip a false
cross-agent overlap warning against the parent's real turn, sending the
#64934 route investigation the wrong way, and (b) pop the parent's in-flight
slot at its own persist, making a real overlap right after a review go
unreported. Both legs now skip persist-disabled agents symmetrically.
+2 tests.
This commit is contained in:
teknium1 2026-07-19 00:51:10 -07:00 committed by Teknium
parent e4ec9e8bc8
commit 14add28785
2 changed files with 50 additions and 7 deletions

View file

@ -410,8 +410,13 @@ def note_turn_start(agent, turn_id: str):
# Cross-agent leg: same session_id in flight under a different agent
# object means two routing keys resolve to one durable session — the
# busy guard (keyed by routing key) cannot see this overlap at all.
# Persist-disabled agents (background-review forks) deliberately share
# the live parent's session_id for prompt-cache warmth but can never
# write to the transcript — they must not register here (would warn a
# false overlap against the parent's real turn) nor pop the parent's
# slot at their persist (note_turn_persisted skips them symmetrically).
session_id = getattr(agent, "session_id", None)
if session_id:
if session_id and not getattr(agent, "_persist_disabled", False):
now = time.time()
with _INFLIGHT_TURNS_LOCK:
entry = _INFLIGHT_TURNS_BY_SESSION.get(session_id)
@ -443,12 +448,17 @@ def note_turn_persisted(agent):
and the tripwire under-reports instead of double-reporting. A diagnostic
must never be noisier than the defect it hunts."""
agent._inflight_turn_id = None
session_id = getattr(agent, "_inflight_turn_session_id", None) or getattr(
agent, "session_id", None
)
if session_id:
with _INFLIGHT_TURNS_LOCK:
_INFLIGHT_TURNS_BY_SESSION.pop(session_id, None)
# Symmetric with note_turn_start's cross-agent leg: persist-disabled
# forks never registered a session slot, and their persist funnel still
# runs — popping here would steal the live parent turn's slot and make
# the tripwire under-report the real overlap it exists to catch.
if not getattr(agent, "_persist_disabled", False):
session_id = getattr(agent, "_inflight_turn_session_id", None) or getattr(
agent, "session_id", None
)
if session_id:
with _INFLIGHT_TURNS_LOCK:
_INFLIGHT_TURNS_BY_SESSION.pop(session_id, None)
agent._inflight_turn_session_id = None

View file

@ -144,3 +144,36 @@ def test_crashed_cross_agent_turn_warns_once_then_recovers(caplog):
note_turn_persisted(agent_b)
note_turn_start(agent_c, "s1:t3:cccc") # clean again
assert len(caplog.records) == 1
def test_persist_disabled_fork_neither_registers_nor_warns(caplog):
"""Background-review forks share the live parent's session_id for
prompt-cache warmth but are _persist_disabled they can never write
to the transcript, so they must not trip the cross-agent warning
against the parent's real in-flight turn (in either direction)."""
parent, fork = _FakeAgent(), _FakeAgent()
fork._persist_disabled = True
with caplog.at_level(logging.WARNING, logger="agent.agent_runtime_helpers"):
note_turn_start(parent, "s1:t1:aaaa") # real turn in flight
assert note_turn_start(fork, "s1:tr:ffff") is None # fork: silent
note_turn_persisted(fork) # fork's funnel still runs
# Reverse order on the next cycle: fork in flight, then real turn.
note_turn_persisted(parent)
note_turn_start(fork, "s1:tr:gggg")
assert note_turn_start(parent, "s1:t2:bbbb") is None
assert not caplog.records
def test_persist_disabled_fork_persist_does_not_steal_parent_slot(caplog):
"""The fork's persist funnel still runs; it must not pop the parent's
session slot, or a real cross-agent overlap right after a review fork
would go unreported."""
parent, fork, intruder = _FakeAgent(), _FakeAgent(), _FakeAgent()
fork._persist_disabled = True
with caplog.at_level(logging.WARNING, logger="agent.agent_runtime_helpers"):
note_turn_start(parent, "s1:t1:aaaa") # real turn holds the slot
note_turn_start(fork, "s1:tr:ffff")
note_turn_persisted(fork) # must NOT release s1
prev = note_turn_start(intruder, "s1:t2:bbbb")
assert prev == "s1:t1:aaaa"
assert len(caplog.records) == 1