Problem
scripts/sync-leaderboard.js — computeRankChanges() (~lines 203-231) starts with previousRanks = {} and only populates it if getYesterdaySnapshot() returned an array. That helper (~lines 194-200) returns null on any error.
Impact (data integrity / correctness)
On any network/GitHub-API error, rate-limit, or missing commit, getYesterdaySnapshot() returns null, previousRanks stays empty, and the loop hits previousRanks[user.id] === undefined for every user → sets user.rankChange = "NEW". One transient hiccup renders the whole leaderboard as [new] for all users with no up/down deltas, and it's persisted to JSON so it sticks until the next clean run.
Suggested fix (tiny)
If previousData is null / not an array, skip rank-change computation (leave prior rankChange/"=") instead of defaulting everyone to "NEW". Optionally distinguish "snapshot unavailable" from "genuinely new user."
Would love to take this under GSSoC '26.
Problem
scripts/sync-leaderboard.js—computeRankChanges()(~lines 203-231) starts withpreviousRanks = {}and only populates it ifgetYesterdaySnapshot()returned an array. That helper (~lines 194-200) returnsnullon any error.Impact (data integrity / correctness)
On any network/GitHub-API error, rate-limit, or missing commit,
getYesterdaySnapshot()returnsnull,previousRanksstays empty, and the loop hitspreviousRanks[user.id] === undefinedfor every user → setsuser.rankChange = "NEW". One transient hiccup renders the whole leaderboard as[new]for all users with no up/down deltas, and it's persisted to JSON so it sticks until the next clean run.Suggested fix (tiny)
If
previousDatais null / not an array, skip rank-change computation (leave priorrankChange/"=") instead of defaulting everyone to"NEW". Optionally distinguish "snapshot unavailable" from "genuinely new user."Would love to take this under GSSoC '26.