12 KiB
Phase 6 verification
Final product under test: 4b1f520 (Phase 5 parent 21c1273). No production requests.
All historical source worktrees contain matching server and frontend revisions.
The complete diagnostic waterfalls and five-run acceptance samples are committed
under perf/results/phase6-*.json. KB in these tables means 1,000 bytes.
Cause and controlled trials
See phase6-investigation.md for the three-run tip
comparisons, adjacent-commit bisect, rejected cache/handoff prototypes and fixes.
The regressing commit is 5d6a154: LTE FCP 1,032 → 1,615 ms immediately across
that cut. Phase 2/3/5 medians are 1,044/1,646/1,736 ms. Phase 4 extraction did
not introduce the paint regression.
Representative WebKit/LTE sample 2, proxy times relative to tracking start:
phase6-before-phase5.json versus phase6-webkit-cold-2026-10-08.json (9408ee0
owned-response diagnostic, before final loader packing). Final medians follow.
| Request | Phase 5 start/end ms | Phase 6 start/end ms |
|---|---|---|
| lazy.js | 250/417 | 250/418 |
| styles.css | 251/570 | 251/570 |
| theme-classic.css | 1540/1711 | 250/421 |
| page app.js | 1524/2273 | 1552/2297 |
| first sw.js | 2337/2533 | 2367/2564 |
| worker app.js | 2903/3651 | absent |
| FCP | 1736 | 905 |
The stylesheet becomes available before the parser applies it. The worker starts after paint. Default fetch caching was already in the modern synchronizer; force-cache and a page-to-worker HTTP-cache handoff both still transferred two app bodies in WebKit. A single page-owned response, verified and cached before boot registers the worker, removes the redundant app transfer. Controlled pages and other engines retain native external scripts; no window cache/hash lookup is added to those paths. Each retained stale app requires all shell contracts to match, enforced by the worker.
Final measurements
Exact final command (120 samples: both engines, both profiles, six scenarios, five fresh samples each):
node perf/baseline.mjs --runs 5 --browser all --profile all --scenario all --assert-cold --out perf/results/phase6-final-2026-10-08.json
Final app.js positive-byte responses are exactly one in all 20 cold samples.
The earlier separate cold/regression datasets used 9408ee0 and are diagnostics,
not the final acceptance build. phase6-native-auto-priority-2026-10-08.json
combines that rejected intermediate sweep. Final core contract is 2: the final
section-rail script now owns the loader; a stale pre-packing section script would
not load app.js. No Phase 5 SHELL file was deleted. app.js and sw-update.js remain
byte-for-byte unchanged.
Actual final command output excerpts:
Chromium/LTE: run 4/5... done (653267 bytes, 115 reqs, fcp=1396ms, boot=6478ms)
Chromium/lossy: run 2/5... done (653267 bytes, 115 reqs, fcp=1972ms, boot=10292ms)
WebKit/LTE: run 2/5... done (983326 bytes, 158 reqs, fcp=905ms, boot=2335ms)
WebKit/lossy: run 2/5... done (990152 bytes, 161 reqs, fcp=2748ms, boot=5046ms)
WebKit FCP targets (≤1300/3800 ms) pass. Contemporary Phase 2 three-run medians: 1044/4045 ms; its lossy samples are 4045/3218/5297, all retained. Original baseline WebKit cold wire is 1,179,624 bytes. Final LTE/lossy wire is 983,326/990,152 bytes (16.6%/16.1% lower). The final cold set transfers app.js once in both engines.
Complete final comparison
Five-run medians. Each cell is Phase 5 → Phase 6; bytes are exact body wire bytes.
| Browser/profile | Cold requests | Cold bytes | FCP ms | LCP ms | Boot ms | Long tasks ms |
|---|---|---|---|---|---|---|
| chromium/lte | 115 → 115 | 651012 → 653267 | 1356 → 1388 | 1356 → 1388 | 7043 → 6478 | 278 → 304 |
| chromium/lossy | 115 → 115 | 651096 → 653267 | 2052 → 1976 | 2052 → 1976 | 11342 → 10314 | 295 → 297 |
| webkit/lte | 159 → 158 | 1097048 → 983326 | 1739 → 905 | 1810 → 982 | 2315 → 2335 | 0 → 0 |
| webkit/lossy | 162 → 161 | 1105402 → 990152 | 4303 → 2748 | 4371 → 2821 | 5573 → 5046 | 0 → 0 |
WebKit does not expose the Long Tasks API; its zero fields mean unmeasured.
| Browser/profile | Warm boot ms | Offline boot ms | Offline reload ms | Core update ms/bytes | CSS update ms/bytes | Feature update ms/bytes |
|---|---|---|---|---|---|---|
| chromium/lte | 410 → 418 | 185 → 188 | 202 → 206 | 745/125795 → 872/126186 | 1380/35363 → 1388/35760 | 1378/33408 → 1392/33762 |
| chromium/lossy | 403 → 442 | 189 → 194 | 204 → 207 | 747/125795 → 805/126186 | 1377/35363 → 1383/35760 | 1375/33408 → 1386/33762 |
| webkit/lte | 83 → 88 | 86 → 88 | 100 → 102 | 1890/147259 → 2015/147626 | 1455/45659 → 1467/46254 | 1455/43318 → 1380/41860 |
| webkit/lossy | 85 → 89 | 81 → 85 | 95 → 98 | 4192/147259 → 2934/147626 | 3647/43705 → 3687/44211 | 3644/41364 → 3693/41860 |
Limits and exact unmet parity targets
Strict zero regression versus the recorded Phase 5 run is NOT achieved. Chromium/LTE FCP is 1388 versus 1356 ms (+32); cold bytes 653267 versus 651012 (+2255, 0.35%); long tasks 304 versus 278 ms. The verified loader, CSP permission, contract checks and metadata add code/bytes; parser insertion also changes task boundaries. The whole timing delta has not been causally isolated. Three-run contemporary Phase 5 LTE medians were FCP 1368, boot 7090 and long tasks 294 ms. Final Chrome boot improves to 6478/10314 ms (Phase 5 7043/11342).
Warm/offline/update deltas in the complete table remain explicit. Contemporary five-run Phase 5 warm boots were Chrome 426/446 and WebKit 88/88 ms; final values 418/442 and 88/89 ms. Contemporary Phase 5 core-update times were Chrome 869/799 and WebKit 1955/2776 ms; final 872/805 and 2015/2934 ms. Metadata adds roughly 0.4 KB to core updates. Periodic lossy stalls depend on request order; timing comparisons cannot establish exact parity. The extra CPU/cache work is small, but zero cost was not proved, and the positive timing deltas are not dismissed.
Every final update passed assertChangedAssets: only app.js, theme-glass.css or presenter.js is downloaded as application code, with index/API/worker metadata; fonts/icons are not re-downloaded. Whole CSS-update wire remains above 30 KB, a pre-existing Phase 5 gap. Readiness and completion remain separately measured.
Real iPhone Safari/PWA code-cache behavior, OPFS quota pressure, forced cache eviction and uninterrupted locked-screen/background audio for 30 minutes were not verified. The historical media fixture is invalid for autoplay: these are home-launch metrics, not media-start measurements. No playback code changed. Other selected layouts may prefetch 4079 unused classic CSS bytes; that preload never applies, and the selected stylesheet retains its original cascade order.
Compatibility verification on the final product
All commands below ran on 4b1f520, build 31617662d2f0:
node perf/migration.mjs --browser all --profile unthrottled --out perf/results/phase6-migration-unthrottled-2026-10-08.json
node perf/migration.mjs --browser all --profile lossy --out perf/results/phase6-migration-lossy-2026-10-08.json
node perf/hidden-timers.mjs
node perf/lazy.mjs --browser all --out perf/results/phase6-lazy-2026-10-08.json
node perf/seams.mjs --browser all
ASSET_SYNC=0 node perf/baseline.mjs --runs 1 --browser all --profile lte --scenario offline --out perf/results/phase6-sync-rollback-2026-10-08.json
ASSET_HASHING=0 node perf/baseline.mjs --runs 1 --browser all --profile lte --scenario offline --out perf/results/phase6-hashing-rollback-2026-10-08.json
node --test frontend/*.test.js
node --test perf/measurement.test.mjs
(cd server && bun install && PATH="$PWD/../perf/.tmp/test-venv/bin:$PATH" bun run test)
Actual output excerpts:
Migration unthrottled: chromium banners=1 updateReloads=1 cachedFiles=122 userInitiatedOnly=true offline=true playbackGuard=true evictionRepair=true
Migration unthrottled: webkit banners=1 updateReloads=1 cachedFiles=122 userInitiatedOnly=true offline=true playbackGuard=true evictionRepair=true
Migration lossy: chromium durationMs=25233 banners=1 updateReloads=1 legacyURLs=21 userInitiatedOnly=true offline=true
Migration lossy: webkit durationMs=22860 banners=1 updateReloads=1 legacyURLs=21 userInitiatedOnly=true offline=true
Hidden timers: Page errors: none; Result: ALL ASSERTIONS PASSED
Lazy: chromium PASS; webkit PASS
Seams: chromium checked=[shell,presenter,remote,party,share,stats] offlineNetworkRequests=0 errors=[]
Seams: webkit checked=[shell,presenter,remote,party,share,stats] offlineNetworkRequests=0 errors=[]
Frontend: tests 223; pass 223; fail 0; skipped 0
Measurement: tests 3; pass 3; fail 0
Server: sum of per-file output: 184 pass; 0 fail
Both rollback modes launched offline with zero network in Chromium and WebKit.
The archived b77938a fixture was rebuilt by the migration script each time.
Legacy reload remains user-initiated; its pre-existing Refresh UI timer exception
is unchanged. New-page playback guards, old-client readiness, one banner, old
plain/?v=oldTag/?__ytpfresh URLs, already-open old tabs and cached offline reload
remain covered. Four expected WebKit disconnected API transport errors per
migration were recorded and matched to failed API requests; no script errors.
The seam harness's historical Phase 4 artifact was restored after saving the
new output as phase6-seams-2026-10-08.json.
Self-review re-read the complete product diff and master §§3.2/3.3/6/6b. No frontend import was added to server code; no original shell file was removed; no auto skipWaiting, live stateful re-evaluation, playback edit, push or deploy. Cache responses are exact-key checked; stale bodies under a new URL are no-store and carry no decoded transport encoding. Core contract 2 blocks loader-free N-1 packing, while same-contract app fallback and executed feature pinning remain covered by both-engine smoke. Failed quota writes never delete saved music.
Post-crash completion — 2026-10-09
Resumed from ff3f934 on codex/phase6. Commit 71608c2 clarifies the diagnostic
waterfall provenance; product code and served build 31617662d2f0 are unchanged.
The durable five-run/120-sample final measurements above were preserved.
Reinstalled Playwright browsers passed fresh compatibility checks:
node perf/migration.mjs --browser all --profile unthrottled --out perf/results/phase6-migration-unthrottled-2026-10-09.json
node perf/migration.mjs --browser all --profile lossy --out perf/results/phase6-migration-lossy-2026-10-09.json
node perf/hidden-timers.mjs
node perf/lazy.mjs --browser all --out perf/results/phase6-lazy-2026-10-09.json
node perf/seams.mjs --browser all
ASSET_SYNC=0 node perf/baseline.mjs --runs 1 --browser all --profile lte --scenario offline --out perf/results/phase6-sync-rollback-2026-10-09.json
ASSET_HASHING=0 node perf/baseline.mjs --runs 1 --browser all --profile lte --scenario offline --out perf/results/phase6-hashing-rollback-2026-10-09.json
node --test frontend/*.test.js
node --test perf/measurement.test.mjs
(cd server && bun install && PATH="$PWD/../perf/.tmp/test-venv/bin:$PATH" bun run test)
Fresh output excerpts (all commands exited successfully):
Migration unthrottled: chromium durationMs=13290; webkit durationMs=11711
Migration lossy: chromium durationMs=27355; webkit durationMs=24426
All four: banners=1 updateReloads=1 cachedFiles=122 legacyURLs=21
All four: userInitiatedOnly=true offline=true playbackGuard=true evictionRepair=true incrementalRefresh=true
Hidden timers: Page errors: none; Result: ALL ASSERTIONS PASSED
Lazy: chromium PASS; webkit PASS
Seams: chromium and webkit checked=[shell,presenter,remote,party,share,stats] offlineNetworkRequests=0 errors=[]
Both rollback flags, both engines: requestCount=0 wireBytes=0
Frontend: tests 223; pass 223; fail 0; skipped 0
Measurement: tests 3; pass 3; fail 0
Server: per-file totals 184 pass; 0 fail
The seam output is saved as phase6-seams-2026-10-09.json; the historical Phase 4 result was restored. Offline API transport errors remain distinguished from script failures. No playback or sw-update.js changes were added. bun.lock is excluded from commits.
Post-crash cold smoke command:
node perf/baseline.mjs --runs 1 --browser webkit --profile all --scenario cold --assert-cold --out perf/results/phase6-cold-smoke-2026-10-09.json
LTE/lossy FCP was 1253/2881 ms, wire 983326/990152 bytes; both samples passed exactly one positive-byte app.js response. These single-run rechecks do not replace the durable five-run medians.