fix(claude): Settle positive task-notification results

A Claude V2 turn whose terminal SDK result carried origin.kind
"task-notification" had that result discarded, so the run stayed running
forever and every run queued behind it stalled. The drop is now limited to
results reporting zero model turns, which is what the stale debris the guard
was written for actually looks like.

ClaudeAdapterV2 dropped any task-notification-origin result unless the turn was
an agent/provider continuation. An app-owned delegated-task wake run is
agent/server, so its terminal results were discarded and finalizeActiveTurn
never ran. Any turn whose final result carries that origin hangs, not just
wakes. Observed in production against a real session: three terminal success
results with num_turns 154, 60 and 7 were all dropped, the session went silent
for 8h27m, and five queued runs behind it never dispatched.

The guard could not simply be deleted. After interrupt recovery a stale stopped
task_notification and its origin result interleave ahead of the real root
assistant stream and must not terminalize the turn or leak their text.
Zero-turn results are still dropped, so that path is unchanged: this drops
strictly fewer results than before, so no previously working path can regress.

num_turns separates the two cases cleanly. The existing stale fixture sets
numTurns 0 explicitly, makeResultFrame defaults to 1, and the production
results all carried positive turns. The predicate is num_turns === 0 rather
than < 1 or a truthiness check on purpose: num_turns is required on both result
variants in 0.3.205, but if an older emitter ever omitted it, undefined === 0
is false, so the result is accepted rather than dropped. That fails toward
terminalizing rather than toward the hang class this fixes.

Both drops and accepts are logged with num_turns, stop_reason, terminal_reason,
result uuid, session id and message provenance. The drop is debug level because
interrupt recovery produces it routinely; the accept is info, because a
positive-turn task-notification result settling a non-continuation turn is both
the hang fix working and the exact shape a stale positive-turn result would
take.

Co-authored-by: codex <codex@users.noreply.github.com>
6ffc9cedfeMike Olson committed on 8/29/2026, 6:01:50 AM· committed by Julius Marmingeparentb31bfab
2 files changedLine totals unavailable