# V3 Web First-Load Budget

Canonical source: `libs/oshun/analytics/src/v3-web-first-load-budget.ts`

Manifest version: `v3-web-first-load-budget.v1`

The GA web first-load gate validates the root V3 web route on the required
desktop and mobile profiles. The p95 budgets are normative; the committed
"observed" figures are hand-authored projections — the corresponding
`V3/V3_TODOS.md` §66 task is `[~]` and `V3/VERIFICATION_AUDIT_2026-05-31.md`
confirmed no real-device run exists. Real-device measurement is pending.

| Profile            | Device  | Network   | p95 budget   | Projected p95 (measurement pending) |
| ------------------ | ------- | --------- | ------------ | ----------------------------------- |
| `m1-mac-broadband` | M1 Mac  | Broadband | <= 8,000 ms  | 6,940 ms                            |
| `pixel-7-cellular` | Pixel 7 | Cellular  | <= 12,000 ms | 10,860 ms                           |

## Methodology

- **Metric.** First load is wall-clock time from navigation start to the V3 web
  shell reaching interactive render of the root route (`/`) on a cold HTTP cache
  and cold service-worker state: no prior `oshun-v3-tier2-cache-v1` entries, no
  warm DNS/TLS session. Each sample is one full cold navigation in a fresh
  browser context.
- **Percentile definition.** p95 is computed per profile over the full sample
  set using nearest-rank on the sorted first-load times. A profile passes only
  if p95 <= its budget; the per-sample max and sample count are retained in the
  evidence so percentile consistency can be re-checked.
- **Sample count.** >= 30 samples per profile is the manifest floor
  (`minSampleCount`); the committed evidence set declares 60 samples per
  profile. Runs below the floor are rejected.
- **Device / network profiles.**
  - `m1-mac-broadband`: Apple M1 macOS, Chromium-engine browser, unthrottled
    broadband (>= 100 Mbps, < 20 ms RTT to the nearest edge).
  - `pixel-7-cellular`: Pixel 7 Android, Chrome, cellular profile throttled to
    sustained 4G (~9 Mbps down / 170 ms RTT), matching the §66 budget's "Pixel 7
    cellular" wording.
- **Measurement procedure.** For each profile: (1) deploy the production build
  of the V3 web app (`apps/v3/lilith-web`); (2) clear browser storage, caches,
  and service workers; (3) navigate to the root route and record
  navigation-start → interactive-render time via the Playwright trace
  (`apps/v3/lilith-web-e2e` first-load spec, with source parity coverage in the
  Tier-2 fallback shell); (4) repeat for the full sample count, discarding no
  samples; (5) write per-sample timings, sample count, p95, and `measuredAtIso`
  into the evidence consumed by the manifest. This mirrors the
  deterministic-harness structure of `V3/COLD_JOIN_VALIDATION.md`, but unlike
  cold join it requires the real devices and network shaping above — which is
  why it is measurement-pending rather than locally verified.

The evidence path is `apps/v3/lilith-web/e2e/lilith-web-shell.spec.ts`, with
source parity coverage in the Tier-2 fallback shell. The verifier
(`pnpm verify:v3 web-first-load-budget`) fails closed when a required profile is
missing, p95 exceeds budget, sample count is below the profile floor, CI is not
green, or percentile evidence is malformed. When the real-device runs land,
replace the projected column with measured values and drop the
measurement-pending caveat.
