Plan phase 2: Add incremental asset sync and migration verification
This commit is contained in:
64
plans/phase2-plan.md
Normal file
64
plans/phase2-plan.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user