* fix(subagents): harden background-task registry and capacity snapshot edge cases
- execute_async drops the just-registered background entry when submitting
to the isolated loop fails. The caller sees the exception and never
polls, and cleanup_background_task refuses non-terminal entries, so the
entry would otherwise stay as a PENDING zombie forever.
- SubagentExecutionCapacity.snapshot derives queued from len(_waiters)
instead of iterating it. snapshot is read from non-loop threads (e.g.
configure_subagent_execution_capacity) while the loop thread mutates the
deque, so iteration can raise 'deque mutated during iteration'. The raw
length may count a waiter that just timed out but has not removed itself
yet, which only makes the busy-check more conservative.
* fix(subagents): close failure-path gaps around background submit
Address both review findings on the background submission lifecycle:
- execute_async() copies the isolated-loop context before registering
the _background_tasks entry, so a context-copy failure (callback-
manager copy or loop-bound handler filtering) can no longer strand a
permanent PENDING entry the caller will never poll.
- _submit_to_isolated_loop_in_context() resolves the loop before
calling the coroutine factory. As direct run_coroutine_threadsafe
arguments the coroutine was created first, so a loop-startup failure
stranded a never-awaited coroutine (RuntimeWarning + retained
captures until collection). Both call sites share the fix.
New tests verified red on the previous implementation, green after:
- context-copy failure leaves no registry residue
- the real submit helper (only the loop getter patched) never invokes
the coroutine factory when loop startup fails
* fix(subagents): close the coroutine when scheduling rejects it
run_coroutine_threadsafe can itself raise once the coroutine exists (e.g.
the loop closes between the lookup and the internal call_soon_threadsafe).
Wrap the call, close the rejected coroutine, and re-raise; a focused test
patches only run_coroutine_threadsafe and asserts the created coroutine
reaches CORO_CLOSED.