72 lines
4.7 KiB
Markdown
72 lines
4.7 KiB
Markdown
# Phase 2 — incremental service-worker asset sync
|
|
|
|
Base: `codex/phase1` at `7434f2f`; branch: `codex/phase2`.
|
|
|
|
1. Add tests first in `frontend/asset-sync-core.test.js`, extend
|
|
`frontend/sw.test.js` / `frontend/sw-update.test.js`, and deliberately extend
|
|
`frontend/shell-consistency.test.js` and `server/static-delivery.test.js`.
|
|
2. Add pure UMD `frontend/asset-sync-core.js`: exact hashed URL planning,
|
|
group-based blocking sets (everything except explicit background groups),
|
|
contract-bump blocking, verified resumable writes, capped six-way concurrency,
|
|
three retries, missing-entry checks and changed-file N-1 retention/N-2 pruning.
|
|
Register it in `frontend/assets.json`, `frontend/index.html` and the retained
|
|
legacy SHELL. Do not include unrelated shipped test/source files in downloads.
|
|
3. Integrate in `frontend/sw.js`: persistent `ytplayer-assets` utility cache,
|
|
per-build candidate manifests, atomic active-manifest promotion on activation,
|
|
verified exact lookups, plain-URL resolution, navigation/SPA index fallback,
|
|
resumable install, honest CACHE_STATUS, and quota logging. Preserve thumbnails,
|
|
fonts, share-target handling and network-only APIs. Delete legacy shell caches
|
|
only after commit and retain verified old bytes/manifest for N-1 compatibility.
|
|
4. Integrate in `frontend/sw-update.js`: a thin sync-core refresh caller,
|
|
preserved opt-in ready fast path, and playback checks immediately before
|
|
activation and every reload callback. Keep a legacy fallback for rollback.
|
|
Never change the banner rule, update outcome logic or audio/timer machinery.
|
|
5. Required server gap: inject ASSET_SYNC mode and a versioned core-module URL
|
|
into the served worker in `server/asset-manifest.js` / `server/server.js`.
|
|
Keep served worker hash headers accurate after injection. `ASSET_SYNC=0`
|
|
selects the legacy worker install/update path; test both modes. For cold
|
|
installs, share already downloaded HTTP asset bytes without accepting stale
|
|
plain responses or weakening hash verification; report remaining URL gaps.
|
|
6. Extend `perf/migration.mjs`: actual b77938a old helper, ready:true reply,
|
|
proof no refresh re-download, exactly one banner/reload, N-1 old-tab requests,
|
|
offline boot; Chromium/WebKit, with and without `perf/proxy.mjs` stalls.
|
|
Add browser checks for interrupted downloads, eviction repair and rollback.
|
|
7. Run `perf/baseline.mjs` reduced update/cold/warm/offline measurements against
|
|
`perf/results/after-phase0-2026-10-07.json`; record requested asset paths and
|
|
compressed bytes. Acceptance: JS-only change fetches JS + index + manifest;
|
|
CSS-only change <30 KB; zero font/icon update downloads; no duplicate cold
|
|
shell transfer (or explain an evidenced gap). All required unit suites green
|
|
after each implementation commit, and browser checks pass in both engines.
|
|
8. Review full diff against master §2c/§3.2/§6b; commit a ≤350-word
|
|
`plans/phase2-report.md` with hashes, measurements, gaps and iPhone checks;
|
|
write DONE02 only after completion. No push, merge, deploy or production call.
|
|
|
|
Risks: an install must not silently switch the active tab's manifest; incomplete
|
|
sync must not delete old data; exact hashes must not resolve to unrelated current
|
|
bytes; worker/page HTTP caches can duplicate font transfers; cache quota competes
|
|
with saved audio. Rollback preserves both schemes until its own commit succeeds.
|
|
|
|
## Required owner decision before implementation
|
|
|
|
The production `b77938a` helper already running in legacy tabs does not check
|
|
Player._wantsPlaying: applyUpdate sends SKIP_WAITING and schedules an unconditional
|
|
reload after four seconds. A read-only Node VM reproduction using that exact git
|
|
source with Player._wantsPlaying=true produced:
|
|
`{"wantsPlaying":true,"messages":["SKIP_WAITING"],"reloads":1}`.
|
|
A newly installed worker cannot cancel a timer in an already-running old page.
|
|
Refusing SKIP_WAITING still leaves that old timer able to reload via the old worker.
|
|
|
|
Recommended policy: enforce the playback guarantee in all upgraded clients and
|
|
require paused playback for the one-time legacy Refresh UI migration. Legacy
|
|
migration browser tests use paused playback; already-open playing tabs are never
|
|
automatically reloaded. This explicit legacy exception needs owner clarification
|
|
because the brief states the guarantee without an exception. COMMON.md requires
|
|
QUESTION and stopping for an unanswered user-visible behavior decision.
|
|
|
|
## Owner answer
|
|
|
|
Accepted: the legacy timer remains user-triggered by Refresh UI. New pages
|
|
show a playback guard with an explicit override, report PLAYING to the worker,
|
|
and the worker defers known-playing requests. Installation never calls
|
|
skipWaiting. Migration must prove no automatic legacy reload.
|