# Real web composer performance comparison

The measurement driver runs Chromium against two separate web development servers. No parser microbenchmark or test is used as performance evidence. Both servers use fresh, revision-specific T3 homes with `T3CODE_DEV_SEED=0`, the same synthetic README project, and one completed free `devReplay/multi-turn` seed turn. The driver opens a **New thread** in that project before measuring; no measured text is sent to an agent.

## Reproduce

1. Create a worktree at each revision and run `vp i` in each. Run `T3CODE_DEV_SEED=0 vp run dev` separately in each worktree and retain its session. Read each startup URL locally; pairing URLs are credentials and must not be uploaded.
2. Run `bash seed.sh CHECKOUT CHECKOUT/.t3 SYNTHETIC_PROJECT THREAD_JSON` for each revision. Use the same synthetic project path and separate thread JSON files. If the server is still starting, wait for startup before running the seed.
3. Pair a browser to each server and save a local Playwright storage-state JSON. These authentication files must stay local. Install the checkout's Playwright Chromium headless shell if needed.
4. Run `node measure.cjs CHECKOUT ORIGIN AUTH_STATE THREAD_JSON OUTPUT_ROOT before BASE_SHA`, then the identical command with the other checkout, origin, authentication and thread files, `after`, and `HEAD_SHA`. Run one measurement at a time on the same machine.

The driver creates a new timestamped output directory. It records video, individual per-key durations, paste durations, long tasks, output text hashes, normalized DOM hashes, and stable screenshots. It never uploads credentials. Its overlay is explicitly identified as driver output, and is separate from the app UI. The thread details panel is closed before measurement to keep machine names out of captures.

## Measurement

Each case has three independent composer resets. Clear; type `check `; type `@README`; wait for the suggestion; press Enter to create the README chip; type a space; write the repeated chunk to the system clipboard; press Ctrl+V; press `t`, `y`, `p`, `i`, `n`, `g` separately. Cases: `( a ` ×1500 control; `\( a ` ×250, 500, 1000, 1500; `\[` followed by newline ×1000, 1500.

The timer starts in a capturing listener on the trusted DOM `keydown` or `paste` event. It ends in a zero-delay task scheduled by the next `requestAnimationFrame`, after the rendering opportunity. This measures input-handler/React/parser/layout work through the next paint opportunity, without automation transport overhead. It is not a physical display latency measurement. Chromium is headless, Linux, no CPU throttling, 1440×1000 at scale 1, dark theme. Browser version is in the JSON.

For each case the summary median is over all 18 keys; the three run medians and all individual keys are retained. A run-median spread is maximum minus minimum of those three medians. The comparison should exceed both sides' spread and retain identical output. The driver compares paragraph text joined with newlines against the expected parsed text (multiline clipboard paste starts a new paragraph in this editor), a single README mention chip and trusted events after every run. Cross-revision text and normalized rendered-DOM hashes are compared separately by the report script.

Before each still, the driver de-focuses the editor to remove caret blinking, then requires two byte-identical screenshots 500 ms apart. Videos are trimmed only to remove initial navigation/pairing and are otherwise played at real speed. Trimming/encoding commands and timing offsets are recorded in `process-captures.py` and the JSON. Uploaded content contains only synthetic fixture data.

Short 1,500-opener excerpts show paste and typing, from 0.25 seconds before paste until 0.75 seconds after the final key; they retain original speed. Full recordings contain every reset and repeat. The evidence bundle contains all 42 stable stills, both full recordings, the short excerpts, raw measurement JSON, comparison output, environment metadata, and all source scripts.
