# Evidence recapture round 2

Pinned real apps: before 85bd3f2a2a0ad4a8ddf2950e01db80765e9a1bf4, after 0277fd6975bcf7b79b12833bee93ed714844b319. Detached worktrees /home/ubuntu/wt/pr-28065-cap-before and /home/ubuntu/wt/pr-28065-cap-after. vp install in each. No app source changed.

Scratch root is /tmp/lead-28065-r1/capture2. The adapted round-1 fixture.mjs uses management port 19465 and reads the registry fixture from the after capture worktree. Run node fixture.mjs. It writes a timestamped fixture folder and fixture-run.txt. The synthetic account data and CLI protocol are unchanged from round 1.

Start each server with T3CODE_DEV_SEED=0 vp run dev --home-dir /tmp/lead-28065-r1/capture2/<side>-home from its own worktree. This run used after backend 14194 / web 6154, before backend 16471 / web 8431. Use localhost for Vite's IPv6 loopback listener. Issue each side's own startup pairing credential to the preview browser. Never upload auth files or logs containing those credentials.

Run node seed.mjs <checkout> <home> <backend-port> disable, plan, thread, codex on each side. Fresh databases only; no live database reads/copies. A06 uses the three-account MIX fixture. Before opening Usage, freeze Date constructor/Date.now at 1793674800000. If Limits is already selected, switch to Cost and back to Limits to refresh its explicit render clock. a06-driver.mjs exports capture(tools,tabId,out,side). Use T3 preview, light, 1440x1000. It opens default Session, reveals email, Escape, waits/validates closed; opens Work Session, reveals email, Escape, waits 1.8 seconds/validates closed, then stops.

Create the literal hub-full file under capture2, then run seed ... refresh on both sides. B02/B01/B07 and B06 use FULL. Navigate to the synthetic threads by selecting them in the sidebar; direct URL navigation can leave Syncing messages visible for these synthetic ids. Hide the main sidebar and use identical panel state per pair. Freeze Date before opening the command; await fonts and settled app content. web-driver.mjs exports popupCapture. Use default options for B02 wide, {width:390,height:844,stem:'B02-B01-B07-P-dark'} for phone, {title:'Synthetic workspace evidence',stem:'B06-W-dark'} for Codex. Each recording opens /usage-limits, reveals email labels where present, holds top, scrolls to bottom, holds bottom, clicks Dismiss usage limits, waits 1.8 seconds, asserts the button has disappeared, snapshots, then stops. Two stills 500 ms apart are RGB-compared in the driver. The shared rendering code is unmodified. Reduced-motion emulation is unavailable in preview.

web-timelines.json stores wall-clock driver offsets including recorder-start acknowledgement. Published approximate video timestamps subtract that acknowledgement. One-second timestamped contact sheets independently show the transitions. The preview exports variable-frame-rate video. finalize-web.py decodes and encodes it as H.264 MP4 at 30 fps, CRF 18; it adds no app frames or state changes. Export paths and accepted source paths are explicit in that script. The absolute final frame of every delivered MP4 is extracted with ffmpeg -sseof -0.1 -i <file> -update 1 <final.png>. This run also decoded full streams; all delivered ends show closed state. Empty contact-sheet cells are unused padding.

Native: vp run mobile:install ios --prepare in each pinned worktree returned the same cached native fingerprint 887f84d7e8ee2e1063658bf884c9d17f60d6cbb3. Connect and lease pr28065-r2-ipad through SIMLOCK_AGENT_DEVICE_URL; device iPad Pro 13-inch (M5). The lease belongs to /home/ubuntu/t3code, so install-pinned/package.json runs the pinned install script with that cwd. Run vp run mobile:install ios --session pr28065-r2-ipad from that wrapper folder. No cached client was fetched manually.

Start each checkout's Metro in apps/mobile with REACT_NATIVE_PACKAGER_HOSTNAME=fs-38.tail131df4.ts.net vp run dev:client --port 8085 (after) / 8086 (before). clock-proxy.mjs 8195 8085 and clock-proxy.mjs 8196 8086 prepend only the same fixed Date instrumentation to bundle responses. backend-proxy.mjs exposes loopback backends on reachable 14195/16472. Open the matching clock proxy with the dev-client URL and disableAutoLaunch=1&disableFab=1; accept the system Open alert if present. Pair via that checkout's .agents/skills/test-t3-mobile/scripts/pair-client.sh <backend-port> <home> http://fs-38.tail131df4.ts.net:<public-backend-port> agent-device --session pr28065-r2-ipad.

Clear app data and keychain between sides. OS appearance dark, text-size large. native-steps.mjs records the shared UI procedure: select Synthetic usage evidence, Maximize content, focus the composer, type/select /usage-limits, dismiss Hide keyboard if present, Reveal account label. Do not scroll: the popup starts at zero on both sides and c@example.net is fully visible. native-still.mjs captures twice 500 ms apart and accepts only RGB-identical frames, writing each attempt to a new timestamped directory. OS minute and subtle translucent bottom-tab-bar shading differences between sides are disclosed. Final accepted pointers are native-before-accepted.txt and native-after-accepted.txt; package-native.py copies these raw stills and makes the full-frame diffs and labelled sheet. Compare full raw RGB images with diffs.py: Diff0 per-channel absolute delta x255 clipped, DiffT8 white where max channel delta >8/255; no crops, alignment, or masks.

The round-1 accepted stills/diffs and native recordings are retained unchanged. capture2/evidence-section.md replaces the eight web recordings and their narration, and adds the settled native pair/diffs. It does not edit the PR body. Every delivered frame/diff/contact sheet is visually reviewed. ghdrop output is appended verbatim to the Evidence section.

Cleanup: close pr28065-r2-ipad; close owned preview tabs; SIGTERM only process groups whose PIDs were captured at spawn in processes.json; remove both capture worktrees with git worktree remove --force. Leave capture and capture2 for the lead.
