# Runtime proof for PR 25121

Base: 83d238218d86a035ab3674efb09e51fd68437712
Head: 2215634bf375e4398d7953d17ad004494f30148e

Both commits ran with `vp run dev`, `T3CODE_DEV_SEED=0`, separate fresh T3 homes, synthetic project/thread data created through the CLI, the free dev replay provider, and the same leased Pixel 9 Pro Fold (Android 36), returned between runs. Browser viewport: 1280×800 CSS pixels, DPR 2, light theme. No application source was edited. No tests supplied the evidence.

## Controlled screenshot faults

Natural malformed screenshots were not observed. These captures deliberately deliver malformed bytes to the actual consumers, rather than asserting that the pool naturally generated them.

1. Configure a Simlock device source from the existing pool environment credentials, enable device support and agent access, and open the named foldable through the real app's device.open command. Open its Device panel.
2. For the server boundary, rename the worktree-local installed agent-device entry to `agent-device-original.mjs`, and put `fault-wrapper.mjs` at the original entry path. This wrapper still runs the real command against the leased device. After it succeeds, the wrapper prepends/appends warning text or cuts the resulting PNG in half, according to the adjacent `proof-mode` file. Application source and the PNG implementation are untouched.
3. Issue a short-lived bearer token with the app CLI; pass its filename to `server-capture.py REPO TOKEN_FILE SIDE DEVICE_ID`. It calls the real authenticated HTTP screenshot route in clean, warning and truncated modes and records the response bodies. The script restores clean mode.
4. Independently inject the same two faults at the browser fetch response boundary using `client-ui-driver.js`, while the server returns clean screenshots. Set `window.proof.fault` to `warning` and then `truncated`. The script locates and invokes the existing DeviceControlsRail.onScreenshot callback. Simlock hides the Save screenshot button, so these are direct invocations of the real handler, not clicks on a visible control. The handler runs the real captureDeviceScreenshot implementation and its real download/error UI. An observer records the resulting downloads or alert; Chromium's createImageBitmap records whether each exported image decodes. No assertion replaces the app behavior.
5. Open the actual downloaded warning-image files in Chromium's native image viewer. Base displays a broken image; head displays the screenshot. The viewer screenshots show these real download files. For truncation, base creates an undecodable download without an alert; head creates no download and displays the incomplete-screenshot alert in the Device panel.

Stills were accepted only after two captures at least 500 ms apart had identical SHA-256 hashes. The live device clocks and replay timestamps differ between commits; all seeded conversation content, device model, theme, viewport and fault steps are the same.

Server transcript: base returns HTTP 200 for both malformed cases (warning PNG signature at offset 36; truncated response missing IEND). Head strips the warning bytes (signature at offset 0; IEND at the end) and rejects truncation with HTTP 500 and no image body.

Client transcript: base warning download retains all 3,450,756 bytes and fails Chromium decoding; head removes the 65 surrounding bytes and exports a decodable 2076×2152 PNG. Base truncation downloads 1,725,486 bytes and fails decoding; head reports “The device returned an incomplete screenshot. Try again.” and downloads nothing.

The focused head video removes only the first 40 seconds of stream connection setup from the raw recording; the raw recording is preserved in the bundle. The base recording has no such prelude. Handler invocations occur through the browser driver and therefore do not show a pointer clicking the hidden button.

## SDK discovery and Gradle

Run `sdk-discovery.py BASE_REPO HEAD_REPO` on Linux with real `/usr/bin/adb`. It creates an isolated HOME whose standard Android/Sdk/platform-tools/adb points to that real binary, and a PATH containing only node/git/sh. Neither SDK variable is set. The exact real `mobile-native-client.ts ensure android` command fails adb discovery on base, and reaches device lookup on head. Setting ANDROID_HOME is the control: both commits then reach device lookup. No local emulator is connected.

Run `gradle-environment.py BASE_REPO HEAD_REPO`. This invokes the real `ensure android --prepare` command with native caching disabled and local builds selected. It runs real Expo prebuild and the generated Gradle wrapper. The isolated Gradle init script prints System.getenv("ANDROID_HOME") and intentionally aborts before any build tasks. Base prints `<unset>`; head prints the isolated HOME's default Android/Sdk. Both commands intentionally exit 1 after this measurement. This verifies the actual Gradle child environment; it does not claim a completed APK build or installation.

All tokens and configuration credentials are excluded from the uploaded artifacts. Cleanup returned the leases and stopped the development servers and Gradle daemon.
