Skip to content
Development

Two stats, two definitions of "captured"

By Victor Da Luz•
rustsqlitedev-loggreenhouse

Greenhouse’s dashboard shows two related stats: a “Captured today” badge and a consecutive-day streak. They’re supposed to agree, and mostly they did, until you captured an idea and promoted it to an active project on the same day. Then “Captured today” would quietly flip back off, even though you’d captured something that same morning.

The bug was two functions computing the same concept two different ways. The streak function pulled every item’s created_at regardless of what status it was in now, on purpose, with a doc comment explaining that a capture day shouldn’t vanish just because the idea got promoted later. But the “captured today” count filtered for status = 'fresh_idea' only. The moment you promoted an idea, it stopped being a fresh idea, and stopped counting, even though the streak still credited the day correctly. Same underlying data, two different lenses, two different answers.

While tracing this I found a second, related question sitting unresolved in the same corner of the code: importing an existing folder from disk stamps created_at at import time and quietly fed the streak too. Import a folder full of six-month-old song ideas and Greenhouse would credit you with capturing something today. The PRD means something narrower by “captured” though, and it’s explicit: “Captured an idea today?” is about the Capture flow, the actual creative act of sitting with a new idea. Adopting a folder someone already created isn’t that.

Fixed both at once: added a column marking rows as imported vs. actually captured, and pointed both stats at the same underlying query, filtered to exclude imports. Existing rows backfill to “not imported” by default, which means old imports from before this fix still count retroactively. I decided that was fine. It’s a motivational nudge, not a ledger, and the PRD is explicit that streaks are stats, never locks.

The whole fix lived in the database layer, no UI to click through, so the verification was four new tests exercising the real production functions directly rather than a mocked render. Sometimes the right amount of ceremony for a bug is a migration and a few unit tests, not a browser.

Related reading

You might also find useful

Proton

Proton Drive

Encrypted cloud storage from the team behind Proton Mail.

As a Proton Partner, I earn from qualifying purchases of Proton's privacy and security services (Pass, Mail, VPN, Drive).

Learn more
Proton

Proton VPN

Commercial VPN with NetShield filtering and a kill switch.

As a Proton Partner, I earn from qualifying purchases of Proton's privacy and security services (Pass, Mail, VPN, Drive).

Learn more
RackNerd

RackNerd VPS

Budget VPS hosting for lightweight always-on services.

As a RackNerd affiliate, I earn from qualifying purchases.

Learn more