# fix\(server\): route projection reads through the reader connection · PR \#23867 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/23867)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: open

Source repository: pingdotgg/t3code

Source branch: fix/issue-23687

Target branch: main

Head commit: 7ca41e9da546c518d1b48d7190dca0998bdcf434

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/23867)

[Commits](https://git.cafe/pingdotgg/t3code/pull/23867/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/23867/diffs?format=markdown)

## Description

---

## Problem

Pure projection reads use the writer connection, so MCP thread listing can fail while another connection holds a SQLite write transaction. On current main, holding `BEGIN IMMEDIATE` throughout a real MCP `t3_thread_list` request caused a 5,027 ms wait and `OrchestratorMcpFailure`.

## Change

Route the five projection reads through the existing `NodeSqliteClient.readOnly` helper. Multi-query reads retain their snapshot transactions, and reads inside an existing write transaction retain its writer connection. Reuses vifar's prepared implementation from [#23689](https://github.com/pingdotgg/t3code/pull/23689), with author credit in the commit.

## Scope and approval

Fixes #23687

Triaged bug via the automated issue flow: [#23687](https://git.cafe/pingdotgg/t3code/issues/23687).

## Verification

- Five regression cases failed on main with `expected ['reader'], received ['writer']`; all pass with the fix.
- Final scoped run: `vp test run apps/server/src/orchestration-v2/ProjectionStore.test.ts packages/shared/src/nodeSqliteClient.test.ts` — 2 files, 55 tests passed.
- Scoped lint and server typecheck passed.
- Independent Codex and Claude reviews both returned MERGE; both proof audits returned SUFFICIENT.

Evidence: [sanitized runtime transcript](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/64eeb7463dbc6ac8/issue-23687-evidence.txt). Real dev server used an isolated, seeded 55.6 MB database; the browser paired and loaded successfully. The same MCP request was made while an external write transaction remained open until the response:

| Proof | Before: `2c8bdf6177` | After: `7ca41e9da5` |
| --- | --- | --- |
| HTTP MCP thread list under write lock | Failure after 5,027 ms | Success after 54 ms |
| Server transaction trace | Writer routing; contended transaction failed after 5,013.65 ms | Reader transaction completed in 11.66 ms |

Server-only change; the capture matrix is empty. No rendering or client-contract changes require screenshots or recordings. The reporter's 25.5 GB macOS workload was not replicated; the connection-routing and lock-contention defect was reproduced on Linux with the real server.

Models: GPT-6.1-Sol and Claude Opus 5.5, through Codex and Claude harnesses in T3 Code.

