# PASS1 refresh — proof audit for issue 23661

Issue [#23661](https://git.cafe/pingdotgg/t3code/issues/23661); prospective PR, no PR exists or is claimed. Complete five-file diff read from [fef851bee0](https://git.cafe/pingdotgg/t3code/commit/fef851bee0) to [cfb3ad9a0f](https://git.cafe/pingdotgg/t3code/commit/cfb3ad9a0f654bbd400f9b4c09a370cf4ec18a2c). Worktree `/home/ubuntu/wt/issue-23661`, branch `fix/issue-23661`, HEAD verified and clean. This is source-derived proof planning, not approval or a reproduction. No tests, browser, server, repository edits, live data access, pushes, comments, or merges performed. Scratch and upload only.

Supersedes the [prior matrix](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/7bbe756ef9977525/matrix.md). Lead reports prior-head integrated normal success passed; this audit has not inspected that capture. Prior timeout video is INVALID: test-generated `.vite-temp` caused dev-server restart. It proves neither healthy-socket timeout nor recovery. Lead reports ports 8006/16046 STOPPED until reviews/tests finish; do not connect, start, or assume readiness. Capture agent must coordinate fresh server and exact base/head switching with lead.

## Refresh findings and boundaries

| Changed file | Current behavior and proof consequence |
|---|---|
| apps/web/src/components/chat/useComposerSend.ts | One replaceable deferred submit, not FIFO. Inner send claims generation synchronously; completion settles only matching generation AND route. Auto follow-up becomes queue. Clear after upload/dock awaits only when submitted draft content is unchanged (direct annotation remains unconditional). Drain cancels with informational unsent toast if approval or active pending question is present. |
| apps/web/src/components/ChatView.logic.ts | Comparator uses exact prompt, ordered image/file IDs, reference identity for four context arrays. Model/mode/provider and upload metadata ignored. Helpers separately settle route/generation and choose wait/send/drop/cancel. |
| packages/client-runtime/src/operations/commands.ts | Two-minute answer deadline now wraps BOTH message.dispatch branches AND launchThread for first message/worktree bootstrap. No generic RPC deadline or retry. Timer starts around request, after attachment persistence, command allocation and relevant projection/capability awaits. Worktree preparation after commit is not capped. |
| ChatView.logic.test.ts | Comparator and settlement/resolution examples include wrong route/generation, null generation, unsuccessful start, pending request, edit and navigation. Pure helper coverage, not hook lifecycle/promotion integration. |
| packages/client-runtime/src/operations/commands.test.ts | Fake supervisor records one request then never answers. New exact 119s pending/120s typed-error assertions cover normal default send and createThread launch. Not an integrated client result; explicit-start and prepareWorktree branches, late commit, cancellation and UI restoration are not separately exercised by these new tests. |

All four prior blockers have source changes addressing them; do not call them visually verified. The old statement “launchThread bypasses deadline” is obsolete. Draft promotion remains an integration boundary because route and draft target change. Pending request cancellation is checked when ready/unblocked; a request that arrives and disappears before draining is not recorded historically. Confirm the intended race with Review2 rather than claiming “any request ever arrived” from this code. Exceptions escaping the inner promise still bypass settlement after `await`; focused review/tests own that concern.

No JSX, CSS, native UI, adapters, server, contract, Electron shell/IPC or docs changed. Main chat submit routes converge on the web hook; direct annotations bypass deferral, resume/multi-model paths do not gain this deferred wrapper. Shared startThreadTurn callers (plans, retries/forks, mobile outbox/new task, etc.) inherit the answer deadline when reaching wrapped requests. No need to exercise unrelated shell features, six provider adapters, native installation flows, or a new transport architecture.

## Practical capture matrix

Every interaction or time claim needs RECORDING; stills supplement only. All rows below are UNVERIFIED at this head unless a capture agent later supplies an individually inspected artifact and ledger. Reported prior-head normal success is context only.

| ID | Real-app seed/action | Observable acceptance | Minimum placement / status |
|---|---|---|---|
| A1 success | Established idle thread; delay ONLY next message.dispatch 10s; FIRST, then type SECOND and Enter while FIRST sends. | SECOND remains until successful first answer; exactly one second dispatch, queue intent (resolved delivery depends on active run), both visible. Do not wait for agent completion to establish dispatch. | C1 1440 light, C2 390 dark; UNVERIFIED |
| A2 repeat | In A1 press Enter repeatedly on unchanged SECOND. | One replaceable deferred submission, one SECOND dispatch. | Append C1; UNVERIFIED |
| A3 edit/clear | Defer SECOND; edit without Enter; separate reset clears; third reset edits then Enter again. Include typing during FIRST's pre-dispatch upload/dock await when reproducible. | Edited next content survives original clear and is not sent automatically; clear cancels; resubmitted changed snapshot sends once. No assertion that attachment metadata changes are user edits. | C5 1440 light, labeled segments; UNVERIFIED |
| A4 navigation/stale completion | A pending send on thread A; navigate to established B; start B and defer B2; release A before B, then release B; return A. | A completion cannot release/cancel B2; only B completion can. No follow-up into destination accidentally; returning does not replay abandoned A intent. | C5 independent reset segment; UNVERIFIED; pure helper test supplies source-level support only |
| A5 timeout with follow-up | Withhold ONLY next existing-thread message.dispatch; healthy Ping/Pong/other traffic; FIRST then SECOND+Enter. | Uncut ~120s from request: existing slow warning near 15s is baseline; explicit “server did not confirm…may still arrive” error at deadline, busy releases; SECOND retained, unsent info toast, no auto retry. | C3 1440 dark, C4 390 light; >=125s each; UNVERIFIED; previous timeout video INVALID |
| A6 restore | Same unanswered request with NO SECOND; after timeout inspect restored FIRST and manually send only after confirming suppressed frame never reached server. | Original snapshot restores into empty composer, optimistic state settles according to existing path, manual send available. With SECOND present existing failure path preserves SECOND and may retain FIRST optimistic state; don't promise server absence. | C6 390 dark; UNVERIFIED |
| P1 promotion | Fresh New Thread; delay launchThread; FIRST then SECOND+Enter through promotion; release. Also withhold launch answer once, preferably reuse A6 recovery protocol. | Inspect draft-to-thread transition, preservation of SECOND and any dropped intent; no send in unrelated composer. Launch unanswered now fails at 120s; preparation continuing after ack is not timeout. Record actual behavior rather than assume A1 equivalence. | C7 1440 dark; timeout may be second labeled segment; UNVERIFIED |
| A12 approval/new question | Real provider already active; arrange a NEW approval or user question after SECOND is deferred but before it drains. Keep request outstanding, then allow first request answer. Run approval and question separately if both can be seeded. | SECOND remains plain composer text; no approval feedback/question answer RPC carrying it; one unsent toast, explicit later user action needed. Show actual request UI and sanitized RPC count. | C8 390 light (or append C5); UNVERIFIED; conditional on real-app seed, never claim pure helper test proves UI |
| A7 comparator bookkeeping | Same IDs while image persistence/preview metadata changes; model switch while deferred; context chips where naturally available. | Metadata/model change alone doesn't cancel; actual content removal does. Equal-content newly allocated context arrays currently cancel by identity. | Focused helper tests + optional recorded A3 extension; UNVERIFIED UI |
| A8 modes/other callers | Representative active-run ordinary auto; explicit intent/resume/multi-model/direct annotation/plan paths assessed by focused tests. | Queue rather than unintended steering; existing bypasses retain behavior. No claim all callers gain deferral. | Record any claimed interaction; focused tests proportional to changed branches; UNVERIFIED |
| A9 rejection/blockers | Reject first request or disconnect while deferred; recover; exercise relevant detail-loading/setup blocker in focused tests. | No ready drain from failed start; preserve draft, no automatic retry. Blocked successful start drains at most once after unblocked. | Focused lifecycle tests; record if included as client claim; UNVERIFIED |
| A10 late commit/transport | Fake transport receives then withholds answer, later commits/responds; non-message RPC unaffected. | No duplicate retry; late arrival is possible and error copy remains honest. Outgoing suppression alone cannot prove receipt/late commit. | Focused transport tests; no extra visual gallery required; UNVERIFIED |
| M1 native mobile | iOS/Android existing-thread outbox and new-task launch reach shared deadline. | Restore/error and outbox lock release/no unintended duplicate. Native composer uses separate logic, no new web deferred wrapper. | BOTH iOS and Android UNVERIFIED; responsive 390px is web only. No native build/install prerequisite imposed for this research task |
| E1 Electron | Shared web hook + runtime deadline in Electron renderer. | Core A1/A5 smoke if claiming desktop tested. No shell or IPC feature changed. | Electron renderer UNVERIFIED; web recording supports shared code only, not native runtime claim |
| R1 connection modes/providers | Local, remote/relay/tunnel and provider variations. | Deadline belongs to shared client; unchanged adapter/shell behavior is source-derived scope, not verification. | Local/remote/relay/tunnel all unverified in this audit. One usable provider sufficient for web capture; no six-provider gallery required |

## Proportional minimum pack

Seven web recordings preserve the original lifecycle floor: C1 A1+A2 (1440x900 light), C2 A1 (390x844 dark), C3 A5 (1440x900 dark), C4 A5 (390x844 light), C5 A3+A4 independent reset segments (1440 light), C6 A6 (390 dark), C7 promotion plus launch-timeout segment (1440 dark). C8 cancellation is required if the real app can seed it safely; it may be a labeled C5 segment, so file count is not the requirement. Recordings can contain independent labeled resets; don't imply a single continuous scenario when concatenated. These cover both changed main visible outcomes at both widths and both themes overall, not every Cartesian cell. No theme/style changes justify duplicating all branches four ways.

For before/after: coordinate exact base and head with lead, same synthetic markers, viewport, theme and injection. Capture matched A1 and A5 baseline at the four core cells if claiming the corresponding comparisons. Baseline A5 must show it remains pending past 120s; end with controlled cleanup rather than indefinite wait. Preserve label of existing 1280x800 baseline; it cannot stand in for 1440 or 390. Base Enter was reportedly ignored while retaining SECOND; do not relabel it as reproduced text erasure. New-head-only branch captures may stand alone with explicit unverified baseline; missing footage is a visible evidence gap, not permission to invent it.

Overlay commit, CSS viewport, theme, run marker and wall elapsed time (no secrets). Show composer, timeline, error/toast at 390 without clipped controls. For all recordings retain sanitized ledger of first captured frame, forwarded count, RPC answer/projection order, second dispatch mode, Ping/Pong times, socket close/reload and server uptime. A delay callback alone is not acknowledgment. A successful prior-head capture does not prove current head.

## Seeding and controlled transport constraints

Lead alone owns fresh server startup after tests/reviews, base/head switch, isolated `.t3`, and PID cleanup. No SQLite writes while running, no live `~/.t3/userdata`, no migration against live state. Seed through real UI: project in worktree, available provider, harmless “reply ready without tools”, let initial turn finish; second established thread for A4. P1 intentionally starts fresh. Synthetic unique FIRST/SECOND per run; no actual conversation/state in public artifacts.

Temporary page WebSocket send wrapper is sufficient for client-observable stall. Inspect real envelope first, fail closed. Match next `orchestration.dispatchCommand` with payload `type: message.dispatch`; for P1 arm separately for `orchestration.launchThread`. Never match all dispatch commands or both paths accidentally. Consume injection before scheduling; retain original socket/data/native method; delay forwards exactly once at 10s; no-answer never forwards this frame. All other traffic, Ping and control RPCs pass. Restore wrapper per run/reload; discard if socket closes before release. Do not reconnect/replay captured data or blindly resend potentially delivered FIRST. No fake browser clock.

Approval/question seed needs an already active REAL provider turn able to emit that pending request during the narrow wait. Prefer holding the FIRST response inbound while letting server commit/provider events flow, so the request can appear while its send still awaits acknowledgment. A simple outgoing FIRST suppression prevents that FIRST from generating a request; an already active prior turn could still generate one. Inbound response-only delay must match the inspected FIRST request ID, preserve all event/Pong frames, and forward that response once. Do not hold every incoming frame or insert fake DOM/store/DB pending requests and call it integrated proof. Use ordinary safe question or provider permission behavior; do not trigger destructive tools merely to obtain approval. If available provider/mode cannot produce it, mark A12 approval and/or question UNVERIFIED with exact reason and retain focused helper tests as limited support.

Run tests/builds BEFORE fresh capture server starts. Test-generated `.vite-temp`, HMR/reload, socket replacement, process restart, missing Pong continuity, or changing commits mid-recording invalidates timed run; restart the capture from a clean known state. Don't count a restart/transport failure as healthy-socket timeout.

## FRICTION and handoff

- No browser/server access in this subtask; all UI rows unproduced and explicitly UNVERIFIED. No dependency on stopped ports was exercised.
- Full diff inspected; clean exact head confirmed. Tests read, not run; Review2 is independent and its outcome was not supplied here.
- Four fixes present in source. Request-cancellation historical race and comparator reference semantics remain proof limits to discuss with reviewers, not newly proven blockers in this research pass.
- Prior timeout recording invalid; fresh uninterrupted timing evidence required after lead finishes tests/reviews. No standalone server or second capture owner was created.
- Native mobile and Electron gaps are explicit and limited to affected renderer/runtime paths. No unrelated native operations are required to close this web proof pack.
- Public upload contains source-derived instructions and synthetic fixtures only. Owned scratch is limited to this matrix under `/tmp/issue-23661-proof-matrix`; no committed drivers or repository artifacts.
