Problem
frontend/js/user/badges.js (~lines 36-81) recomputes a "streak" by walking the last 8 recorded history entries and incrementing whenever total[j] - total[j-1] >= 1, with no calendar-day validation.
Impact (correctness)
History entries only exist for days a sync actually ran, so gaps are normal. A user active on 8 non-consecutive recorded days (which can span weeks) earns HOT_STREAK, titled "Solved ≥1 problem every day for 7 days." HARD_CARRY (~lines 75-81) has the same flaw over its 7-entry window regardless of calendar span. The code also ignores the backend streak object that fetch-user-info.js already returns.
Suggested fix (small)
Validate consecutive calendar days between adjacent entries (mirror the diffDays === 1 logic in scripts/backfill-streaks.js:30-38), or drive the badge from the backend data.streak field.
Related to #360/#196 (wiring the streak card to backend), but this is a distinct mis-count in the badge logic itself.
Happy to fix under GSSoC '26 if assigned.
Problem
frontend/js/user/badges.js(~lines 36-81) recomputes a "streak" by walking the last 8 recorded history entries and incrementing whenevertotal[j] - total[j-1] >= 1, with no calendar-day validation.Impact (correctness)
History entries only exist for days a sync actually ran, so gaps are normal. A user active on 8 non-consecutive recorded days (which can span weeks) earns HOT_STREAK, titled "Solved ≥1 problem every day for 7 days." HARD_CARRY (~lines 75-81) has the same flaw over its 7-entry window regardless of calendar span. The code also ignores the backend
streakobject thatfetch-user-info.jsalready returns.Suggested fix (small)
Validate consecutive calendar days between adjacent entries (mirror the
diffDays === 1logic inscripts/backfill-streaks.js:30-38), or drive the badge from the backenddata.streakfield.Related to #360/#196 (wiring the streak card to backend), but this is a distinct mis-count in the badge logic itself.
Happy to fix under GSSoC '26 if assigned.