# Portfolio performance lab runbook This runbook separates executable developer evidence from the two physical release gates. A passing laptop/headless run never substitutes for the named hardware. ## Automated build and transfer gate Run `npm run build:preview`. The build ends with `npm run check:budgets`, which classifies every shipped file exactly once, measures Brotli transfer bytes (or raw bytes for already-compressed formats), verifies that the live Three.js scene remains behind a dynamic import, and applies the exact section 14 thresholds. Unknown files fail closed. Every non-empty manifest media file is hash-checked and deterministically decoded: Sharp verifies image dimensions and `ffprobe` verifies video dimensions and duration against the manifest. Missing probe evidence, disagreement, or an unprobeable asset fails the gate. `config/performance-budget-evidence.json` is the auditable allocation declaration. The checker derives texture bytes as `width × height × bytes-per-pixel × layers × 4/3` for mipmaps, render-target bytes as `width × height × bytes-per-pixel × attachments × samples`, adds declared geometry buffer bytes and the fixed 32 MB allowance, and enforces the Low/High GPU caps. It also enforces peak request concurrency and the 2048-pixel mobile texture bound. High-tier-only chunks use the `high-tier-*`/`environment-high-*` bucket and are capped separately. Any scene allocation or request-scheduling change must update this declaration in the same change; incomplete allocations fail closed. The current empty-media preview measures approximately 7.8 KB for HTML plus critical CSS, 61.8 KB for initial application JavaScript, and 114.2 KB for the deferred first live scene. These values are build observations, not permanent allowances. ## Current-Chromium developer trace Run: ```bash npx playwright test tests/performance/drive-trace.spec.ts \ --project=performance-desktop --project=performance-mobile --workers=1 ``` The two 20-second traces use current Chromium, trusted CDP mouse/key/wheel input, the specified desktop/mobile network profiles, exact action offsets, fixed High/Low rendering tiers, the deterministic Toolkit cancellation barrier, and one fresh browser context per run. Each test writes `drive-trace.v1.json` under its ignored Playwright result directory. Developer reports deliberately contain: - `evidenceKind: current-chromium-developer-machine-non-reference` - `gatingReferenceResult: false` - individual budget booleans and measured values - `pendingPhysicalReferenceRuns: 5` They prove that the harness and interactions execute. They do not make a release claim, even if every number happens to pass. Instrumentation exists only in an authenticated test build, stays inside the page/test process, records no GPU or audio-device identity, and sends no telemetry. ## Five-run physical reference gate Use only the Pixel 6 8 GB / Chromium Mobile Low and M1 MacBook Air 8 GB / Chromium Desktop High reference classes, or hardware with the same CPU/GPU and RAM. Fix both displays at 60 Hz; require battery above 50%, power saving off, a cool start, no foreground competition, page zoom 100%, full motion, Save-Data off, and the exact network shaping from section 14. Record OS/browser/display versions in the private lab evidence, not in shipped artifacts. For each profile, run five fresh temporary profiles from `about:blank`. Clear service workers, Cache Storage, HTTP cache, cookies, local/session storage, and IndexedDB before every run. Reference mode is fail-closed. Create one private `portfolio-reference-run-attestation/v1` JSON file per run with the exact pinned device, Chromium/OS/display, viewport, network, run index/ID, and every environmental assertion recorded. Keep device metadata outside the public repository. Compute the SHA-256 of the exact file bytes, then run one trace with all three variables set: ```bash PORTFOLIO_REFERENCE_LAB=1 \ PORTFOLIO_REFERENCE_ATTESTATION_PATH=/private/evidence/desktop-run-1.json \ PORTFOLIO_REFERENCE_ATTESTATION_SHA256=<64-lowercase-hex-digest> \ npx playwright test tests/performance/drive-trace.spec.ts \ --project=performance-desktop --workers=1 ``` Reference mode rejects missing or extra fields, digest mismatch, wrong hardware/network/profile, failed setup assertions, or disagreement with the browser-observed viewport, visibility, reduced-motion, Save-Data, zoom, and Chromium version. Only a validated attestation can produce `gatingReferenceResult: true`; ordinary developer runs always remain false. A warm-up median outside 16.667 ±1 ms or any per-run budget failure invalidates the run. Aggregate exactly five reviewed JSON paths: ```bash npm run aggregate:performance -- run-1.json run-2.json run-3.json run-4.json run-5.json ``` Aggregation fails unless the set contains unique authenticated run IDs, digests, and indexes 1–5 for one profile, all five are marked reference evidence, every per-run gate passes, worst/median LCP are at most 3.0/2.5 seconds, and worst/median TBT are at most 300/200 ms. Run and aggregate the other profile separately. Do not commit result files until their metadata has passed privacy review. The former High DPR cap of 2 produced a conservative 242 MB estimate at 1440×900 once the antialiased framebuffer, post target, route-sign texture, geometry, and fixed allowance were counted. High is therefore capped at DPR 1.5. The executable declaration now derives 153,078,016 bytes (about 146 MB) for High and 39,508,160 bytes (about 37.7 MB) for Low, below the exact 192/96 MB limits. ## Physical ten-minute protocol `tests/performance/physical-drive.protocol.ts` is the versioned `physical-drive.v1` action generator. A platform runner must consume it without changing timing or order. It uses only `driveTouch` touch and `driveKeys` key sources, round-half-up safe-viewport coordinates, 15×40 ms swipe moves plus a 400 ms pause, and the direction rule sampled at every cycle start. The generator includes rotations, 30-second background periods, audio interruption, context loss/restore, the 389/390-second cycle exclusions, the 390-second Infrastructure barrier and 391-second production-epoch cancellation, live versus terminal-Static pause/resume branches, and Contact settlement at ten minutes. Mouse/pen fallback, scripted click/focus, altered offsets, or emulation in place of the physical devices invalidates evidence. Physical iPhone/Pixel execution remains pending until those devices and platform automation drivers are available. Never mark those rows passed from desktop emulation.