PR 32561 runtime verification, 2026-11-10 Baseline: github/main e89abadaee70e0d73fb19a5ce40a686b1a92310e git worktree add ../main github/main cd ../main && vp i T3CODE_DEV_SEED=0 setsid nohup vp run dev > /tmp/main-dev.log 2>&1 & Actual server:16733 / web:8693; isolated /home/user/main/.t3 Playwright 1.60.0 with /usr/bin/google-chrome. Created project and Codex gpt-6.1-sol threads through the web app. Thread A: prepare_upload + real HTTP POST, ownership.txt, 16 bytes. Thread B: t3_thread_send_attachments(A's pending id) => isError:false Thread B: t3_thread_launch(A's pending id) => isError:false Launched Codex thread completed. Stopped main by captured process group 34746 before starting PR. PR exact head: b3c5eb2e9c9a8e8607c6916ef5a4c7c352902566 vp i setsid nohup vp run dev --home-dir /home/user/t3code/.t3 --no-seed > /tmp/dev.log 2>&1 & Actual server:13773 / web:5733; isolated /home/user/t3code/.t3 Same file contents, same model, web-created project and threads. Thread A: prepare_upload + real HTTP POST => success Thread B: send A's pending id => invalid_request Thread B: launch with A's pending id => invalid_request Thread B: discard A's pending id => invalid_request Error: Only the caller that prepared a pending upload can send/discard it. Thread A: launch with own pending id => isError:false Launched Codex read ownership.txt => OWNERSHIP-32561 Thread A: send own pending id => isError:false Thread A: discard own pending id => isError:false Reuse existing claimed attachment into idle target => isError:false Target Codex read reused attachment => OWNERSHIP-32561 Web file chooser upload => Codex read WEB-UPLOAD-32561 blacksmith-check run --id [task worker] 'vp i && vp test run apps/server/src/mcp/toolkits/core.test.ts apps/server/src/mcp/toolkits/project/handlers.test.ts' 2 test files passed, 31 tests passed. Worker stopped. Limits: native desktop/mobile; other providers; external client-session ownership; restart/24-hour expiry not exercised. One active self-send was accepted server-side but local provider proxy returned no active upstream websocket for response.interrupt. The idle-target reuse above completed successfully. No source changes made.