# Pull queue performance measurement

This is a manual proof against the real T3 server, not a unit test or a mocked service.
The scenario documentation excludes performance measurements, so the driver starts each
checkout's actual server and drives its HTTP and WebSocket interfaces.

## Run

Install each checkout with `vp i`, then run sequentially on the same machine:

```sh
node bench.mjs <base-checkout> <new-base-output-directory> base 0,3,10 5
node bench.mjs <head-checkout> <new-head-output-directory> head 0,3,10 5
```

Base: `7f81aa8386737ecb244e3fd21c95afdb0649aeb7`, the merge-base of the
head and origin/main. Head: `f7e8b862fb89928a113bab678f729bb34c6707c8`.
Runtime: Linux x86_64, Node v26.13.1. Both ran sequentially on the same machine.

The driver starts the source server with its own fresh data directory and
T3CODE_DEV_SEED=0. It creates projects through HTTP, then calls vcs.refreshStatus
and vcs.pull through the real WebSocket RPC transport. No model is involved.

Each repetition creates N other repositories plus one target. Every repository
has a local bare remote, a cloned working copy, and one new upstream commit.
The server's Git wrapper delays only background status fetches, identified by
`--no-write-fetch-head`, by 2,000 ms. Pull's own fetch is not delayed.

1. Refresh the N other repositories and wait for min(N,4) background fetch starts.
2. Refresh the target. Wait for the end of its pre-fetch upstream lookup,
   `for-each-ref --format=%(upstream:remotename)`, then 200 ms.
3. Reject a repetition if the target is not running for N=0/3 or queued for N=10.
4. Time vcs.pull from sending its RPC request to receiving its success response.
5. Verify HEAD changed to the expected upstream commit and value.txt is updated.
6. Await status responses and fetch drain before the next repetition.

The JSON includes every measured Pull response, phase, background-fetch count,
and fetch/pull timeline relative to the Pull request. All fixtures are synthetic.
The PNG captures render these measured results on a common scale; the text output
and JSON retain the individual values. Private startup logs are not uploaded.

The wrapper adds process overhead and local remotes omit network latency, so
absolute values need not match the PR's earlier benchmark. The controlled
comparison measures the queue wait removed by the fix.
