# WAL reader reproduction

AI-assisted; verified with the tests and tools listed above.

## Environment

Linux, Chromium web client, light theme, 1280 × 800 CSS viewport (recordings are 2560 × 1600 pixels). Each commit runs its own real dev server from a dedicated checkout and a fresh, unseeded T3 home. All project and conversation data is synthetic. No test result is used as evidence.

Base: 3a8c250cb0c8056f2f563091fd412fe5db809fa1
Head: 04930a115d638086ac195b2eb494b181fed5a400

## Run on each commit

1. Install dependencies with `vp i`. Start `T3CODE_DEV_SEED=0 T3CODE_AUTO_BOOTSTRAP_PROJECT_FROM_CWD=0 vp run dev --home-dir <fresh-home> --no-seed`.
2. Configure that fresh home's settings to disable real providers and use the dev replay provider, recording `multi-turn`, as default. Start `node manual-driver.mjs <checkout> <fresh-home> <new-output-directory>`.
3. Pair the web client with the server's startup pairing URL. The driver creates a git project and a thread named **Reader admission check**, with one completed replay turn, through the real CLI and server.
4. Create `<new-output-directory>/start-load`. The driver opens the database read-only and executes `BEGIN; SELECT count(*) FROM sqlite_master`, holding the transaction open. It launches batches of four replay turns with identical 118,415-character synthetic prompts. Stop after the WAL exceeds 128 MiB or a batch stays pending for 15 seconds. Both runs requested 48 load turns.
5. In the web app, search for **Reader admission**, select **Reader admission check**, and close the thread details panel. Start recording. Fill `[data-testid="composer-editor"]` with **second**, then press Enter.
6. Keep the reader open for approximately 55 seconds after submission. On base, **Working** and the slow-request warning remain visible; there is no completed reply. On head, **second fixture turn complete** appears immediately. A separate read-only query confirmed the head's web message and final assistant response were persisted while the original reader remained open.
7. Create `<new-output-directory>/release-reader`. The driver commits and closes its reader and records the WAL size without requesting any more writes. Keep recording until the base's queued reply completes. Both WALs fell to zero. On head, all turns had already finished, so this specifically demonstrated idle reclamation without another write.

The recordings show the same message submission and observation interval on each side. The base recording also shows the queued reply completing after the reader is released. The companion runtime transcript reports the actual WAL sizes and persisted message timestamps.

## Results

- Base: WAL pinned at 134,237,872 bytes; final load batch pending; web message blocked until reader release, approximately 55 seconds after submission.
- Head: all 48 load turns completed; WAL 135,267,872 bytes before the web message, then 137,340,232 bytes; web reply persisted while reader stayed open. After all writes stopped, reader release let idle retries reclaim the WAL to zero.

Desktop, mobile, provider-specific behavior, and longer sustained load were not exercised.
