- Replace BigInt hammingDistance with 32-bit popcount — safer (no throw
on malformed hashes) and ~10× faster
- Make scan() async with setImmediate chunking so the event loop stays
responsive on large libraries
- Batch getGroups() photo lookup in slices of 900 to stay under SQLite's
999-variable limit
- Add POST /api/duplicates/keep-best endpoint: scores by resolution then
filesize, soft-deletes the losers, dismisses the pair
- DuplicateGroup: green "Keep" badge on the best photo, green "Keep best"
button in footer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>