What to fix: Chrome on the installed PWA repeatedly shows the "review
app icon update" prompt; accepting it doesn't stop it, and the before/after
icons in the dialog look identical. Diagnosis: web/manifest.json declares
each icon with "purpose": "any maskable". Chrome processes the maskable
variant for the launcher, and its app-identity check then keeps flagging a
mismatch against the served file — dual-purpose entries are a documented
anti-pattern for exactly this loop. The icons themselves are fine: they are
drawn with content inside the maskable safe zone (scripts/make_icons.py),
so the same PNGs can serve both purposes as separate entries.
Prescription: manifest-only. Replace each dual-purpose entry with two
entries — one "purpose": "any", one "purpose": "maskable" — at both 192
and 512 (four entries over the two existing PNGs), and add an explicit
"id": "/" to pin app identity. Do not bump the SW cache name: the
shell is network-first, so the fresh manifest reaches clients on the next
online load. Icon PNG bytes unchanged; make_icons.py untouched.
Blocked by: None — independent of the 01–08 dependency order.
Status: ready-for-agent
manifest.json: every icon entry declares exactly one purpose; both
any and maskable are covered at 192 and 512; "id" is present
web/manifest.json and asserts those invariants plusthat every referenced icon file exists
icon-192.png / icon-512.png bytes unchanged; no SW cache-name bumplegitimate review prompt on the phone, then none over the following week