# Performance Test Report — Cycle 2

**Date**: 2026-05-12
**Cycle**: 2 (Phase B, autodev Step 15)
**Runner**: `scripts/run-performance-tests.sh --static-only`
**Toolchain**: bun 1.3.11, vite 6.4.2 (post-AZ-502 override), node 24.10
**Trigger**: pre-deploy gate after Cycle 2 Step 14 (security audit + AZ-501/AZ-502 inline fixes)

## Summary

```
Scenarios: pass 1 · warn 0 · fail 0 · unverified 9 (deferred) · quarantined 3
Verdict:   PASS — bundle size budget honored after Vite 6.4.2 upgrade
```

The only enforced metric this cycle (NFT-PERF-01, gzipped initial JS bundle ≤ 2 MB)
passes with a wide margin. All other NFT-PERF-* scenarios are runtime-observable in
Playwright; the perf-mode Playwright project (`e2e/playwright.perf.config.ts`) is not
yet wired (deferred to per-AC test tasks AZ-457..AZ-482), so they are recorded as
**Unverified** rather than failed. Three scenarios remain quarantined pending
upstream code fixes (NFT-PERF-03, NFT-PERF-08, NFT-PERF-09).

## Per-Scenario Results

| Scenario | Verdict | Measured | Threshold | Source row |
|----------|---------|----------|-----------|------------|
| NFT-PERF-01 (initial JS bundle, gzipped) | **Pass** | 290 465 B (~283.7 KB) | ≤ 2 097 152 B (2 MB) | results_report row 40 / AC-11 |
| NFT-PERF-02 (auth refresh round-trips)   | Unverified | — | exactly 1 refresh per cycle | results_report row 12 |
| NFT-PERF-03 (SSE bearer-rotation reconnect) | Quarantine | — | ≤ 5 000 ms | Step 8 hardening (SSE refresh rotation) |
| NFT-PERF-04 (live-GPS SSE open after select) | Unverified | — | ≤ 5 000 ms | results_report row 34 |
| NFT-PERF-05 (live-GPS SSE close after deselect) | Unverified | — | ≤ 1 000 ms | results_report row 35 |
| NFT-PERF-06 (annotation-status SSE unmount close) | Unverified | — | ≤ 1 000 ms | results_report row 25 |
| NFT-PERF-07 (bulk-validate UI reflect)   | Unverified | — | ≤ 2 000 ms | results_report row 37 |
| NFT-PERF-08 (panel-width persistence debounce) | Quarantine | — | exactly 1 PUT ≤ 1 000 ms | Step 4 fix (panel-width persistence) |
| NFT-PERF-09 (settings save error surfacing) | Quarantine | — | ≤ 2 000 ms | Step 4 fix (settings save error surfacing) |
| NFT-PERF-10 (FCP on /flights, edge profile) | Unverified | — | ≤ 3 000 ms | results_report row 98 |

## Bundle Size Detail (NFT-PERF-01)

Vite 6.4.2 fresh build (`bun run build` after `rm -rf dist`):

| Chunk | Raw | Gzipped |
|-------|-----|---------|
| `dist/index.html` | 0.43 KB | 0.30 KB |
| `dist/assets/index-*.css` | 53.76 KB | 13.50 KB |
| `dist/assets/index-*.js` (initial entry) | 923.12 KB | **290.45 KB** |

Headroom against the 2 MB gate: ~1.78 MB unused (~85.86% of budget).

**No bundle regression introduced by AZ-502 Vite/PostCSS upgrade** — pre- and post-upgrade
bundles measured identically at 290 465 B (cached `dist/` and freshly rebuilt `dist/` produced
the same byte total).

### Pre-existing build warnings (not introduced this cycle)

- `Some chunks are larger than 500 kB after minification` — single 923.12 KB unsplit `index-*.js` chunk. Mitigation candidates listed in build output (dynamic `import()`, `manualChunks`). Track separately if/when CI enforces a stricter chunk-size budget.
- One CSS lint note about `flex` value (compiler suggestion). Pre-existing; unrelated to AZ-502.

## Coverage Gaps

The 6 Unverified scenarios (NFT-PERF-02, -04, -05, -06, -07, -10) measure runtime UI timings
that require the Playwright perf project. Per the runner script:

> Awaiting NFT-PERF-* task implementations (AZ-457..AZ-482); until then the e2e perf
> scenarios are SKIPPED.

Recommended next step (cycle 3+): enable the perf Playwright project alongside the
existing e2e harness so these thresholds can be enforced pre-deploy.

## Outcome

**PASS — auto-chain to autodev Step 16 (Deploy)**.

No regression detected. All enforced thresholds met. Unverified scenarios are deferred
gaps tracked in the performance-tests spec, not blocking failures.
