Post-task UI refresh was scattered: every page added its own taskCompleted
listener and hard-coded which actions it cared about, so it was easy to add a
task and forget the refresh (stale UI), with no single place to see the wiring.
Adds TaskRefreshCoordinator (window.taskRefresh): one listener, with dedupe
(the SSE bus + synthetic fallbacks double-fire) and opt-in debounce (bursts
coalesce; per-task handlers run every time). Components now register a refresh
entry; window.taskRefresh.table() is the introspectable "what reloads when" map.
Migrated onto it: apps (install/uninstall/tool/config_update lifecycle +
restore/update/rebuild state), backups (backup/restore/delete), the update
badge, and the admin overview integrity badge. Gaps closed: restore/update/
rebuild now repaint app+service data. (start/stop/restart intentionally omitted —
no live status surface to refresh today; revisit if a running/stopped badge is
added. Storage reclaim/image-rm keep their own in-page refresh.)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>