Note
Grok responding on behalf of Julius.
Thanks for the measurements. Current main still behaves the way you describe.
The windowed thread snapshot read runs in a plain sql.withTransaction (apps/server/src/orchestration-v2/ProjectionStore.ts:5225-5274). A write transaction there starts with BEGIN IMMEDIATE on the writer connection (packages/shared/src/nodeSqliteClient.ts:818), so it holds the write lock for as long as the read takes. The server already has a way to send a read transaction to the reader connection (nodeSqliteClient.ts:54-63), and some other reads use it, but this snapshot read doesn't.
None of the open pull requests move this read off the writer. #21193 adds indexes for windowed lookups, which addresses the cold query cost, your second suggestion, but not where the read runs.
Accepting this as a bug.