# Round 2 rebuild

Only W4, W5 dark six/terminal hover and M2 native sidebar were captured for [#24317](https://git.cafe/pingdotgg/t3code/pull/24317). Before [36d4d711b7](https://github.com/pingdotgg/t3code/commit/36d4d711b79c73eb33131944f73ea4a8c6156484), after [cb6a593a16](https://github.com/pingdotgg/t3code/commit/cb6a593a16050106ea2523bb827c4677a7e18791). The corrected audit makes W2 N/A. Other rows retain round 1 evidence.

Download the index's scripts into one scratch directory. They deliberately encode the capture root, checkout paths, fs-14 tailnet name, session names and ports; change those consistently when reproducing elsewhere. The files contain no credentials. Original round 1 scripts are linked as provenance; these are their round 2 adaptations.

## Setup

1. Install each pinned checkout with `vp install`. The before checkout was created with `git -C /home/ubuntu/t3code worktree add /home/ubuntu/wt/pr-24317-before 36d4d711b79c73eb33131944f73ea4a8c6156484`. Do not use later main. Keep tracked files unchanged.
2. Start each real app with `T3CODE_DEV_SEED=0 vp run dev --home-dir <scratch>/<side>-home`, capturing its spawn PID/session. Before backend16050/web8010; after backend15942/web7902. Fresh databases at each checkout's own migration level; no live data was read/copied. No VITE origin override.
3. Create a synthetic empty Git workspace at `<scratch>/workspace`, main branch, one empty commit, no remote. Pair each real browser through the normal pairing screen using `pair-browser.mjs`. Mint its short-lived pairing link privately with `T3CODE_PORT=<backend> node apps/server/src/bin.ts auth pairing create --base-dir <scratch>/<side>-home --base-url http://localhost:<web> --ttl 30m`. Store stdout only in `<side>-pair-private.log`; never upload credentials.
4. Once initial navigation settles, run `node seed-browser.mjs before|after`. `seed.js` uses public app RPC, real project/thread/link/snapshot commands and shell readback. All data is synthetic and no provider prompt is sent. A navigation-interrupted seed must resume only after checking existing IDs; do not blindly duplicate creates.

## Web

Use headed Chromium156 with an owned Xvfb display and named sessions `r2-evidence-hover-before` and `r2-evidence-hover-after`; preserve paired private auth between launches. Headless mode is unsuitable if it reports no fine-pointer hover. The driver's hover phase rejects that. The actual binary path is in `web-capture.mjs`; CLI0.39.2 was installed here. Run sides serially: `node web-capture.mjs <side> hover`.

The driver sets 1440×900 CSS/pixels, DPR1/zoom1, dark/reduced-motion, top scroll, selected MIX6, and collapsed settled shelf. It installs fixed Date at 2026-10-29T12:00:00.000Z **before app module initialization via CDP**, then reloads. This avoids cached minute/age differences. The original fixture snapshot clock remains 2026-10-27T12:00:00.000Z. It waits for fonts and network quiet, blurs focus for stills, requires two screenshots 500ms apart to be identical, and records actual command times. Latest driver dismisses an existing host-warning toast through its ordinary close button before recording. No backdrop CSS, pixel, or alpha repair was applied.

Sequence: t1 query15702; t3 hover settled six; t5 still; t12 query15703; t14 hover settled terminal; t16 still; t23 Clear search; t25 pointer away. The delivered new stills use the same scene sequence; accepted round 1 interaction videos remain linked. New trial recordings are in the archive, not credited: they show a transient host-load warning at the start. An optional later refresh hit daemon timeouts and was abandoned after the required clean stills were complete.

`web-pairs.json` selects the two delivered before/after pairs. `web-corner-investigation.json` records the suspect pixels across unmodified same-SHA retakes. A same-before-SHA screenshot changes (4,69) from RGB3,3,3 to3,3,4 without a code change. The location is the dev blueprint/grain gradient fade, not a scrollbar or focus ring. The most plausible cause is renderer compositing/8-bit quantization; exact browser internals were not instrumented. Initial full rerenders/reloads, equal launch conditions and settled full-image comparison removed it; final RGB3,3,4 on both sides. No pixel is masked or edited.

## Android Pixel Tablet

Prepare through `vp run mobile:install android --prepare`, then lease Pixel Tablet using `agent-device connect proxy --daemon-base-url "$SIMLOCK_AGENT_DEVICE_URL" --session r2-evidence-24317` and `agent-device open --platform android --device "Pixel Tablet" --session r2-evidence-24317`. Every device command uses that session and the after checkout cwd. Install only with `vp run mobile:install android --session r2-evidence-24317 --metro http://fs-14.tail131df4.ts.net:8081`. Both pins have native fingerprint ed36a9cc9856c84a322bb71e6d67744f0a00877d; one cached native dev client serves both JS bundles.

Run Metro from each checkout's apps/mobile using `REACT_NATIVE_PACKAGER_HOSTNAME=fs-14.tail131df4.ts.net vp run dev:client --port 8081` (after), 8082 (before), all interfaces. `mobile-forwarder.mjs` exposes loopback backends on25942/26050 for the tablet. `trim-m2.mjs <side>` uses public RPC to remove synthetic controls not needed in this row, leaving active MIX6, MIX2-T, MIX2-P, MIX6-B and OPEN plus two collapsed settled clones. Do this identically on both sides, after web capture.

Enable rotation (`orientation auto`) and landscape; set system animations off and font scale1.0. On this device `settings text-size large` produced1.0; medium produced0.94 and was rejected. Read back Dimensions/PixelRatio; accept only 1280×800 logical,2560×1600 pixels, density2/fontScale1. FULL_USER tablet orientation and width≥720/height≥600 enable the real split layout.

Open `t3code-dev://expo-development-client/?url=http%3A%2F%2Ffs-14.tail131df4.ts.net%3A<metro>&disableAutoLaunch=1&disableFab=1` with `agent-device open com.t3tools.t3code.dev <url> --session ...`. Pair only the corresponding synthetic backend via `native-pair.mjs <side>` **before freezing Date**. Async Hermes pairing/removal returns a Promise object: read `evidencePairResult` / `evidenceRemoveResult` and the real catalog before continuing. `native-remove-environments.js` removes only these synthetic connections before a bundle switch.

Apply `native-init.js` via `native-eval.mjs <metro-port> <script-file>`. It freezes app Date, hides the Android clock/status bar consistently, disables the working shelf and collapses settled. Wait for minuteTick to catch up to2026-10-29T12:00 (an already scheduled tick can take up to one real minute). The driver rejects stale minute snapshots. Let the hidden-status-bar safe-area update settle across a warm reload; a cold-start vs warm-start top-inset mismatch was rejected. Never move/crop-align the full screenshots to hide this difference. Final full-image comparisons prove matching insets.

Select MIX6. It and MIX6-B must appear selected/unselected simultaneously, with MIX2-T/MIX2-P and OPEN fully visible. Run `node native-capture.mjs <side> m2` (both themes), or `m2-dark` for the identical dark retake. Each theme first taps Maximize content, starts recording, t1 taps Show sidebar, t5 takes the two-frame-verified still, and t12 reads accessibility. Screenshots are whole-screen. Crops are additional exact rectangles (144,0)-(904,1600), never a substitute.

Android screenrecord is VFR and encodes only screen changes. Delivered clips have2.56–3.54s encoded duration although capture windows are13–21s; their final frames include the fully opened sidebar. No later static tail or timing/performance promise is claimed. `review-native-videos.py` decodes every frame of these short clips using their actual PTS, including the final frame. The native-final-after manifest combines completed light and the later completed dark retake; the first dark readback timeout remains only in the archive.

## Diffs and review

`assemble-evidence.py <final-dark-run-directory>` reads `web-pairs.json`, makes native full-screen pairs and additional760×1600 sidebar crops, runs `image-diff.py`, and writes `final-pairs.json` plus labeled four-panel sheets. Diff0 is raw absolute RGB channel difference multiplied by255; DiffT highlights max-channel delta strictly >8/255. No alignment, masking, or repair. Full-screen pairs are compared before cropping.

All delivered original stills, both diff images and composites were opened and visually checked. All frames of native clips were inspected; accepted round 1 web videos retain the auditor's prior review. The archive contains failed/earlier captures for diagnosis; only final-pairs.json and the index identify accepted stills. It also contains scrubbed logs and metadata/AX/PTS sidecars. Auth homes, databases, pairing logs/state, raw private logs and JS bundles are excluded. `package-artifacts.py` packages the public subset and creates content hashes. `upload-assets.mjs` uses `ghdrop upload -m`, retaining verbatim output.

Stop owned tracked server/Metro/forwarder sessions, close browsers/preview and release the pool device. Remove only the owned before worktree and scratch subdirectory after upload; preserve the lead's after checkout. No product source, commit, push or PR body edit is involved.
