The service worker populated a new build's cache with plain addAll(),
which the browser may satisfy from its HTTP cache — and static assets
were served without Cache-Control, so Safari's heuristic caching could
hold app.js for days. Together that could install a mixed build: a
fresh index.html whose buttons reference listeners a stale app.js never
registers.
Install now fetches assets with cache: "reload", and the server marks
all static assets no-cache (revalidation is a cheap 304; fast/offline
loads are the SW cache's job anyway).