Follow-up to v1.8.7
What's fixed
v1.8.7 patched the delayed EvaluateAllProfiles startup pass, but missed the synchronous Load() path inside AchievementBadgeService's constructor. That Load path was also calling EvaluateBadges(profile, userId) with default arguments (silent: false, unlockTimestamp: utcNow) — so every badge that got re-evaluated during plugin load fired webhook + audit + toast.
This was the true origin of the update-toast cascade.
The fix
Load() now passes silent: true + DateTimeOffset.UnixEpoch, matching the trick v1.8.7 applied to the delayed pass. Any unlocks happening during profile load are stamped with 1970, so they can never pass the client's since cutoff and replay as toasts.
About the "data reset" reports
No counter data is actually being wiped on update. Atomic writes + the 3-layer recovery chain (primary → .bak → .recovery) remain untouched. SyncDefinitions only adds definitions; EvaluateBadges only increments counters.
The perceived "reset" was the cascade of old unlocks re-toasting, which made it look like achievements were being re-earned.
With v1.8.7 + v1.8.8 together, the cascade should be fully eliminated.