_compute_from_scan(is_partial=True) evaluated against an empty unlock
set, and _run_background_scan publishes those partials to
_SNAPSHOT_CACHE every progress_every sessions. So for the duration of
every background rescan an already-earned badge rendered as locked and
unlocked_count collapsed then climbed back — the exact 39<->40 flicker
from #112273 that the finished-scan floor alone did not remove.
Read state.json for partials as well (the floor applies); partials
still never record new unlocks or save_state, since an unlock time from
half a scan could be invalidated by a later session.
Also:
- tests/plugins fake SessionDB accepts include_compacted, which the
scanner now passes (this was the red 'Python tests' check).
- engine tests patch get_hermes_home so _data_file's legacy migration
cannot copy the developer's real state.json into the temp dir.
Part of #112273