# Scoped evidence capture, round 2

Scope: replacement E1 failure-only and E3 active-watch C-pass web stills for the exact revisions in the row tables. E2/E4/E5 and H1/H2 results remain the previously accepted captures; only H1/H2's Node label is corrected from the original raw runtime-log metadata. No source edit, commit, push, live Azure call, genuine model call, or PR-body edit was made.

Use the original matrix and round-one recipe linked in Evidence.md. The az fixture routes, seed RPCs, inert provider, natural two-minute scheduler, restart-triggered later phases, viewport, theme, frozen browser clock, scroll, font settings, and native monitor renderer are unchanged. Python runs with `-I`. The copied drivers change their scratch root to `/tmp/lead-24568-r1/evidence-capture-2`; the az stub's shebang also enables isolated mode.

1. Create the exact baseline checkout beside the after checkout and run global `vp install`. Run `python3 -I setup.py`; it creates a new timestamped run and active-run.txt. Each side gets its own fresh home and synthetic project. Start both servers with `server-control.py <side> start`; that driver sets `T3CODE_DEV_SEED=0` and an explicit isolated home. Seed both with `rpc-driver.py <side> seed`. No developer database is read or seeded.
2. Retain subscriptions with `rpc-driver.py <side> observe`. Hold E1-running through the normal scheduled sweep. Switch both fixtures with `phase.py E1-failed rejected,running,running a normal`, then await the next completed actual scheduled sweep with wait-next-sweep.py. Await the inert provider's terminal run via `rpc-driver.py after wait-idle`, and save capture-state.py. Do not advance to a pass phase yet.
3. Use T3 preview tools only. Open each web URL and authenticate privately through its own pairing flow. Resolve environment and thread IDs from each isolated server and ids.json. Navigate to the watched thread. Resize to 1280x900 and set dark appearance. Reuse the round-one browser-driver.js `prep` expression: hide main sidebar and thread details with the app controls, freeze browser Date to 2026-10-27T16:00Z, blur focus, and pause existing status-pulse at time 0. No reduced-motion emulation exists in these tools.
4. Execute browser-capture.js through functions.exec with its tools bindings. The session store supplies beforeTab, afterTab, captureLabel='E1-failure', and the unchanged round-one prep expression. It waits for fonts and one second of resource quiet, records viewport/DPR/fonts/theme/clock/scroll/popup state, takes two whole-viewport preview snapshots at least 500ms apart, and requires pixel equality. It creates a new timestamped capture attempt beneath the run. Save capture-state.py again, still in E1-failed.
5. Replay the exact round-one later phases, preserving the same watch: E2-required-pending, E2-required-pass, its duplicate, E2-all-pass, its duplicate; E3-A-queued, E3-A-rerun-failed, E3-A-rerun-passed, E3-C-pending, E3-C-passed. Each uses phase-run.py and the same status/head arguments as round one. replay-to-c-pass.py lists these phases after E2-required-pending and deliberately stops at C-pass. Before captures, await the completed real startup sweep and the inert provider's terminal run.
6. Hold E3-C-passed. Restore each watched-thread route after the Vite restart, wait for the Watching banner, and run browser-capture.js with captureLabel='E3-active-C-pass'. Save capture-state.py again. The saved watch is non-null on both sides; AFTER has six monitor notifications and BEFORE zero. No unwatch occurs until both captures are complete. The final committed wake and actual inert-provider turn/start input identify `All 2 required checks passed on ccccccc`.
7. Run make-scoped-diffs.py per pair. Diff0 is absolute per-channel delta amplified 32x; DiffT16 marks per-channel delta greater than 16/255. Inspect both selected full-viewport images and both diffs. Zero-threshold differences are confined to the notification summaries/icons and removal of the empty-conversation prompt. Both watch bars and composers match.
8. package-scoped-runtime.py retains synthetic az records, all saved milestones, completed sweep traces, watched-thread committed events from the last pre-cleanup persisted snapshot, source identities/hashes, and provider receipts restricted to turn/start input. It excludes cookies, pairing credentials, keys, provider thread/start configuration, unrelated discovery catalogs, and real data. The full inputs and outputs of the synthetic az fixture are retained.
9. Unwatch PR42 through each isolated server RPC, close both owned preview tabs, stop captured process groups, and remove only the baseline worktree. verify-cleanup.py checks tracked server/provider PIDs and source cleanliness. It reported no live tracked processes, removed baseline, clean after checkout, and 29 GB free.

Driver fixes needed during this replay: the inherited stop command sent SIGTERM and immediately restarted, racing the old home lock; server-control.py now awaits pidfds for the captured group. A trace rotation moved the completed sweep to server.trace.ndjson.1; capture-state.py and wait-sweep.py now read both segments. The affected phases were completed and recaptured without resetting state or changing source. replay.log retains the original failure, while phase/milestone/event recordings show the continued sequence.

Uploads use `ghdrop upload -m`. The VM DNS resolver intermittently failed. Direct retries succeeded. A process-local CONNECT tunnel was tried and stopped, but a connection trace showed ghdrop bypassed it; do not attribute the successful uploads to that tunnel. No system resolver configuration was changed. upload-transport.py is retained for completeness, not required for replay.
