A script of mine runs weekly, scans four sources and sends a ranking to Telegram. This week I pulled the raw data back and re-derived every figure in code. The counts were right — but three places confidently state something the script never measured. Here is how each one happens and how to fix it.
Defect 1: stars-per-day rewards the newest repo
The script divides stars by repo age to rank. The formula has a blind spot: it does not penalise being young. An 811-star repo at 0.82 days displays 985 stars/day — ranking above a 5,226-star repo at 5.79 days (902 stars/day). A reader sees word-atlas above aerial-tv and misreads which one is more popular.
Scale of it: 25 of the 615 repos (4%) are under a day old — exactly the group the formula rewards. The youngest repo has 43 stars and still displays 58 stars/day.
The fix: filter on a minimum age before dividing, or return two separate tables — one by raw stars, one by velocity with each repo's age shown. Do not blend two quantities with different units into a single number.
Defect 2: a “7-day” label on a window that is not 7 days
Two sources take no time-window parameter. Lobsters uses `/hottest.json` — the 25 hottest items right now — and Product Hunt uses an Atom feed of the 50 newest entries. The script calls those endpoints and stamps “in 7 days” on the result.
- Lobsters: 25 items spanning 1.1 hours to 55.4 hours — 2.3 days, not 7. The label is off by a factor of three.
- Product Hunt: 50 entries spanning 22.6 hours to 36.9 days. Only 36 of the 50 fall inside a 7-day window.
- So the Product Hunt section mixes launches from this week with launches from last month, without saying so.
The fix: take the timestamp of the oldest item and label by that, not by the parameter the script was invoked with. Or parse `published` from the feed and drop items outside the window. Dropping them is the more honest option.
Defect 3: a source lacks the field the report implies it has
Product Hunt's Atom feed carries no vote count. I checked all 50 entries: none contains a vote field. But the Product Hunt section is an ordered list — readers reasonably read that order as popularity. It is only feed order.
- Real vote counts need the Product Hunt GraphQL API, which requires a key and a quota — not the public feed.
- Until then, the honest presentation is: state “ordered by feed, not by votes”, or drop the ranking entirely.
- Similarly, the Show HN section displays both points and comments — but comments are not in the ranking formula. A 938-point, 425-comment post and a 126-point, 36-comment post are ordered by a single variable.
One more defect I found while writing the checker
Counting commits and contributors from GitHub's `Link` header, I parsed with `split("page=")`. That substring also matches `per_page=1` in the URL, so every repo returned 1 commit and 1 contributor — which reads as if every project were one person. Anchoring the regex on `[?&]page=` revealed the real numbers: aerial-tv has 268 commits and 22 contributors, harp has 2,565 commits and 171 contributors.
The common thread across all four: the digest is confident where it only *infers*, not measures. Everything I counted directly was correct; the labels, the ranking and the derived quantities were wrong. That is why I now write a `verify_numbers.py` with an assert per published figure before a post goes out — it caught all four of these.
The verified data: this week's 615 new repos and how many of them you can sell. Why GitHub stars do not measure project quality: the next post.
Sources: Lobsters hottest API, Product Hunt feed, HN Algolia API, GitHub pagination. Data as of 26 October 2026.