Root cause of "watch history delete does not work at all": the removal paths
call watchHistoryService.snapshot(remaining, …), but snapshot published via
updateWatchHistoryList WITHOUT replace:true. The default merges incoming items
with the existing cached list, so the just-removed item was merged straight back
and the deletion silently had no effect. Removing the LAST item was worse: an
empty list fell through to republishing the pending queue instead of clearing.
- snapshot now honors options.replace: forwards it to updateWatchHistoryList,
treats an explicit empty replace as a clear (publishes empty instead of
short-circuiting or falling back to the queue), and skips the cached-items
merge when replacing. Adds (the default) keep merge semantics.
- Both removal call sites (watchHistoryController.handleWatchHistoryRemoval and
historyView.defaultRemoveHandler) now pass replace:true.
Tests (snapshot at the updateWatchHistoryList boundary): removing an item
publishes the remaining list with replace:true; removing the last item publishes
an empty replace (not a queue republish / no-op); a normal watch-tracking
snapshot still merges (replace not forced). Mutation-verified — dropping the
replace forwarding fails 2 cases and reverting the empty-clear handling fails the
clear case.
Build + full lint green.
Co-Authored-By: Claude Opus 4.8 <[email protected]>