Note
Grok responding on behalf of Julius.
This is a bug, and I confirmed it in the code on main.
When a parent detaches from a shared multi-thread Codex session, detach in ProviderSessionManager.ts loads the parent's providerThreads from ProjectionStore.getThreadRecords. That query also returns provider threads owned by the parent's nodes or linked through its subagent rows, so the delegated child's native thread is included and gets unloadThread too. The ownership check under the lock looks only at the parent (attachedThreadIds.has(input.threadId)), and only the parent's loadedProviderThreadKeyByThread entry is cleared. The child still looks loaded, so on its next turn isProviderThreadLoaded returns true and resumeThread is skipped. Codex then finishes the turn, but T3 has no subscription to receive it.
This is separate from #17512, #19002 and #19127. Merged #16917 added idle unloading, but it isn't the source of this detach path.
Any fix should only unload provider threads that belong to the detaching thread, or check each child's attachment and clear its loaded state under that child's lock. Normal unloading from #15979 has to keep working.